Skip to content

Commit 885ddd9

Browse files
authored
Move the dispatch of gauge metric calls to its dedicated thread asynchronously (#7601)
1 parent 0fcf354 commit 885ddd9

File tree

4 files changed

+28
-21
lines changed

4 files changed

+28
-21
lines changed

FirebasePerformance/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Deprecate Clearcut event transport mechanism.
33
* Enable dynamic framework support. (#7569)
44
* Remove the warning to include Firebase Analytics as Perf does not depend on Analytics (#7487)
5+
* Fix the crash on gauge manager due to race condition. (#7535)
56

67
# Version 7.7.0
78
* Add community supported tvOS.

FirebasePerformance/Sources/Gauges/FPRGaugeManager+Private.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242

4343
/**
4444
* Prepares for dispatching the current set of gauge data to Google Data Transport.
45+
*
46+
* @param sessionId SessionId that will be used for dispatching the gauge data
4547
*/
46-
- (void)prepareAndDispatchGaugeData;
48+
- (void)prepareAndDispatchCollectedGaugeDataWithSessionId:(nullable NSString *)sessionId;
4749

4850
@end

FirebasePerformance/Sources/Gauges/FPRGaugeManager.m

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ @interface FPRGaugeManager () <FPRCPUGaugeCollectorDelegate, FPRMemoryGaugeColle
3737
@property(nonatomic) NSMutableArray *gaugeData;
3838

3939
/** @brief Currently active sessionID. */
40-
@property(nonatomic, readwrite) NSString *currentSessionId;
40+
@property(nonatomic, readwrite, copy) NSString *currentSessionId;
4141

4242
@end
4343

@@ -117,7 +117,8 @@ - (BOOL)gaugeCollectionEnabled {
117117
}
118118

119119
- (void)startCollectingGauges:(FPRGauges)gauges forSessionId:(NSString *)sessionId {
120-
[self prepareAndDispatchGaugeData];
120+
// Dispatch the already available gauge data with old sessionId.
121+
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
121122

122123
self.currentSessionId = sessionId;
123124
if (self.gaugeCollectionEnabled) {
@@ -143,7 +144,8 @@ - (void)stopCollectingGauges:(FPRGauges)gauges {
143144

144145
self.activeGauges = self.activeGauges & ~(gauges);
145146

146-
[self prepareAndDispatchGaugeData];
147+
// Flush out all the already collected gauge metrics
148+
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
147149
}
148150

149151
- (void)collectAllGauges {
@@ -172,31 +174,33 @@ - (void)dispatchMetric:(id)gaugeMetric {
172174

173175
#pragma mark - Utils
174176

175-
- (void)prepareAndDispatchGaugeData {
176-
NSArray *currentBatch = self.gaugeData;
177-
NSString *currentSessionId = self.currentSessionId;
178-
self.gaugeData = [[NSMutableArray alloc] init];
179-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
180-
if (currentBatch.count > 0) {
181-
[[FPRClient sharedInstance] logGaugeMetric:currentBatch forSessionId:currentSessionId];
182-
FPRLogDebug(kFPRGaugeManagerDataCollected, @"Logging %lu gauge metrics.",
183-
(unsigned long)currentBatch.count);
184-
}
177+
- (void)prepareAndDispatchCollectedGaugeDataWithSessionId:(nullable NSString *)sessionId {
178+
dispatch_async(self.gaugeDataProtectionQueue, ^{
179+
NSArray *dispatchGauges = [self.gaugeData copy];
180+
self.gaugeData = [[NSMutableArray alloc] init];
181+
182+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
183+
if (dispatchGauges.count > 0 && sessionId != nil) {
184+
[[FPRClient sharedInstance] logGaugeMetric:dispatchGauges forSessionId:sessionId];
185+
FPRLogDebug(kFPRGaugeManagerDataCollected, @"Logging %lu gauge metrics.",
186+
(unsigned long)dispatchGauges.count);
187+
}
188+
});
185189
});
186190
}
187191

188192
/**
189193
* Adds the gauge to the batch and decide on when to dispatch the events to Google Data Transport.
190194
*
191-
* @param gaugeData Gauge data received from the collectors.
195+
* @param gauge Gauge data received from the collectors.
192196
*/
193-
- (void)addGaugeData:(id)gaugeData {
197+
- (void)addGaugeData:(id)gauge {
194198
dispatch_async(self.gaugeDataProtectionQueue, ^{
195-
if (gaugeData) {
196-
[self.gaugeData addObject:gaugeData];
199+
if (gauge) {
200+
[self.gaugeData addObject:gauge];
197201

198202
if (self.gaugeData.count >= kGaugeDataBatchSize) {
199-
[self prepareAndDispatchGaugeData];
203+
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
200204
}
201205
}
202206
});

FirebasePerformance/Tests/Unit/Gauges/FPRGaugeManagerTests.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ - (void)testCollectAllGauges {
154154
- (void)testBatchingOfGaugeEvents {
155155
FPRGaugeManager *manager = [FPRGaugeManager sharedInstance];
156156
id mock = [OCMockObject partialMockForObject:manager];
157-
OCMExpect([mock prepareAndDispatchGaugeData]).andDo(nil);
157+
OCMExpect([mock prepareAndDispatchCollectedGaugeDataWithSessionId:@"abc"]).andDo(nil);
158158
[manager startCollectingGauges:FPRGaugeCPU forSessionId:@"abc"];
159159
[manager.cpuGaugeCollector stopCollecting];
160160
for (int i = 0; i < kGaugeDataBatchSize; i++) {
@@ -172,7 +172,7 @@ - (void)testBatchingOfGaugeEventsDoesNotHappenLessThanBatchSize {
172172
id mock = [OCMockObject partialMockForObject:manager];
173173
[manager startCollectingGauges:FPRGaugeCPU forSessionId:@"abc"];
174174
[manager.cpuGaugeCollector stopCollecting];
175-
OCMReject([mock prepareAndDispatchGaugeData]);
175+
OCMReject([mock prepareAndDispatchCollectedGaugeDataWithSessionId:@"abc"]);
176176
for (int i = 0; i < kGaugeDataBatchSize - 1; i++) {
177177
[manager.cpuGaugeCollector collectMetric];
178178
}

0 commit comments

Comments
 (0)