Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 7d9162d

Browse files
committed
Merge pull request #166 from Microsoft/metrics-sdk-changes
Metrics SDK Changes
2 parents 7d15a58 + 509cc0f commit 7d9162d

File tree

9 files changed

+327
-129
lines changed

9 files changed

+327
-129
lines changed

CodePush.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ failCallback:(void (^)(NSError *err))failCallback;
9595

9696
@end
9797

98+
@interface CodePushTelemetryManager : NSObject
99+
100+
+ (NSDictionary *)getBinaryUpdateReport:(NSString *)appVersion;
101+
+ (NSDictionary *)getRollbackReport:(NSDictionary *)lastFailedPackage;
102+
+ (NSDictionary *)getUpdateReport:(NSDictionary *)currentPackage;
103+
104+
@end
105+
98106
typedef NS_ENUM(NSInteger, CodePushInstallMode) {
99107
CodePushInstallModeImmediate,
100108
CodePushInstallModeOnNextRestart,

CodePush.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
103103
});
104104
};
105105

106-
sdk.reportStatusDeploy = (deployedPackage, status) => {
106+
sdk.reportStatusDeploy = (deployedPackage, status, previousLabelOrAppVersion, previousDeploymentKey) => {
107107
return new Promise((resolve, reject) => {
108-
module.exports.AcquisitionSdk.prototype.reportStatusDeploy.call(sdk, deployedPackage, status, (err) => {
108+
module.exports.AcquisitionSdk.prototype.reportStatusDeploy.call(sdk, deployedPackage, status, previousLabelOrAppVersion, previousDeploymentKey, (err) => {
109109
if (err) {
110110
reject(err);
111111
} else {
@@ -140,13 +140,15 @@ async function notifyApplicationReady() {
140140
const statusReport = await NativeCodePush.getNewStatusReport();
141141
if (statusReport) {
142142
const config = await getConfiguration();
143+
const previousLabelOrAppVersion = statusReport.previousLabelOrAppVersion;
144+
const previousDeploymentKey = statusReport.previousDeploymentKey || config.deploymentKey;
143145
if (statusReport.appVersion) {
144146
const sdk = getPromisifiedSdk(requestFetchAdapter, config);
145-
sdk.reportStatusDeploy();
147+
sdk.reportStatusDeploy(/* deployedPackage */ null, /* status */ null, previousLabelOrAppVersion, previousDeploymentKey);
146148
} else {
147149
config.deploymentKey = statusReport.package.deploymentKey;
148150
const sdk = getPromisifiedSdk(requestFetchAdapter, config);
149-
sdk.reportStatusDeploy(statusReport.package, statusReport.status);
151+
sdk.reportStatusDeploy(statusReport.package, statusReport.status, previousLabelOrAppVersion, previousDeploymentKey);
150152
}
151153
}
152154
}

CodePush.m

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ @implementation CodePush {
2525

2626
// These keys represent the names we use to store data in NSUserDefaults
2727
static NSString *const FailedUpdatesKey = @"CODE_PUSH_FAILED_UPDATES";
28-
static NSString *const LastDeploymentReportKey = @"CODE_PUSH_LAST_DEPLOYMENT_REPORT";
2928
static NSString *const PendingUpdateKey = @"CODE_PUSH_PENDING_UPDATE";
3029

3130
// These keys are already "namespaced" by the PendingUpdateKey, so
@@ -35,8 +34,6 @@ @implementation CodePush {
3534

3635
// These keys are used to inspect/augment the metadata
3736
// that is associated with an update's package.
38-
static NSString *const DeploymentKeyKey = @"deploymentKey";
39-
static NSString *const LabelKey = @"label";
4037
static NSString *const PackageHashKey = @"packageHash";
4138
static NSString *const PackageIsPendingKey = @"isPending";
4239

@@ -168,19 +165,6 @@ - (void)dealloc
168165
[[NSNotificationCenter defaultCenter] removeObserver:self];
169166
}
170167

171-
- (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package
172-
{
173-
// Because deploymentKeys can be dynamically switched, we use a
174-
// combination of the deploymentKey and label as the packageIdentifier.
175-
NSString *deploymentKey = [package objectForKey:DeploymentKeyKey];
176-
NSString *label = [package objectForKey:LabelKey];
177-
if (deploymentKey && label) {
178-
return [[deploymentKey stringByAppendingString:@":"] stringByAppendingString:label];
179-
} else {
180-
return nil;
181-
}
182-
}
183-
184168
- (instancetype)init
185169
{
186170
self = [super init];
@@ -219,13 +203,6 @@ - (void)initializeUpdateAfterRestart
219203
}
220204
}
221205

222-
- (BOOL)isDeploymentStatusNotYetReported:(NSString *)appVersionOrPackageIdentifier
223-
{
224-
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
225-
NSString *sentStatusReportIdentifier = [preferences objectForKey:LastDeploymentReportKey];
226-
return sentStatusReportIdentifier == nil || ![sentStatusReportIdentifier isEqualToString:appVersionOrPackageIdentifier];
227-
}
228-
229206
/*
230207
* This method checks to see whether a specific package hash
231208
* has previously failed installation.
@@ -296,13 +273,6 @@ - (void)loadBundle
296273
});
297274
}
298275

299-
- (void)recordDeploymentStatusReported:(NSString *)appVersionOrPackageIdentifier
300-
{
301-
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
302-
[preferences setValue:appVersionOrPackageIdentifier forKey:LastDeploymentReportKey];
303-
[preferences synchronize];
304-
}
305-
306276
/*
307277
* This method is used when an update has failed installation
308278
* and the app needs to be rolled back to the previous bundle.
@@ -530,7 +500,7 @@ - (void)savePendingUpdate:(NSString *)packageHash
530500
rejecter:(RCTPromiseRejectBlock)reject)
531501
{
532502
[CodePush removePendingUpdate];
533-
resolve([NSNull null]);
503+
resolve(nil);
534504
}
535505

536506
/*
@@ -540,45 +510,35 @@ - (void)savePendingUpdate:(NSString *)packageHash
540510
RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve
541511
rejecter:(RCTPromiseRejectBlock)reject)
542512
{
543-
if (needToReportRollback) {
544-
// Check if there was a rollback that was not yet reported
545-
needToReportRollback = NO;
546-
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
547-
NSMutableArray *failedUpdates = [preferences objectForKey:FailedUpdatesKey];
548-
if (failedUpdates) {
549-
NSDictionary *lastFailedPackage = [failedUpdates lastObject];
550-
if (lastFailedPackage) {
551-
NSString *lastFailedPackageIdentifier = [self getPackageStatusReportIdentifier:lastFailedPackage];
552-
if (lastFailedPackageIdentifier && [self isDeploymentStatusNotYetReported:lastFailedPackageIdentifier]) {
553-
[self recordDeploymentStatusReported:lastFailedPackageIdentifier];
554-
resolve(@{ @"package": lastFailedPackage, @"status": DeploymentFailed });
513+
514+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
515+
if (needToReportRollback) {
516+
needToReportRollback = NO;
517+
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
518+
NSMutableArray *failedUpdates = [preferences objectForKey:FailedUpdatesKey];
519+
if (failedUpdates) {
520+
NSDictionary *lastFailedPackage = [failedUpdates lastObject];
521+
if (lastFailedPackage) {
522+
resolve([CodePushTelemetryManager getRollbackReport:lastFailedPackage]);
555523
return;
556524
}
557525
}
558-
}
559-
} else if (_isFirstRunAfterUpdate) {
560-
// Check if the current CodePush package has been reported
561-
NSError *error;
562-
NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&error];
563-
if (!error && currentPackage) {
564-
NSString *currentPackageIdentifier = [self getPackageStatusReportIdentifier:currentPackage];
565-
if (currentPackageIdentifier && [self isDeploymentStatusNotYetReported:currentPackageIdentifier]) {
566-
[self recordDeploymentStatusReported:currentPackageIdentifier];
567-
resolve(@{ @"package": currentPackage, @"status": DeploymentSucceeded });
526+
} else if (_isFirstRunAfterUpdate) {
527+
NSError *error;
528+
NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&error];
529+
if (!error && currentPackage) {
530+
resolve([CodePushTelemetryManager getUpdateReport:currentPackage]);
568531
return;
569532
}
570-
}
571-
} else if (isRunningBinaryVersion || [_bridge.bundleURL.scheme hasPrefix:@"http"]) {
572-
// Check if the current appVersion has been reported.
573-
NSString *appVersion = [[CodePushConfig current] appVersion];
574-
if ([self isDeploymentStatusNotYetReported:appVersion]) {
575-
[self recordDeploymentStatusReported:appVersion];
576-
resolve(@{ @"appVersion": appVersion });
533+
} else if (isRunningBinaryVersion || [_bridge.bundleURL.scheme hasPrefix:@"http"]) {
534+
// Check if the current appVersion has been reported.
535+
NSString *appVersion = [[CodePushConfig current] appVersion];
536+
resolve([CodePushTelemetryManager getBinaryUpdateReport:appVersion]);
577537
return;
578538
}
579-
}
580-
581-
resolve([NSNull null]);
539+
540+
resolve(nil);
541+
});
582542
}
583543

584544
/*

CodePush.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
1111
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; };
12+
5421FE311C58AD5A00986A55 /* CodePushTelemetryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */; };
1213
54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024C1C0E2880004C3CEC /* aescrypt.c */; };
1314
54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024D1C0E2880004C3CEC /* aeskey.c */; };
1415
54A0026E1C0E2880004C3CEC /* aestab.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024F1C0E2880004C3CEC /* aestab.c */; };
@@ -45,6 +46,7 @@
4546
13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = "<group>"; };
4647
13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = "<group>"; };
4748
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushInstallMode.m"; sourceTree = "<group>"; };
49+
5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushTelemetryManager.m; sourceTree = "<group>"; };
4850
54A0024A1C0E2880004C3CEC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
4951
54A0024B1C0E2880004C3CEC /* aes_via_ace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes_via_ace.h; sourceTree = "<group>"; };
5052
54A0024C1C0E2880004C3CEC /* aescrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aescrypt.c; sourceTree = "<group>"; };
@@ -165,6 +167,7 @@
165167
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
166168
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
167169
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
170+
5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */,
168171
81D51F391B6181C2000DA084 /* CodePushConfig.m */,
169172
13BE3DEC1AC21097009241FE /* CodePush.h */,
170173
13BE3DED1AC21097009241FE /* CodePush.m */,
@@ -239,6 +242,7 @@
239242
54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */,
240243
54A002711C0E2880004C3CEC /* hmac.c in Sources */,
241244
54A002721C0E2880004C3CEC /* prng.c in Sources */,
245+
5421FE311C58AD5A00986A55 /* CodePushTelemetryManager.m in Sources */,
242246
54A002731C0E2880004C3CEC /* pwd2key.c in Sources */,
243247
54A002751C0E2880004C3CEC /* ioapi.c in Sources */,
244248
54A002771C0E2880004C3CEC /* unzip.c in Sources */,

CodePushTelemetryManager.m

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#import "CodePush.h"
2+
3+
static NSString *const DeploymentFailed = @"DeploymentFailed";
4+
static NSString *const DeploymentKeyKey = @"deploymentKey";
5+
static NSString *const DeploymentSucceeded = @"DeploymentSucceeded";
6+
static NSString *const LabelKey = @"label";
7+
static NSString *const LastDeploymentReportKey = @"CODE_PUSH_LAST_DEPLOYMENT_REPORT";
8+
9+
@implementation CodePushTelemetryManager
10+
11+
+ (NSDictionary *)getBinaryUpdateReport:(NSString *)appVersion
12+
{
13+
NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier];
14+
if (previousStatusReportIdentifier == nil) {
15+
[self recordDeploymentStatusReported:appVersion];
16+
return @{ @"appVersion": appVersion };
17+
} else if (![previousStatusReportIdentifier isEqualToString:appVersion]) {
18+
[self recordDeploymentStatusReported:appVersion];
19+
if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) {
20+
NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier];
21+
NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier];
22+
return @{
23+
@"appVersion": appVersion,
24+
@"previousDeploymentKey": previousDeploymentKey,
25+
@"previousLabelOrAppVersion": previousLabel
26+
};
27+
} else {
28+
// Previous status report was with a binary app version.
29+
return @{
30+
@"appVersion": appVersion,
31+
@"previousLabelOrAppVersion": previousStatusReportIdentifier
32+
};
33+
}
34+
}
35+
36+
return nil;
37+
}
38+
39+
+ (NSDictionary *)getRollbackReport:(NSDictionary *)lastFailedPackage
40+
{
41+
return @{
42+
@"package": lastFailedPackage,
43+
@"status": DeploymentFailed
44+
};
45+
}
46+
47+
+ (NSDictionary *)getUpdateReport:(NSDictionary *)currentPackage
48+
{
49+
NSString *currentPackageIdentifier = [self getPackageStatusReportIdentifier:currentPackage];
50+
NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier];
51+
if (currentPackageIdentifier) {
52+
if (previousStatusReportIdentifier == nil) {
53+
[self recordDeploymentStatusReported:currentPackageIdentifier];
54+
return @{
55+
@"package": currentPackage,
56+
@"status": DeploymentSucceeded
57+
};
58+
} else if (![previousStatusReportIdentifier isEqualToString:currentPackageIdentifier]) {
59+
[self recordDeploymentStatusReported:currentPackageIdentifier];
60+
if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) {
61+
NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier];
62+
NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier];
63+
return @{
64+
@"package": currentPackage,
65+
@"status": DeploymentSucceeded,
66+
@"previousDeploymentKey": previousDeploymentKey,
67+
@"previousLabelOrAppVersion": previousLabel
68+
};
69+
} else {
70+
// Previous status report was with a binary app version.
71+
return @{
72+
@"package": currentPackage,
73+
@"status": DeploymentSucceeded,
74+
@"previousLabelOrAppVersion": previousStatusReportIdentifier
75+
};
76+
}
77+
}
78+
}
79+
80+
return nil;
81+
}
82+
83+
#pragma mark - private methods
84+
85+
+ (NSString *)getDeploymentKeyFromStatusReportIdentifier:(NSString *)statusReportIdentifier
86+
{
87+
return [[statusReportIdentifier componentsSeparatedByString:@":"] firstObject];
88+
}
89+
90+
+ (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package
91+
{
92+
// Because deploymentKeys can be dynamically switched, we use a
93+
// combination of the deploymentKey and label as the packageIdentifier.
94+
NSString *deploymentKey = [package objectForKey:DeploymentKeyKey];
95+
NSString *label = [package objectForKey:LabelKey];
96+
if (deploymentKey && label) {
97+
return [[deploymentKey stringByAppendingString:@":"] stringByAppendingString:label];
98+
} else {
99+
return nil;
100+
}
101+
}
102+
103+
+ (NSString *)getPreviousStatusReportIdentifier
104+
{
105+
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
106+
NSString *sentStatusReportIdentifier = [preferences objectForKey:LastDeploymentReportKey];
107+
return sentStatusReportIdentifier;
108+
}
109+
110+
+ (NSString *)getVersionLabelFromStatusReportIdentifier:(NSString *)statusReportIdentifier
111+
{
112+
return [[statusReportIdentifier componentsSeparatedByString:@":"] lastObject];
113+
}
114+
115+
+ (BOOL)isStatusReportIdentifierCodePushLabel:(NSString *)statusReportIdentifier
116+
{
117+
return statusReportIdentifier != nil && [statusReportIdentifier containsString:@":"];
118+
}
119+
120+
+ (void)recordDeploymentStatusReported:(NSString *)appVersionOrPackageIdentifier
121+
{
122+
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
123+
[preferences setValue:appVersionOrPackageIdentifier forKey:LastDeploymentReportKey];
124+
[preferences synchronize];
125+
}
126+
127+
@end

0 commit comments

Comments
 (0)