diff --git a/Riot/Analytics/Analytics.m b/Riot/Analytics/Analytics.m index a376fbef8..5ba48b694 100644 --- a/Riot/Analytics/Analytics.m +++ b/Riot/Analytics/Analytics.m @@ -28,7 +28,6 @@ NSString *const kAnalyticsMetricsActionPattern = @"iOS.%@"; // E2E telemetry is stored under a Piwik category called "E2E". NSString *const kAnalyticsE2eCategory = @"E2E"; NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure"; -NSString *const kAnalyticsE2eDecryptionFailureReasonNoReason = @"no_reason"; @import PiwikTracker; @@ -174,13 +173,16 @@ NSString *const kAnalyticsE2eDecryptionFailureReasonNoReason = @"no_reason"; #pragma mark - MXDecryptionFailureDelegate -- (void)trackFailures:(NSUInteger)failuresCount +- (void)trackFailures:(NSDictionary *)failuresCounts { - [[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory - action:kAnalyticsE2eDecryptionFailureAction - name:kAnalyticsE2eDecryptionFailureReasonNoReason - number:@(failuresCount) - url:nil]; + for (NSString *reason in failuresCounts) + { + [[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory + action:kAnalyticsE2eDecryptionFailureAction + name:reason + number:failuresCounts[reason] + url:nil]; + } } @end diff --git a/Riot/Analytics/DecryptionFailure.h b/Riot/Analytics/DecryptionFailure.h index df9f1af75..7ea43962c 100644 --- a/Riot/Analytics/DecryptionFailure.h +++ b/Riot/Analytics/DecryptionFailure.h @@ -16,6 +16,18 @@ #import +/** + Failure reasons as defined in https://docs.google.com/document/d/1es7cTCeJEXXfRCTRgZerAM2Wg5ZerHjvlpfTW-gsOfI. + */ +struct DecryptionFailureReasonStruct +{ + __unsafe_unretained NSString * const unspecified; + __unsafe_unretained NSString * const olmKeysNotSent; + __unsafe_unretained NSString * const olmIndexError; + __unsafe_unretained NSString * const unexpected; +}; +extern const struct DecryptionFailureReasonStruct DecryptionFailureReason; + /** `DecryptionFailure` represents a decryption failure. */ diff --git a/Riot/Analytics/DecryptionFailure.m b/Riot/Analytics/DecryptionFailure.m index 7cb470e8c..d43b0ec9f 100644 --- a/Riot/Analytics/DecryptionFailure.m +++ b/Riot/Analytics/DecryptionFailure.m @@ -16,6 +16,13 @@ #import "DecryptionFailure.h" +const struct DecryptionFailureReasonStruct DecryptionFailureReason = { + .unspecified = @"unspecified_error", + .olmKeysNotSent = @"olm_keys_not_sent_error", + .olmIndexError = @"olm_index_error", + .unexpected = @"unexpected_error" +}; + @implementation DecryptionFailure - (instancetype)init diff --git a/Riot/Analytics/DecryptionFailureTracker.h b/Riot/Analytics/DecryptionFailureTracker.h index 92c7587f1..45a8e1cee 100644 --- a/Riot/Analytics/DecryptionFailureTracker.h +++ b/Riot/Analytics/DecryptionFailureTracker.h @@ -16,6 +16,8 @@ #import +#import "DecryptionFailure.h" + @import MatrixSDK; @protocol MXDecryptionFailureDelegate; @@ -62,8 +64,8 @@ /** Stats for decryption failures. - @param failuresCount the number of decryption failures. + @param failuresCounts the number of errors per failure reason. */ -- (void)trackFailures:(NSUInteger)failuresCount; +- (void)trackFailures:(NSDictionary *)failuresCounts; @end diff --git a/Riot/Analytics/DecryptionFailureTracker.m b/Riot/Analytics/DecryptionFailureTracker.m index 240f0ecd2..ed87dd952 100644 --- a/Riot/Analytics/DecryptionFailureTracker.m +++ b/Riot/Analytics/DecryptionFailureTracker.m @@ -16,8 +16,6 @@ #import "DecryptionFailureTracker.h" -#import "DecryptionFailure.h" - // Call `checkFailures` every `CHECK_INTERVAL` #define CHECK_INTERVAL 5 @@ -93,8 +91,26 @@ DecryptionFailure *decryptionFailure = [[DecryptionFailure alloc] init]; decryptionFailure.failedEventId = event.eventId; - // TODO: Need to sync with all platforms - // decryptionFailure.reason =; + // Categorise the error + switch (event.decryptionError.code) + { + case MXDecryptingErrorUnknownInboundSessionIdCode: + decryptionFailure.reason = DecryptionFailureReason.olmKeysNotSent; + break; + + case MXDecryptingErrorOlmCode: + decryptionFailure.reason = DecryptionFailureReason.olmIndexError; + break; + + case MXDecryptingErrorEncryptionNotEnabledCode: + case MXDecryptingErrorUnableToDecryptCode: + decryptionFailure.reason = DecryptionFailureReason.unexpected; + break; + + default: + decryptionFailure.reason = DecryptionFailureReason.unspecified; + break; + } reportedFailures[event.eventId] = decryptionFailure; } @@ -128,8 +144,16 @@ if (_delegate && failuresToTrack.count) { - NSLog(@"[DecryptionFailureTracker] trackFailures: %@", @(failuresToTrack.count)); - [_delegate trackFailures:failuresToTrack.count]; + // Sort failures by error reason + NSMutableDictionary *failuresCounts = [NSMutableDictionary dictionary]; + for (DecryptionFailure *failure in failuresToTrack) + { + failuresCounts[failure.reason] = @(failuresCounts[failure.reason].unsignedIntegerValue + 1); + } + + NSLog(@"[DecryptionFailureTracker] trackFailures: %@", failuresCounts); + + [_delegate trackFailures:failuresCounts]; } }