Skip to content

Commit 228cdd2

Browse files
authored
Merge pull request #162 from erkanyildiz/master
For 20.04.1
2 parents ae42d43 + 1fab2f6 commit 228cdd2

21 files changed

+666
-60
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
## 20.04.1
2+
- Added Application Performance Monitoring (Phase 1)
3+
- Manual network traces
4+
- Manual custom traces
5+
- Semi-automatic app start time trace
6+
- Automatic app foreground time trace
7+
- Automatic app background time trace
8+
- Consent handling for Application Performance Monitoring
9+
- Added `COUNTLY_EXCLUDE_PUSHNOTIFICATIONS` flag to disable push notifications altogether in order to avoid App Store Connect warnings (thanks @grundleborg)
10+
- Fixed an incorrect internal logging on SDK start
11+
- Fixed location consent order to avoid some legacy Countly Server issue with location info being unavailable even after giving consent
12+
- Improved `UIApplicationWillTerminateNotification` behaviour
13+
- Prevented recording empty string as `city`, `ISOCountryCode` and `IP` for location info
14+
- Applied `alwaysUsePOST` flag to feedback widget check requests
15+
- Applied `alwaysUsePOST` flag to remote config requests
16+
17+
- Other various improvements
18+
- Deleted some unnecessary imports
19+
- Updated HeaderDocs, internal logs, inline notes and pragma marks
20+
- Added missing frameworks to CocoaPods podspec
21+
- Added ability to override SDK name and version for bridge SDKs
22+
23+
24+
125
## 20.04
226
- Added crash reporting feature for tvOS
327
- Added crash reporting feature for macOS

Countly.h

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
6060

6161
/**
6262
* Flushes request and event queues.
63-
* @discussion Flushes persistenly stored request queue and events recorded but not converted to a request so far.
63+
* @discussion Flushes persistently stored request queue and events recorded but not converted to a request so far.
6464
* @discussion Started timed events will not be affected.
6565
*/
6666
- (void)flushQueues;
@@ -202,7 +202,7 @@ NS_ASSUME_NONNULL_BEGIN
202202
* Records event with given key and segmentation.
203203
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
204204
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
205-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
205+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
206206
* @param key Event key, a non-zero length valid string
207207
* @param segmentation Segmentation key-value pairs of event
208208
*/
@@ -212,7 +212,7 @@ NS_ASSUME_NONNULL_BEGIN
212212
* Records event with given key, segmentation and count.
213213
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
214214
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
215-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
215+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
216216
* @param key Event key, a non-zero length valid string
217217
* @param segmentation Segmentation key-value pairs of event
218218
* @param count Count of event occurrences
@@ -223,7 +223,7 @@ NS_ASSUME_NONNULL_BEGIN
223223
* Records event with given key, segmentation, count and sum.
224224
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
225225
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
226-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
226+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
227227
* @param key Event key, a non-zero length valid string
228228
* @param segmentation Segmentation key-value pairs of event
229229
* @param count Count of event occurrences
@@ -235,7 +235,7 @@ NS_ASSUME_NONNULL_BEGIN
235235
* Records event with given key, segmentation, count, sum and duration.
236236
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
237237
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
238-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
238+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
239239
* @param key Event key, a non-zero length valid string
240240
* @param segmentation Segmentation key-value pairs of event
241241
* @param count Count of event occurrences
@@ -263,7 +263,7 @@ NS_ASSUME_NONNULL_BEGIN
263263
* @discussion Trying to end an event with already ended (or not yet started) key will have no effect.
264264
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
265265
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
266-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
266+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
267267
* @param key Event key, a non-zero length valid string
268268
* @param segmentation Segmentation key-value pairs of event
269269
* @param count Count of event occurrences
@@ -282,6 +282,7 @@ NS_ASSUME_NONNULL_BEGIN
282282

283283
#pragma mark - Push Notification
284284
#if (TARGET_OS_IOS || TARGET_OS_OSX)
285+
#ifndef COUNTLY_EXCLUDE_PUSHNOTIFICATIONS
285286
/**
286287
* Shows default system dialog that asks for user's permission to display notifications.
287288
* @discussion A unified convenience method that handles asking for notification permission on both iOS10 and older iOS versions with badge, sound and alert notification types.
@@ -321,6 +322,7 @@ NS_ASSUME_NONNULL_BEGIN
321322
*/
322323
- (void)clearPushNotificationToken;
323324
#endif
325+
#endif
324326

325327

326328

@@ -355,7 +357,7 @@ NS_ASSUME_NONNULL_BEGIN
355357
- (void)recordIP:(NSString *)IP;
356358

