1 |
efrain |
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 |
|
|
|
15 |
#import <UIKit/UIKit.h>
|
|
|
16 |
|
|
|
17 |
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
|
|
18 |
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
|
|
|
19 |
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
|
|
20 |
|
|
|
21 |
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h"
|
|
|
22 |
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
|
|
23 |
|
|
|
24 |
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
|
|
|
25 |
|
|
|
26 |
FPRConfigName kFPRConfigDataCollectionEnabled = @"dataCollectionEnabled";
|
|
|
27 |
|
|
|
28 |
FPRConfigName kFPRConfigInstrumentationEnabled = @"instrumentationEnabled";
|
|
|
29 |
|
|
|
30 |
NSString *const kFPRConfigInstrumentationUserPreference =
|
|
|
31 |
@"com.firebase.performanceInsrumentationEnabled";
|
|
|
32 |
NSString *const kFPRConfigInstrumentationPlistKey = @"firebase_performance_instrumentation_enabled";
|
|
|
33 |
|
|
|
34 |
NSString *const kFPRConfigCollectionUserPreference = @"com.firebase.performanceCollectionEnabled";
|
|
|
35 |
NSString *const kFPRConfigCollectionPlistKey = @"firebase_performance_collection_enabled";
|
|
|
36 |
|
|
|
37 |
NSString *const kFPRDiagnosticsUserPreference = @"FPRDiagnosticsLocal";
|
|
|
38 |
NSString *const kFPRDiagnosticsEnabledPlistKey = @"FPRDiagnosticsLocal";
|
|
|
39 |
|
|
|
40 |
NSString *const kFPRConfigCollectionDeactivationPlistKey =
|
|
|
41 |
@"firebase_performance_collection_deactivated";
|
|
|
42 |
|
|
|
43 |
NSString *const kFPRConfigLogSource = @"com.firebase.performanceLogSource";
|
|
|
44 |
|
|
|
45 |
@implementation FPRConfigurations
|
|
|
46 |
|
|
|
47 |
static dispatch_once_t gSharedInstanceToken;
|
|
|
48 |
|
|
|
49 |
+ (instancetype)sharedInstance {
|
|
|
50 |
static FPRConfigurations *instance = nil;
|
|
|
51 |
dispatch_once(&gSharedInstanceToken, ^{
|
|
|
52 |
FPRConfigurationSource sources = FPRConfigurationSourceRemoteConfig;
|
|
|
53 |
instance = [[FPRConfigurations alloc] initWithSources:sources];
|
|
|
54 |
});
|
|
|
55 |
return instance;
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
+ (void)reset {
|
|
|
59 |
// TODO(b/120032990): Reset the singletons that this singleton uses.
|
|
|
60 |
gSharedInstanceToken = 0;
|
|
|
61 |
[[NSUserDefaults standardUserDefaults]
|
|
|
62 |
removeObjectForKey:kFPRConfigInstrumentationUserPreference];
|
|
|
63 |
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kFPRConfigCollectionUserPreference];
|
|
|
64 |
}
|
|
|
65 |
|
|
|
66 |
- (instancetype)initWithSources:(FPRConfigurationSource)source {
|
|
|
67 |
self = [super init];
|
|
|
68 |
if (self) {
|
|
|
69 |
_sources = source;
|
|
|
70 |
[self setupRemoteConfigFlags];
|
|
|
71 |
|
|
|
72 |
// Register for notifications to update configs.
|
|
|
73 |
[self registerForNotifications];
|
|
|
74 |
|
|
|
75 |
self.FIRAppClass = [FIRApp class];
|
|
|
76 |
self.userDefaults = [NSUserDefaults standardUserDefaults];
|
|
|
77 |
self.infoDictionary = [NSBundle mainBundle].infoDictionary;
|
|
|
78 |
self.mainBundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
|
|
|
79 |
self.updateQueue = dispatch_queue_create("com.google.perf.configUpdate", DISPATCH_QUEUE_SERIAL);
|
|
|
80 |
}
|
|
|
81 |
|
|
|
82 |
return self;
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
- (void)registerForNotifications {
|
|
|
86 |
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
87 |
selector:@selector(update)
|
|
|
88 |
name:UIApplicationDidBecomeActiveNotification
|
|
|
89 |
object:nil];
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
/** Searches the main bundle and the bundle from bundleForClass: info dictionaries for the key and
|
|
|
93 |
* returns the first result.
|
|
|
94 |
*
|
|
|
95 |
* @param key The key to search the info dictionaries for.
|
|
|
96 |
* @return The first object found in the info dictionary of the main bundle and bundleForClass:.
|
|
|
97 |
*/
|
|
|
98 |
- (nullable id)objectForInfoDictionaryKey:(NSString *)key {
|
|
|
99 |
// If the config infoDictionary has been set to a new dictionary, only use the original dictionary
|
|
|
100 |
// instead of the new dictionary.
|
|
|
101 |
if (self.infoDictionary != [NSBundle mainBundle].infoDictionary) {
|
|
|
102 |
return self.infoDictionary[key]; // nullable.
|
|
|
103 |
}
|
|
|
104 |
NSArray<NSBundle *> *bundles = @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ];
|
|
|
105 |
for (NSBundle *bundle in bundles) {
|
|
|
106 |
id object = [bundle objectForInfoDictionaryKey:key];
|
|
|
107 |
if (object) {
|
|
|
108 |
return object; // nonnull.
|
|
|
109 |
}
|
|
|
110 |
}
|
|
|
111 |
return nil;
|
|
|
112 |
}
|
|
|
113 |
|
|
|
114 |
- (void)update {
|
|
|
115 |
dispatch_async(self.updateQueue, ^{
|
|
|
116 |
if (!self.remoteConfigFlags) {
|
|
|
117 |
[self setupRemoteConfigFlags];
|
|
|
118 |
}
|
|
|
119 |
[self.remoteConfigFlags update];
|
|
|
120 |
});
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
/**
|
|
|
124 |
* Sets up the remote config flags instance based on 3 different factors:
|
|
|
125 |
* 1. Is the firebase app configured?
|
|
|
126 |
* 2. Is the remote config source enabled?
|
|
|
127 |
* 3. If the Remote Config flags instance exists already?
|
|
|
128 |
*/
|
|
|
129 |
- (void)setupRemoteConfigFlags {
|
|
|
130 |
if (!self.remoteConfigFlags && [self.FIRAppClass isDefaultAppConfigured] &&
|
|
|
131 |
(self.sources & FPRConfigurationSourceRemoteConfig) == FPRConfigurationSourceRemoteConfig) {
|
|
|
132 |
self.remoteConfigFlags = [FPRRemoteConfigFlags sharedInstance];
|
|
|
133 |
}
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
#pragma mark - Overridden Properties
|
|
|
137 |
|
|
|
138 |
- (void)setDataCollectionEnabled:(BOOL)dataCollectionEnabled {
|
|
|
139 |
[self.userDefaults setBool:dataCollectionEnabled forKey:kFPRConfigCollectionUserPreference];
|
|
|
140 |
}
|
|
|
141 |
|
|
|
142 |
// The data collection flag is determined by this order:
|
|
|
143 |
// 1. A plist flag for permanently disabling data collection
|
|
|
144 |
// 2. The runtime flag (NSUserDefaults)
|
|
|
145 |
// 3. A plist flag for enabling/disabling (overrideable)
|
|
|
146 |
// 4. The global data collection switch from Core.
|
|
|
147 |
- (BOOL)isDataCollectionEnabled {
|
|
|
148 |
/**
|
|
|
149 |
* Perf only works with the default app, so validate it exists then use the value from the global
|
|
|
150 |
* data collection from the default app as the base value if no other values are set.
|
|
|
151 |
*/
|
|
|
152 |
if (![self.FIRAppClass isDefaultAppConfigured]) {
|
|
|
153 |
return NO;
|
|
|
154 |
}
|
|
|
155 |
|
|
|
156 |
BOOL dataCollectionPreference = [self.FIRAppClass defaultApp].isDataCollectionDefaultEnabled;
|
|
|
157 |
|
|
|
158 |
// Check if data collection is permanently disabled by plist. If so, disable data collection.
|
|
|
159 |
id dataCollectionDeactivationObject =
|
|
|
160 |
[self objectForInfoDictionaryKey:kFPRConfigCollectionDeactivationPlistKey];
|
|
|
161 |
if (dataCollectionDeactivationObject) {
|
|
|
162 |
BOOL dataCollectionDeactivated = [dataCollectionDeactivationObject boolValue];
|
|
|
163 |
if (dataCollectionDeactivated) {
|
|
|
164 |
return NO;
|
|
|
165 |
}
|
|
|
166 |
}
|
|
|
167 |
/**
|
|
|
168 |
* Check if the performance collection preference key is available in NSUserDefaults.
|
|
|
169 |
* If it exists - Just honor that and return that value.
|
|
|
170 |
* If it does not exist - Check if firebase_performance_collection_enabled exists in Info.plist.
|
|
|
171 |
* If it exists - honor that and return that value.
|
|
|
172 |
* If not - return YES stating performance collection is enabled.
|
|
|
173 |
*/
|
|
|
174 |
id dataCollectionPreferenceObject =
|
|
|
175 |
[self.userDefaults objectForKey:kFPRConfigCollectionUserPreference];
|
|
|
176 |
if (dataCollectionPreferenceObject) {
|
|
|
177 |
dataCollectionPreference = [dataCollectionPreferenceObject boolValue];
|
|
|
178 |
} else {
|
|
|
179 |
dataCollectionPreferenceObject = [self objectForInfoDictionaryKey:kFPRConfigCollectionPlistKey];
|
|
|
180 |
if (dataCollectionPreferenceObject) {
|
|
|
181 |
dataCollectionPreference = [dataCollectionPreferenceObject boolValue];
|
|
|
182 |
}
|
|
|
183 |
}
|
|
|
184 |
|
|
|
185 |
return dataCollectionPreference;
|
|
|
186 |
}
|
|
|
187 |
|
|
|
188 |
- (void)setInstrumentationEnabled:(BOOL)instrumentationEnabled {
|
|
|
189 |
[self.userDefaults setBool:instrumentationEnabled forKey:kFPRConfigInstrumentationUserPreference];
|
|
|
190 |
}
|
|
|
191 |
|
|
|
192 |
- (BOOL)isInstrumentationEnabled {
|
|
|
193 |
BOOL instrumentationPreference = YES;
|
|
|
194 |
|
|
|
195 |
id instrumentationPreferenceObject =
|
|
|
196 |
[self.userDefaults objectForKey:kFPRConfigInstrumentationUserPreference];
|
|
|
197 |
|
|
|
198 |
/**
|
|
|
199 |
* Check if the performance instrumentation preference key is available in NSUserDefaults.
|
|
|
200 |
* If it exists - Just honor that and return that value.
|
|
|
201 |
* If not - Check if firebase_performance_instrumentation_enabled exists in Info.plist.
|
|
|
202 |
* If it exists - honor that and return that value.
|
|
|
203 |
* If not - return YES stating performance instrumentation is enabled.
|
|
|
204 |
*/
|
|
|
205 |
if (instrumentationPreferenceObject) {
|
|
|
206 |
instrumentationPreference = [instrumentationPreferenceObject boolValue];
|
|
|
207 |
} else {
|
|
|
208 |
instrumentationPreferenceObject =
|
|
|
209 |
[self objectForInfoDictionaryKey:kFPRConfigInstrumentationPlistKey];
|
|
|
210 |
if (instrumentationPreferenceObject) {
|
|
|
211 |
instrumentationPreference = [instrumentationPreferenceObject boolValue];
|
|
|
212 |
}
|
|
|
213 |
}
|
|
|
214 |
|
|
|
215 |
return instrumentationPreference;
|
|
|
216 |
}
|
|
|
217 |
|
|
|
218 |
#pragma mark - Fireperf SDK configurations.
|
|
|
219 |
|
|
|
220 |
- (BOOL)sdkEnabled {
|
|
|
221 |
BOOL enabled = YES;
|
|
|
222 |
if (self.remoteConfigFlags) {
|
|
|
223 |
enabled = [self.remoteConfigFlags performanceSDKEnabledWithDefaultValue:enabled];
|
|
|
224 |
}
|
|
|
225 |
|
|
|
226 |
// Check if the current version is one of the disabled versions.
|
|
|
227 |
if ([[self sdkDisabledVersions] containsObject:[NSString stringWithUTF8String:kFPRSDKVersion]]) {
|
|
|
228 |
enabled = NO;
|
|
|
229 |
}
|
|
|
230 |
|
|
|
231 |
// If there is a plist override, honor that value.
|
|
|
232 |
// NOTE: PList override should ideally be used only for tests and not for production.
|
|
|
233 |
id plistObject = [self objectForInfoDictionaryKey:@"firebase_performance_sdk_enabled"];
|
|
|
234 |
if (plistObject) {
|
|
|
235 |
enabled = [plistObject boolValue];
|
|
|
236 |
}
|
|
|
237 |
|
|
|
238 |
return enabled;
|
|
|
239 |
}
|
|
|
240 |
|
|
|
241 |
- (BOOL)diagnosticsEnabled {
|
|
|
242 |
BOOL enabled = NO;
|
|
|
243 |
|
|
|
244 |
/**
|
|
|
245 |
* Check if the diagnostics preference key is available in NSUserDefaults.
|
|
|
246 |
* If it exists - Just honor that and return that value.
|
|
|
247 |
* If not - Check if firebase_performance_instrumentation_enabled exists in Info.plist.
|
|
|
248 |
* If it exists - honor that and return that value.
|
|
|
249 |
* If not - return NO stating diagnostics is disabled.
|
|
|
250 |
*/
|
|
|
251 |
id diagnosticsEnabledPreferenceObject =
|
|
|
252 |
[self.userDefaults objectForKey:kFPRDiagnosticsUserPreference];
|
|
|
253 |
|
|
|
254 |
if (diagnosticsEnabledPreferenceObject) {
|
|
|
255 |
enabled = [diagnosticsEnabledPreferenceObject boolValue];
|
|
|
256 |
} else {
|
|
|
257 |
id diagnosticsEnabledObject = [self objectForInfoDictionaryKey:kFPRDiagnosticsEnabledPlistKey];
|
|
|
258 |
if (diagnosticsEnabledObject) {
|
|
|
259 |
enabled = [diagnosticsEnabledObject boolValue];
|
|
|
260 |
}
|
|
|
261 |
}
|
|
|
262 |
|
|
|
263 |
return enabled;
|
|
|
264 |
}
|
|
|
265 |
|
|
|
266 |
- (NSSet<NSString *> *)sdkDisabledVersions {
|
|
|
267 |
NSMutableSet<NSString *> *disabledVersions = [[NSMutableSet<NSString *> alloc] init];
|
|
|
268 |
|
|
|
269 |
if (self.remoteConfigFlags) {
|
|
|
270 |
NSSet<NSString *> *sdkDisabledVersions =
|
|
|
271 |
[self.remoteConfigFlags sdkDisabledVersionsWithDefaultValue:[disabledVersions copy]];
|
|
|
272 |
if (sdkDisabledVersions.count > 0) {
|
|
|
273 |
[disabledVersions addObjectsFromArray:[sdkDisabledVersions allObjects]];
|
|
|
274 |
}
|
|
|
275 |
}
|
|
|
276 |
|
|
|
277 |
return [disabledVersions copy];
|
|
|
278 |
}
|
|
|
279 |
|
|
|
280 |
- (int)logSource {
|
|
|
281 |
/**
|
|
|
282 |
* Order of preference of returning the log source.
|
|
|
283 |
* If it is an autopush build (based on environment variable), always return
|
|
|
284 |
* LogRequest_LogSource_FireperfAutopush (461). If there is a recent value of remote config fetch,
|
|
|
285 |
* honor that value. If logSource cached value (NSUserDefaults value) exists, honor that. Fallback
|
|
|
286 |
* to the default value LogRequest_LogSource_Fireperf (462).
|
|
|
287 |
*/
|
|
|
288 |
int logSource = 462;
|
|
|
289 |
|
|
|
290 |
NSDictionary<NSString *, NSString *> *environment = [NSProcessInfo processInfo].environment;
|
|
|
291 |
if (environment[@"FPR_AUTOPUSH_ENV"] != nil &&
|
|
|
292 |
[environment[@"FPR_AUTOPUSH_ENV"] isEqualToString:@"1"]) {
|
|
|
293 |
logSource = 461;
|
|
|
294 |
} else {
|
|
|
295 |
if (self.remoteConfigFlags) {
|
|
|
296 |
logSource = [self.remoteConfigFlags logSourceWithDefaultValue:462];
|
|
|
297 |
}
|
|
|
298 |
}
|
|
|
299 |
|
|
|
300 |
return logSource;
|
|
|
301 |
}
|
|
|
302 |
|
|
|
303 |
- (PrewarmDetectionMode)prewarmDetectionMode {
|
|
|
304 |
PrewarmDetectionMode mode = PrewarmDetectionModeActivePrewarm;
|
|
|
305 |
if (self.remoteConfigFlags) {
|
|
|
306 |
mode = [self.remoteConfigFlags getIntValueForFlag:@"fpr_prewarm_detection"
|
|
|
307 |
defaultValue:(int)mode];
|
|
|
308 |
}
|
|
|
309 |
return mode;
|
|
|
310 |
}
|
|
|
311 |
|
|
|
312 |
#pragma mark - Log sampling configurations.
|
|
|
313 |
|
|
|
314 |
- (float)logTraceSamplingRate {
|
|
|
315 |
float samplingRate = 1.0f;
|
|
|
316 |
if (self.remoteConfigFlags) {
|
|
|
317 |
float rcSamplingRate = [self.remoteConfigFlags traceSamplingRateWithDefaultValue:samplingRate];
|
|
|
318 |
if (rcSamplingRate >= 0) {
|
|
|
319 |
samplingRate = rcSamplingRate;
|
|
|
320 |
}
|
|
|
321 |
}
|
|
|
322 |
return samplingRate;
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
- (float)logNetworkSamplingRate {
|
|
|
326 |
float samplingRate = 1.0f;
|
|
|
327 |
if (self.remoteConfigFlags) {
|
|
|
328 |
float rcSamplingRate =
|
|
|
329 |
[self.remoteConfigFlags networkRequestSamplingRateWithDefaultValue:samplingRate];
|
|
|
330 |
if (rcSamplingRate >= 0) {
|
|
|
331 |
samplingRate = rcSamplingRate;
|
|
|
332 |
}
|
|
|
333 |
}
|
|
|
334 |
return samplingRate;
|
|
|
335 |
}
|
|
|
336 |
|
|
|
337 |
#pragma mark - Traces rate limiting configurations.
|
|
|
338 |
|
|
|
339 |
- (uint32_t)foregroundEventCount {
|
|
|
340 |
uint32_t eventCount = 300;
|
|
|
341 |
if (self.remoteConfigFlags) {
|
|
|
342 |
eventCount =
|
|
|
343 |
[self.remoteConfigFlags rateLimitTraceCountInForegroundWithDefaultValue:eventCount];
|
|
|
344 |
}
|
|
|
345 |
return eventCount;
|
|
|
346 |
}
|
|
|
347 |
|
|
|
348 |
- (uint32_t)foregroundEventTimeLimit {
|
|
|
349 |
uint32_t timeLimit = 600;
|
|
|
350 |
if (self.remoteConfigFlags) {
|
|
|
351 |
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
|
|
352 |
}
|
|
|
353 |
|
|
|
354 |
uint32_t timeLimitInMinutes = timeLimit / 60;
|
|
|
355 |
return timeLimitInMinutes;
|
|
|
356 |
}
|
|
|
357 |
|
|
|
358 |
- (uint32_t)backgroundEventCount {
|
|
|
359 |
uint32_t eventCount = 30;
|
|
|
360 |
if (self.remoteConfigFlags) {
|
|
|
361 |
eventCount =
|
|
|
362 |
[self.remoteConfigFlags rateLimitTraceCountInBackgroundWithDefaultValue:eventCount];
|
|
|
363 |
}
|
|
|
364 |
return eventCount;
|
|
|
365 |
}
|
|
|
366 |
|
|
|
367 |
- (uint32_t)backgroundEventTimeLimit {
|
|
|
368 |
uint32_t timeLimit = 600;
|
|
|
369 |
if (self.remoteConfigFlags) {
|
|
|
370 |
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
|
|
371 |
}
|
|
|
372 |
|
|
|
373 |
uint32_t timeLimitInMinutes = timeLimit / 60;
|
|
|
374 |
return timeLimitInMinutes;
|
|
|
375 |
}
|
|
|
376 |
|
|
|
377 |
#pragma mark - Network requests rate limiting configurations.
|
|
|
378 |
|
|
|
379 |
- (uint32_t)foregroundNetworkEventCount {
|
|
|
380 |
uint32_t eventCount = 700;
|
|
|
381 |
if (self.remoteConfigFlags) {
|
|
|
382 |
eventCount = [self.remoteConfigFlags
|
|
|
383 |
rateLimitNetworkRequestCountInForegroundWithDefaultValue:eventCount];
|
|
|
384 |
}
|
|
|
385 |
return eventCount;
|
|
|
386 |
}
|
|
|
387 |
|
|
|
388 |
- (uint32_t)foregroundNetworkEventTimeLimit {
|
|
|
389 |
uint32_t timeLimit = 600;
|
|
|
390 |
if (self.remoteConfigFlags) {
|
|
|
391 |
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
|
|
392 |
}
|
|
|
393 |
|
|
|
394 |
uint32_t timeLimitInMinutes = timeLimit / 60;
|
|
|
395 |
return timeLimitInMinutes;
|
|
|
396 |
}
|
|
|
397 |
|
|
|
398 |
- (uint32_t)backgroundNetworkEventCount {
|
|
|
399 |
uint32_t eventCount = 70;
|
|
|
400 |
if (self.remoteConfigFlags) {
|
|
|
401 |
eventCount = [self.remoteConfigFlags
|
|
|
402 |
rateLimitNetworkRequestCountInBackgroundWithDefaultValue:eventCount];
|
|
|
403 |
}
|
|
|
404 |
return eventCount;
|
|
|
405 |
}
|
|
|
406 |
|
|
|
407 |
- (uint32_t)backgroundNetworkEventTimeLimit {
|
|
|
408 |
uint32_t timeLimit = 600;
|
|
|
409 |
if (self.remoteConfigFlags) {
|
|
|
410 |
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
|
|
411 |
}
|
|
|
412 |
|
|
|
413 |
uint32_t timeLimitInMinutes = timeLimit / 60;
|
|
|
414 |
return timeLimitInMinutes;
|
|
|
415 |
}
|
|
|
416 |
|
|
|
417 |
#pragma mark - Sessions feature related configurations.
|
|
|
418 |
|
|
|
419 |
- (float_t)sessionsSamplingPercentage {
|
|
|
420 |
float samplingPercentage = 1.0f; // One Percent.
|
|
|
421 |
if (self.remoteConfigFlags) {
|
|
|
422 |
float rcSamplingRate =
|
|
|
423 |
[self.remoteConfigFlags sessionSamplingRateWithDefaultValue:(samplingPercentage / 100)];
|
|
|
424 |
if (rcSamplingRate >= 0) {
|
|
|
425 |
samplingPercentage = rcSamplingRate * 100;
|
|
|
426 |
}
|
|
|
427 |
}
|
|
|
428 |
|
|
|
429 |
id plistObject = [self objectForInfoDictionaryKey:@"sessionsSamplingPercentage"];
|
|
|
430 |
if (plistObject) {
|
|
|
431 |
samplingPercentage = [plistObject floatValue];
|
|
|
432 |
}
|
|
|
433 |
return samplingPercentage;
|
|
|
434 |
}
|
|
|
435 |
|
|
|
436 |
- (uint32_t)maxSessionLengthInMinutes {
|
|
|
437 |
uint32_t sessionLengthInMinutes = 240;
|
|
|
438 |
if (self.remoteConfigFlags) {
|
|
|
439 |
sessionLengthInMinutes =
|
|
|
440 |
[self.remoteConfigFlags sessionMaxDurationWithDefaultValue:sessionLengthInMinutes];
|
|
|
441 |
}
|
|
|
442 |
|
|
|
443 |
// If the session max length gets set to 0, default it to 240 minutes.
|
|
|
444 |
if (sessionLengthInMinutes == 0) {
|
|
|
445 |
return 240;
|
|
|
446 |
}
|
|
|
447 |
return sessionLengthInMinutes;
|
|
|
448 |
}
|
|
|
449 |
|
|
|
450 |
- (uint32_t)cpuSamplingFrequencyInForegroundInMS {
|
|
|
451 |
uint32_t samplingFrequency = 100;
|
|
|
452 |
if (self.remoteConfigFlags) {
|
|
|
453 |
samplingFrequency = [self.remoteConfigFlags
|
|
|
454 |
sessionGaugeCPUCaptureFrequencyInForegroundWithDefaultValue:samplingFrequency];
|
|
|
455 |
}
|
|
|
456 |
return samplingFrequency;
|
|
|
457 |
}
|
|
|
458 |
|
|
|
459 |
- (uint32_t)cpuSamplingFrequencyInBackgroundInMS {
|
|
|
460 |
uint32_t samplingFrequency = 0;
|
|
|
461 |
if (self.remoteConfigFlags) {
|
|
|
462 |
samplingFrequency = [self.remoteConfigFlags
|
|
|
463 |
sessionGaugeCPUCaptureFrequencyInBackgroundWithDefaultValue:samplingFrequency];
|
|
|
464 |
}
|
|
|
465 |
return samplingFrequency;
|
|
|
466 |
}
|
|
|
467 |
|
|
|
468 |
- (uint32_t)memorySamplingFrequencyInForegroundInMS {
|
|
|
469 |
uint32_t samplingFrequency = 100;
|
|
|
470 |
if (self.remoteConfigFlags) {
|
|
|
471 |
samplingFrequency = [self.remoteConfigFlags
|
|
|
472 |
sessionGaugeMemoryCaptureFrequencyInForegroundWithDefaultValue:samplingFrequency];
|
|
|
473 |
}
|
|
|
474 |
return samplingFrequency;
|
|
|
475 |
}
|
|
|
476 |
|
|
|
477 |
- (uint32_t)memorySamplingFrequencyInBackgroundInMS {
|
|
|
478 |
uint32_t samplingFrequency = 0;
|
|
|
479 |
if (self.remoteConfigFlags) {
|
|
|
480 |
samplingFrequency = [self.remoteConfigFlags
|
|
|
481 |
sessionGaugeMemoryCaptureFrequencyInBackgroundWithDefaultValue:samplingFrequency];
|
|
|
482 |
}
|
|
|
483 |
return samplingFrequency;
|
|
|
484 |
}
|
|
|
485 |
|
|
|
486 |
@end
|