FIRPerformance.m 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2020 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
  15. #import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
  16. #import "FirebasePerformance/Sources/FIRPerformance_Private.h"
  17. #import "FirebasePerformance/Sources/Common/FPRConstants.h"
  18. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
  19. #import "FirebasePerformance/Sources/FPRClient+Private.h"
  20. #import "FirebasePerformance/Sources/FPRClient.h"
  21. #import "FirebasePerformance/Sources/FPRConsoleLogger.h"
  22. #import "FirebasePerformance/Sources/FPRDataUtils.h"
  23. #import "FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h"
  24. #import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
  25. static NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf";
  26. @implementation FIRPerformance
  27. #pragma mark - Public methods
  28. + (instancetype)sharedInstance {
  29. static FIRPerformance *firebasePerformance = nil;
  30. static dispatch_once_t onceToken;
  31. dispatch_once(&onceToken, ^{
  32. firebasePerformance = [[FIRPerformance alloc] init];
  33. });
  34. return firebasePerformance;
  35. }
  36. + (FIRTrace *)startTraceWithName:(NSString *)name {
  37. FIRTrace *trace = [[self sharedInstance] traceWithName:name];
  38. [trace start];
  39. return trace;
  40. }
  41. - (FIRTrace *)traceWithName:(NSString *)name {
  42. if (![self isPerfConfigured]) {
  43. FPRLogError(kFPRTraceNotCreated, @"Failed creating trace %@. Firebase is not configured.",
  44. name);
  45. [NSException raise:kFirebasePerfErrorDomain
  46. format:@"The default Firebase app has not yet been configured. Add [FirebaseApp "
  47. @"configure] to your application initialization."];
  48. return nil;
  49. }
  50. FIRTrace *trace = [[FIRTrace alloc] initWithName:name];
  51. return trace;
  52. }
  53. /**
  54. * Checks if the SDK has been successfully configured.
  55. *
  56. * @return YES if SDK is configured successfully, otherwise NO.
  57. */
  58. - (BOOL)isPerfConfigured {
  59. return self.fprClient.isConfigured;
  60. }
  61. #pragma mark - Internal methods
  62. - (instancetype)init {
  63. self = [super init];
  64. if (self) {
  65. _customAttributes = [[NSMutableDictionary<NSString *, NSString *> alloc] init];
  66. _customAttributesSerialQueue =
  67. dispatch_queue_create("com.google.perf.customAttributes", DISPATCH_QUEUE_SERIAL);
  68. _fprClient = [FPRClient sharedInstance];
  69. }
  70. return self;
  71. }
  72. - (BOOL)isDataCollectionEnabled {
  73. return [FPRConfigurations sharedInstance].isDataCollectionEnabled;
  74. }
  75. - (void)setDataCollectionEnabled:(BOOL)dataCollectionEnabled {
  76. BOOL performanceDataCollectionEnabled = self.dataCollectionEnabled;
  77. if (performanceDataCollectionEnabled != dataCollectionEnabled) {
  78. [[FPRConfigurations sharedInstance] setDataCollectionEnabled:dataCollectionEnabled];
  79. }
  80. }
  81. - (BOOL)isInstrumentationEnabled {
  82. return self.fprClient.isSwizzled || [FPRConfigurations sharedInstance].isInstrumentationEnabled;
  83. }
  84. - (void)setInstrumentationEnabled:(BOOL)instrumentationEnabled {
  85. [[FPRConfigurations sharedInstance] setInstrumentationEnabled:instrumentationEnabled];
  86. if (instrumentationEnabled) {
  87. [self.fprClient checkAndStartInstrumentation];
  88. } else {
  89. if (self.fprClient.isSwizzled) {
  90. FPRLogError(kFPRInstrumentationDisabledAfterConfigure,
  91. @"Failed to disable instrumentation because Firebase Performance has already "
  92. @"been configured. It will be disabled when the app restarts.");
  93. }
  94. }
  95. }
  96. #pragma mark - Custom attributes related methods
  97. - (NSDictionary<NSString *, NSString *> *)attributes {
  98. return [self.customAttributes copy];
  99. }
  100. - (void)setValue:(NSString *)value forAttribute:(nonnull NSString *)attribute {
  101. NSString *validatedName = FPRReservableAttributeName(attribute);
  102. NSString *validatedValue = FPRValidatedAttributeValue(value);
  103. BOOL canAddAttribute = YES;
  104. if (validatedName == nil) {
  105. FPRLogError(kFPRAttributeNoName,
  106. @"Failed to initialize because of a nil or zero length attribute name.");
  107. canAddAttribute = NO;
  108. }
  109. if (validatedValue == nil) {
  110. FPRLogError(kFPRAttributeNoValue,
  111. @"Failed to initialize because of a nil or zero length attribute value.");
  112. canAddAttribute = NO;
  113. }
  114. if (self.customAttributes.allKeys.count >= kFPRMaxGlobalCustomAttributesCount) {
  115. FPRLogError(kFPRMaxAttributesReached,
  116. @"Only %d attributes allowed. Already reached maximum attribute count.",
  117. kFPRMaxGlobalCustomAttributesCount);
  118. canAddAttribute = NO;
  119. }
  120. if (canAddAttribute) {
  121. // Ensure concurrency during update of attributes.
  122. dispatch_sync(self.customAttributesSerialQueue, ^{
  123. self.customAttributes[validatedName] = validatedValue;
  124. });
  125. }
  126. }
  127. - (NSString *)valueForAttribute:(NSString *)attribute {
  128. // TODO(b/175053654): Should this be happening on the serial queue for thread safety?
  129. return self.customAttributes[attribute];
  130. }
  131. - (void)removeAttribute:(NSString *)attribute {
  132. [self.customAttributes removeObjectForKey:attribute];
  133. }
  134. @end