357359
/**
358-
* Disables geo-location based push notifications by clearing all exsisting location info.
360+
* Disables geo-location based push notifications by clearing all existing location info.
359361
* @discussion Once disabled, geo-location based push notifications can be enabled again by calling @c recordLocation: or @c recordCity:andISOCountryCode: or @c recordIP: method.
360362
*/
361363
- (void)disableLocationInfo;
@@ -400,7 +402,7 @@ NS_ASSUME_NONNULL_BEGIN
400402

401403
/**
402404
* @c crashLog: method is deprecated. Please use @c recordCrashLog: method instead.
403-
* @discussion Be advised, parameter type chenged to plain @c NSString from string format, for better Swift compatibility.
405+
* @discussion Be advised, parameter type changed to plain @c NSString from string format, for better Swift compatibility.
404406
* @discussion Calling this method will have no effect.
405407
*/
406408
- (void)crashLog:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) DEPRECATED_MSG_ATTRIBUTE("Use 'recordCrashLog:' method instead!");
@@ -419,12 +421,12 @@ NS_ASSUME_NONNULL_BEGIN
419421

420422
/**
421423
* Records a visited view with given name and custom segmentation.
422-
* @discussion This is an extendened version of @c recordView: method.
424+
* @discussion This is an extended version of @c recordView: method.
423425
* @discussion If segmentation has any of Countly reserved keys, they will be ignored:
424426
* @discussion @c name, @c segment, @c visit, @c start, @c bounce, @c exit, @c view, @c domain, @c dur
425427
* @discussion Segmentation should be an @c NSDictionary, with keys and values are both @c NSString's only.
426428
* @discussion Custom objects in segmentation will cause events not to be sent to Countly Server.
427-
* @discussion Nested values in segmentation will be ignored by Counly Server event segmentation section.
429+
* @discussion Nested values in segmentation will be ignored by Countly Server event segmentation section.
428430
* @param viewName Name of the view visited, a non-zero length valid string
429431
* @param segmentation Custom segmentation key-value pairs
430432
*/
@@ -558,6 +560,64 @@ NS_ASSUME_NONNULL_BEGIN
558560
*/
559561
- (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(void (^)(NSError * error))completionHandler;
560562

563+
564+
565+
#pragma mark - Performance Monitoring
566+
567+
/**
568+
* Manually records a network trace for performance monitoring.
569+
* @discussion A network trace is a collection of measured information about a network request.
570+
* @discussion When a network request is completed, a network trace can be recorded manually to be analyzed in Performance Monitoring feature.
571+
* @discussion Trace name needs to be a non-zero length string, otherwise it is ignored.
572+
* @param traceName Trace name, a non-zero length valid string
573+
* @param requestPayloadSize Size of the request's payload in bytes
574+
* @param responsePayloadSize Size of the received response's payload in bytes
575+
* @param responseStatusCode HTTP status code of the received response
576+
* @param startTime UNIX time stamp in milliseconds for the starting time of the request
577+
* @param endTime UNIX time stamp in milliseconds for the ending time of the request
578+
*/
579+
- (void)recordNetworkTrace:(NSString *)traceName requestPayloadSize:(NSInteger)requestPayloadSize responsePayloadSize:(NSInteger)responsePayloadSize responseStatusCode:(NSInteger)responseStatusCode startTime:(long long)startTime endTime:(long long)endTime;
580+
581+
/**
582+
* Starts a performance monitoring custom trace with given name to be ended later.
583+
* @discussion Duration of custom trace will be calculated on ending.
584+
* @discussion Trying to start a custom trace with already started name will have no effect.
585+
* @param traceName Trace name, a non-zero length valid string
586+
*/
587+
- (void)startCustomTrace:(NSString *)traceName;
588+
589+
/**
590+
* Ends a previously started performance monitoring custom trace with given name and metrics.
591+
* @discussion Trying to end a custom trace with already ended (or not yet started) name will have no effect.
592+
* @param traceName Trace name, a non-zero length valid string
593+
* @param metrics Metrics key-value pairs
594+
*/
595+
- (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary * _Nullable)metrics;
596+
597+
/**
598+
* Cancels a previously started performance monitoring custom trace with given name.
599+
* @discussion Trying to cancel a custom trace with already cancelled (or ended or not yet started) name will have no effect.
600+
* @param traceName Trace name, a non-zero length valid string
601+
*/
602+
- (void)cancelCustomTrace:(NSString *)traceName;
603+
604+
/**
605+
* Clears all previously started performance monitoring custom traces.
606+
* @discussion All previously started performance monitoring custom traces are automatically cleaned when:
607+
* @discussion - Consent for @c CLYConsentPerformanceMonitoring is cancelled
608+
* @discussion - A new app key is set using @c setNewAppKey: method
609+
*/
610+
- (void)clearAllCustomTraces;
611+
612+
/**
613+
* Calculates and records app launch time for performance monitoring.
614+
* @discussion This method should be called when the app is loaded and displayed its first user facing view successfully.
615+
* @discussion e.g. @c viewDidAppear: method of the root view controller or whatever place is suitable for the app's flow.
616+
* @discussion Time passed since the app started to launch will be automatically calculated and recorded for performance monitoring.
617+
* @discussion App launch time can be recorded only once per app launch. So, second and following calls to this method will be ignored.
618+
*/
619+
- (void)appLoadingFinished;
620+
561621
NS_ASSUME_NONNULL_END
562622

563623
@end

Countly.m

100755100644
Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@ @interface Countly ()
1515
}
1616
@end
1717

