FIRPerformance.m 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 "
  47. @"`FirebaseApp.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. [[FPRConfigurations sharedInstance] setDataCollectionEnabled:dataCollectionEnabled];
  77. }
  78. - (BOOL)isInstrumentationEnabled {
  79. return self.fprClient.isSwizzled || [FPRConfigurations sharedInstance].isInstrumentationEnabled;
  80. }
  81. - (void)setInstrumentationEnabled:(BOOL)instrumentationEnabled {
  82. [[FPRConfigurations sharedInstance] setInstrumentationEnabled:instrumentationEnabled];
  83. if (instrumentationEnabled) {
  84. [self.fprClient checkAndStartInstrumentation];
  85. } else {
  86. if (self.fprClient.isSwizzled) {
  87. FPRLogError(kFPRInstrumentationDisabledAfterConfigure,
  88. @"Failed to disable instrumentation because Firebase Performance has already "
  89. @"been configured. It will be disabled when the app restarts.");
  90. }
  91. }
  92. }
  93. #pragma mark - Custom attributes related methods
  94. - (NSDictionary<NSString *, NSString *> *)attributes {
  95. return [self.customAttributes copy];
  96. }
  97. - (void)setValue:(NSString *)value forAttribute:(nonnull NSString *)attribute {
  98. NSString *validatedName = FPRReservableAttributeName(attribute);
  99. NSString *validatedValue = FPRValidatedAttributeValue(value);
  100. BOOL canAddAttribute = YES;
  101. if (validatedName == nil) {
  102. FPRLogError(kFPRAttributeNoName,
  103. @"Failed to initialize because of a nil or zero length attribute name.");
  104. canAddAttribute = NO;
  105. }
  106. if (validatedValue == nil) {
  107. FPRLogError(kFPRAttributeNoValue,
  108. @"Failed to initialize because of a nil or zero length attribute value.");
  109. canAddAttribute = NO;
  110. }
  111. if (self.customAttributes.allKeys.count >= kFPRMaxGlobalCustomAttributesCount) {
  112. FPRLogError(kFPRMaxAttributesReached,
  113. @"Only %d attributes allowed. Already reached maximum attribute count.",
  114. kFPRMaxGlobalCustomAttributesCount);
  115. canAddAttribute = NO;
  116. }
  117. if (canAddAttribute) {
  118. // Ensure concurrency during update of attributes.
  119. dispatch_sync(self.customAttributesSerialQueue, ^{
  120. self.customAttributes[validatedName] = validatedValue;
  121. });
  122. }
  123. }
  124. - (NSString *)valueForAttribute:(NSString *)attribute {
  125. // TODO(b/175053654): Should this be happening on the serial queue for thread safety?
  126. return self.customAttributes[attribute];
  127. }
  128. - (void)removeAttribute:(NSString *)attribute {
  129. [self.customAttributes removeObjectForKey:attribute];
  130. }
  131. @end