Skip to content

Commit

Permalink
Merge pull request #1022 from OneSignal/track_cold_restarts
Browse files Browse the repository at this point in the history
Track cold restarts with track endpoint
  • Loading branch information
emawby committed Nov 29, 2021
2 parents fc53bf2 + 6f5f945 commit fd06483
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
24 changes: 24 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/OneSignal.m
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,7 @@ + (BOOL)isRegisterUserSuccessful {
return _registerUserSuccessful || isOnSessionSuccessfulForCurrentState;
}

static BOOL _trackedColdRestart = false;
+ (BOOL)shouldRegisterNow {
// return if the user has not granted privacy permissions
if ([self shouldLogMissingPrivacyConsentErrorWithMethodName:nil])
Expand Down Expand Up @@ -1709,9 +1710,32 @@ + (BOOL)shouldRegisterNow {
// Make sure last time we closed app was more than 30 secs ago
const int minTimeThreshold = 30;
NSTimeInterval delta = now - lastTimeClosed;

// Tracking cold starts within 30 seconds of last close.
// Depending on the results of our tracking we will change this case
// from a tracking request to return true
if (delta < minTimeThreshold && appId && !_registerUserFinished && !_trackedColdRestart) {
[OneSignal trackColdRestart];
}
return delta >= minTimeThreshold;
}

+ (void)trackColdRestart {
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"trackColdRestart"];
// Set to true even if it doesn't pass the sample check
_trackedColdRestart = true;
// Sample /track calls to avoid hitting our endpoint too hard
int randomSample = arc4random_uniform(100);
if (randomSample == 99) {
NSString *osUsageData = [NSString stringWithFormat:@"kind=sdk, version=%@, source=iOS_SDK, name=cold_restart, lockScreenApp=false", ONESIGNAL_VERSION];
[[OneSignalClient sharedClient] executeRequest:[OSRequestTrackV1 trackUsageData:osUsageData appId:appId] onSuccess:^(NSDictionary *result) {
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"trackColdRestart: successfully tracked cold restart"];
} onFailure:^(NSError *error) {
[OneSignal onesignal_Log:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"trackColdRestart: Failed to track cold restart: %@", error.localizedDescription]];
}];
}
}

+ (void)registerUserAfterDelay {
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserAfterDelay"];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(registerUser) object:nil];
Expand Down
1 change: 1 addition & 0 deletions iOS_SDK/OneSignalSDK/Source/OneSignalRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
@property (nonatomic) HTTPMethod method;
@property (strong, nonatomic, nonnull) NSString *path;
@property (strong, nonatomic, nullable) NSDictionary *parameters;
@property (strong, nonatomic, nullable) NSDictionary<NSString *, NSString *> *additionalHeaders;
@property (nonatomic) int reattemptCount;
@property (nonatomic) BOOL dataRequest; //false for JSON based requests
-(BOOL)missingAppId; //for requests that don't require an appId parameter, the subclass should override this method and return false
Expand Down
4 changes: 4 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/OneSignalRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ -(NSMutableURLRequest *)urlRequest {

let request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];

for (NSString *key in self.additionalHeaders) {
[request setValue:self.additionalHeaders[key] forHTTPHeaderField:key];
}

if (!self.dataRequest)
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

Expand Down
4 changes: 4 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/Requests.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,9 @@ NS_ASSUME_NONNULL_END
+ (instancetype _Nonnull)withPlayerId:(NSString * _Nullable)playerId notificationId:(NSString * _Nonnull)notificationId appId:(NSString * _Nonnull)appId;
@end

@interface OSRequestTrackV1 : OneSignalRequest
+ (instancetype _Nonnull)trackUsageData:(NSString * _Nonnull)osUsageData
appId:(NSString * _Nonnull)appId;
@end
#endif /* Requests_h */

17 changes: 17 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/Requests.m
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,20 @@ + (instancetype)measureOutcomeEvent:(OSOutcomeEventParams *)outcome appId:(NSStr
return request;
}
@end

@implementation OSRequestTrackV1
NSString * const OS_USAGE_DATA = @"OS-Usage-Data";
+ (instancetype)trackUsageData:(NSString *)osUsageData appId:(NSString *)appId {
let request = [OSRequestTrackV1 new];
let params = [NSMutableDictionary new];
let headers = [NSMutableDictionary new];
params[APP_ID] = appId;
headers[APP_ID] = appId;
headers[OS_USAGE_DATA] = osUsageData;
request.method = POST;
request.path = @"v1/track";
request.parameters = params;
request.additionalHeaders = headers;
return request;
}
@end
38 changes: 38 additions & 0 deletions iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ BOOL checkHttpBody(NSData *bodyData, NSDictionary *correct) {
return dictionariesAreEquivalent(serialized, correct);
}

BOOL checkHttpHeaders(NSDictionary *additionalHeaders, NSDictionary *correct) {
return dictionariesAreEquivalent(additionalHeaders, correct);
}

- (void)testBuildGetTags {
let request = [OSRequestGetTags withUserId:testUserId appId:testAppId];

Expand Down Expand Up @@ -743,4 +747,38 @@ - (void)testSendExternalWithAuthUserId {
XCTAssertTrue(checkHttpBody(request.urlRequest.HTTPBody, @{@"app_id" : testAppId, @"external_user_id" : testExternalUserId, @"external_user_id_auth_hash" : testExternalUserIdHashToken}));
}

- (void)testSendTrackUsageRequest {
NSString *testUsageData = @"test usage data";
let request = [OSRequestTrackV1 trackUsageData:testUsageData appId:testAppId];
let correctUrl = correctUrlWithPath(@"v1/track");

XCTAssertTrue([correctUrl isEqualToString:request.urlRequest.URL.absoluteString]);
XCTAssertTrue(checkHttpBody(request.urlRequest.HTTPBody, @{@"app_id" : testAppId}));
XCTAssertTrue(checkHttpHeaders(request.additionalHeaders, @{@"app_id" : testAppId,
@"OS-Usage-Data" : testUsageData,
}));
}

- (void)testAdditionalHeaders {
// Create a fake request
let request = [OneSignalRequest new];
let params = [NSMutableDictionary new];
let headers = [NSMutableDictionary new];
params[@"app_id"] = testAppId;
headers[@"app_id"] = testAppId;
headers[@"test-header"] = @"test_header_value";
request.method = POST;
request.path = @"test/path";
request.parameters = params;
request.additionalHeaders = headers;

// Properties must be set in the request before accessing urlRequest
let urlRequest = request.urlRequest;
let requestHeaders = urlRequest.allHTTPHeaderFields;
// Verify that all headers we added via additionalHeaders are in the request's header fields
for (NSString *key in headers) {
XCTAssertTrue(requestHeaders[key] != nil);
}
}

@end

0 comments on commit fd06483

Please sign in to comment.