18+
long long appLoadStartTime;
19+
1820
@implementation Countly
1921

22+
+ (void)load
23+
{
24+
[super load];
25+
26+
appLoadStartTime = floor(NSDate.date.timeIntervalSince1970 * 1000);
27+
}
28+
2029
+ (instancetype)sharedInstance
2130
{
2231
static Countly *s_sharedCountly = nil;
@@ -57,7 +66,7 @@ - (instancetype)init
5766

5867
- (void)startWithConfig:(CountlyConfig *)config
5968
{
60-
if (CountlyCommon.sharedInstance.hasStarted)
69+
if (CountlyCommon.sharedInstance.hasStarted_)
6170
return;
6271

6372
CountlyCommon.sharedInstance.hasStarted = YES;
@@ -70,7 +79,7 @@ - (void)startWithConfig:(CountlyConfig *)config
7079
if (!config.host.length || [config.host isEqualToString:@"https://YOUR_COUNTLY_SERVER"])
7180
[NSException raise:@"CountlyHostNotSetException" format:@"host property on CountlyConfig object is not set"];
7281

73-
COUNTLY_LOG(@"Initializing with %@ SDK v%@", kCountlySDKName, kCountlySDKVersion);
82+
COUNTLY_LOG(@"Initializing with %@ SDK v%@", CountlyCommon.sharedInstance.SDKName, CountlyCommon.sharedInstance.SDKVersion);
7483

7584
if (!CountlyDeviceInfo.sharedInstance.deviceID || config.resetStoredDeviceID)
7685
[CountlyDeviceInfo.sharedInstance initializeDeviceID:config.deviceID];
@@ -110,6 +119,7 @@ - (void)startWithConfig:(CountlyConfig *)config
110119
#endif
111120

112121
#if (TARGET_OS_IOS || TARGET_OS_OSX)
122+
#ifndef COUNTLY_EXCLUDE_PUSHNOTIFICATIONS
113123
if ([config.features containsObject:CLYPushNotifications])
114124
{
115125
CountlyPushNotifications.sharedInstance.isEnabledOnInitialConfig = YES;
@@ -119,6 +129,7 @@ - (void)startWithConfig:(CountlyConfig *)config
119129
CountlyPushNotifications.sharedInstance.launchNotification = config.launchNotification;
120130
[CountlyPushNotifications.sharedInstance startPushNotifications];
121131
}
132+
#endif
122133
#endif
123134

124135
CountlyCrashReporter.sharedInstance.crashSegmentation = config.crashSegmentation;
@@ -152,6 +163,9 @@ - (void)startWithConfig:(CountlyConfig *)config
152163
CountlyRemoteConfig.sharedInstance.isEnabledOnInitialConfig = config.enableRemoteConfig;
153164
CountlyRemoteConfig.sharedInstance.remoteConfigCompletionHandler = config.remoteConfigCompletionHandler;
154165
[CountlyRemoteConfig.sharedInstance startRemoteConfig];
166+
167+
CountlyPerformanceMonitoring.sharedInstance.isEnabledOnInitialConfig = config.enablePerformanceMonitoring;
168+
[CountlyPerformanceMonitoring.sharedInstance startPerformanceMonitoring];
155169

156170
[CountlyCommon.sharedInstance observeDeviceOrientationChanges];
157171

@@ -225,6 +239,8 @@ - (void)setNewAppKey:(NSString *)newAppKey
225239

226240
[self suspend];
227241

242+
[CountlyPerformanceMonitoring.sharedInstance clearAllCustomTraces];
243+
228244
CountlyConnectionManager.sharedInstance.appKey = newAppKey;
229245

230246
[self resume];
@@ -339,9 +355,15 @@ - (void)willTerminateCallBack:(NSNotification *)notification
339355
{
340356
COUNTLY_LOG(@"App will terminate.");
341357

358+
CountlyConnectionManager.sharedInstance.isTerminating = YES;
359+
342360
[CountlyViewTracking.sharedInstance endView];
343361

344-
[self suspend];
362+
[CountlyConnectionManager.sharedInstance sendEvents];
363+
364+
[CountlyPerformanceMonitoring.sharedInstance endBackgroundTrace];
365+
366+
[CountlyPersistency.sharedInstance saveToFileSync];
345367
}
346368

347369
- (void)dealloc
@@ -543,6 +565,7 @@ - (void)cancelEvent:(NSString *)key
543565

544566
#pragma mark - Push Notifications
545567
#if (TARGET_OS_IOS || TARGET_OS_OSX)
568+
#ifndef COUNTLY_EXCLUDE_PUSHNOTIFICATIONS
546569

547570
- (void)askForNotificationPermission
548571
{
@@ -569,6 +592,7 @@ - (void)clearPushNotificationToken
569592
[CountlyPushNotifications.sharedInstance clearToken];
570593
}
571594
#endif
595+
#endif
572596

573597

574598

@@ -581,11 +605,17 @@ - (void)recordLocation:(CLLocationCoordinate2D)location
581605

582606
- (void)recordCity:(NSString *)city andISOCountryCode:(NSString *)ISOCountryCode
583607
{
608+
if (!city.length && !ISOCountryCode.length)
609+
return;
610+
584611
[CountlyLocationManager.sharedInstance recordLocationInfo:kCLLocationCoordinate2DInvalid city:city ISOCountryCode:ISOCountryCode andIP:nil];
585612
}
586613

587614
- (void)recordIP:(NSString *)IP
588615
{
616+
if (!IP.length)
617+
return;
618+
589619
[CountlyLocationManager.sharedInstance recordLocationInfo:kCLLocationCoordinate2DInvalid city:nil ISOCountryCode:nil andIP:IP];
590620
}
591621

@@ -720,4 +750,39 @@ - (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(v
720750
}
721751

722752

753+
754+
#pragma mark - Performance Monitoring
755+
756+
- (void)recordNetworkTrace:(NSString *)traceName requestPayloadSize:(NSInteger)requestPayloadSize responsePayloadSize:(NSInteger)responsePayloadSize responseStatusCode:(NSInteger)responseStatusCode startTime:(long long)startTime endTime:(long long)endTime
757+
{
758+
[CountlyPerformanceMonitoring.sharedInstance recordNetworkTrace:traceName requestPayloadSize:requestPayloadSize responsePayloadSize:responsePayloadSize responseStatusCode:responseStatusCode startTime:startTime endTime:endTime];
759+
}
760+
761+
- (void)startCustomTrace:(NSString *)traceName
762+
{
763+
[CountlyPerformanceMonitoring.sharedInstance startCustomTrace:traceName];
764+
}
765+
766+
- (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary * _Nullable)metrics
767+
{
768+
[CountlyPerformanceMonitoring.sharedInstance endCustomTrace:traceName metrics:metrics];
769+
}
770+
771+
- (void)cancelCustomTrace:(NSString *)traceName
772+
{
773+
[CountlyPerformanceMonitoring.sharedInstance cancelCustomTrace:traceName];
774+
}
775+
776+
- (void)clearAllCustomTraces
777+
{
778+
[CountlyPerformanceMonitoring.sharedInstance clearAllCustomTraces];
779+
}
780+
781+
- (void)appLoadingFinished
782+
{
783+
long long appLoadEndTime = floor(NSDate.date.timeIntervalSince1970 * 1000);
784+
785+
[CountlyPerformanceMonitoring.sharedInstance recordAppStartDurationTraceWithStartTime:appLoadStartTime endTime:appLoadEndTime];
786+
}
787+
723788
@end

Countly.podspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'Countly'
3-
s.version = '20.04'
3+
s.version = '20.04.1'
44
s.license = { :type => 'MIT', :file => 'LICENSE.md' }
55
s.summary = 'Countly is an innovative, real-time, open source mobile analytics platform.'
66
s.homepage = 'https://github.com/Countly/countly-sdk-ios'
@@ -19,6 +19,7 @@ Pod::Spec.new do |s|
1919
core.source_files = '*.{h,m}'
2020
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h'
2121
core.preserve_path = 'countly_dsym_uploader.sh'
22+
core.ios.frameworks = ['Foundation', 'UIKit', 'UserNotifications', 'CoreLocation', 'WebKit', 'CoreTelephony', 'AdSupport', 'WatchConnectivity']
2223
end
2324

2425
s.subspec 'NotificationService' do |ns|

0 commit comments

Comments
 (0)