/** * Copyright (c) 2016-present Invertase Limited & Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this library except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #import #import #import #import "RNFBPerfModule.h" static __strong NSMutableDictionary *traces; static __strong NSMutableDictionary *httpMetrics; @implementation RNFBPerfModule #pragma mark - #pragma mark Module Setup RCT_EXPORT_MODULE(); - (instancetype)init { self = [super init]; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ traces = [[NSMutableDictionary alloc] init]; httpMetrics = [[NSMutableDictionary alloc] init]; }); return self; } - (void)dealloc { @synchronized ([self class]) { for (NSString *key in traces) { [traces removeObjectForKey:key]; } for (NSString *key in httpMetrics) { [httpMetrics removeObjectForKey:key]; } } } - (NSDictionary *)constantsToExport { NSMutableDictionary *constants = [NSMutableDictionary new]; constants[@"isPerformanceCollectionEnabled"] = @([RCTConvert BOOL:@([FIRPerformance sharedInstance].dataCollectionEnabled)]); return constants; } + (BOOL)requiresMainQueueSetup { return NO; } #pragma mark - #pragma mark Firebase Perf Methods RCT_EXPORT_METHOD(setPerformanceCollectionEnabled: (BOOL) enabled resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { [FIRPerformance sharedInstance].dataCollectionEnabled = (BOOL) enabled; [FIRPerformance sharedInstance].instrumentationEnabled = (BOOL) enabled; resolve([NSNull null]); } RCT_EXPORT_METHOD(startTrace: (nonnull NSNumber *) id identifier: (NSString *) identifier resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { FIRTrace *trace = [[FIRPerformance sharedInstance] traceWithName:identifier]; [trace start]; @synchronized ([self class]) { traces[id] = trace; } resolve([NSNull null]); } RCT_EXPORT_METHOD(stopTrace: (nonnull NSNumber *) id traceData: (NSDictionary *) traceData resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { FIRTrace *trace; @synchronized ([self class]) { trace = traces[id]; } NSDictionary *metrics = traceData[@"metrics"]; NSDictionary *attributes = traceData[@"attributes"]; [metrics enumerateKeysAndObjectsUsingBlock:^(NSString *metricName, NSNumber *value, BOOL *stop) { [trace setIntValue:[value longLongValue] forMetric:metricName]; }]; [attributes enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSString *value, BOOL *stop) { [trace setValue:value forAttribute:attributeName]; }]; [trace stop]; @synchronized ([self class]) { [traces removeObjectForKey:id]; } resolve([NSNull null]); } RCT_EXPORT_METHOD(startHttpMetric: (nonnull NSNumber *) id url: (NSString *) url httpMethod: (NSString *) httpMethod resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { FIRHTTPMethod method = FIRHTTPMethodGET; NSURL *toNSURL = [NSURL URLWithString:url]; if ([httpMethod compare:@"put" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodPUT; if ([httpMethod compare:@"post" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodPUT; if ([httpMethod compare:@"head" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodHEAD; if ([httpMethod compare:@"trace" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodTRACE; if ([httpMethod compare:@"patch" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodPATCH; if ([httpMethod compare:@"delete" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodDELETE; if ([httpMethod compare:@"options" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodOPTIONS; if ([httpMethod compare:@"connect" options:NSCaseInsensitiveSearch] == NSOrderedSame) method = FIRHTTPMethodCONNECT; FIRHTTPMetric *httpMetric = [[FIRHTTPMetric alloc] initWithURL:toNSURL HTTPMethod:method]; [httpMetric start]; @synchronized ([self class]) { httpMetrics[id] = httpMetric; } resolve([NSNull null]); } RCT_EXPORT_METHOD(stopHttpMetric: (nonnull NSNumber *) id metricData: (NSDictionary *) metricData resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { FIRHTTPMetric *httpMetric; @synchronized ([self class]) { httpMetric = httpMetrics[id]; } NSDictionary *attributes = metricData[@"attributes"]; [attributes enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSString *value, BOOL *stop) { [httpMetric setValue:value forAttribute:attributeName]; }]; if (metricData[@"httpResponseCode"]) { NSNumber *responseCode = (NSNumber *) metricData[@"httpResponseCode"]; [httpMetric setResponseCode:[responseCode integerValue]]; } if (metricData[@"requestPayloadSize"]) { NSNumber *requestPayloadSize = (NSNumber *) metricData[@"requestPayloadSize"]; [httpMetric setRequestPayloadSize:[requestPayloadSize longValue]]; } if (metricData[@"responsePayloadSize"]) { NSNumber *responsePayloadSize = (NSNumber *) metricData[@"responsePayloadSize"]; [httpMetric setResponsePayloadSize:[responsePayloadSize longValue]]; } if (metricData[@"responseContentType"]) { NSString *responseContentType = (NSString *) metricData[@"responseContentType"]; [httpMetric setResponseContentType:responseContentType]; } [httpMetric stop]; @synchronized ([self class]) { [httpMetrics removeObjectForKey:id]; } resolve([NSNull null]); } @end