CKKSAnalyticsLogger.m [plain text]
/*
* Copyright (c) 2017 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#if OCTAGON
#import "CKKSAnalyticsLogger.h"
#import "debugging.h"
#import "CKKS.h"
#import "CKKSViewManager.h"
#import "CKKSKeychainView.h"
#include <utilities/SecFileLocations.h>
#import "Analytics/SFAnalyticsLogger.h"
#import <os/log.h>
NSString* const CKKSAnalyticsAttributeRecoverableError = @"recoverableError";
NSString* const CKKSAnalyticsAttributeZoneName = @"zone";
NSString* const CKKSAnalyticsAttributeErrorDomain = @"errorDomain";
NSString* const CKKSAnalyticsAttributeErrorCode = @"errorCode";
NSString* const CKKSAnalyticsHasTLKs = @"TLKs";
NSString* const CKKSAnalyticsSyncedClassARecently = @"inSyncA";
NSString* const CKKSAnalyticsSyncedClassCRecently = @"inSyncC";
NSString* const CKKSAnalyticsIncomingQueueIsErrorFree = @"IQNOE";
NSString* const CKKSAnalyticsOutgoingQueueIsErrorFree = @"OQNOE";
NSString* const CKKSAnalyticsInSync = @"inSync";
CKKSAnalyticsFailableEvent* const CKKSEventProcessIncomingQueueClassA = (CKKSAnalyticsFailableEvent*)@"CKKSEventProcessIncomingQueueClassA";
CKKSAnalyticsFailableEvent* const CKKSEventProcessIncomingQueueClassC = (CKKSAnalyticsFailableEvent*)@"CKKSEventProcessIncomingQueueClassC";
CKKSAnalyticsFailableEvent* const CKKSEventUploadChanges = (CKKSAnalyticsFailableEvent*)@"CKKSEventUploadChanges";
CKKSAnalyticsSignpostEvent* const CKKSEventPushNotificationReceived = (CKKSAnalyticsSignpostEvent*)@"CKKSEventPushNotificationReceived";
CKKSAnalyticsSignpostEvent* const CKKSEventItemAddedToOutgoingQueue = (CKKSAnalyticsSignpostEvent*)@"CKKSEventItemAddedToOutgoingQueue";
@implementation CKKSAnalyticsLogger
+ (NSString*)databasePath
{
return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)@"ckks_analytics_v2.db") path];
}
+ (instancetype)logger
{
// just here because I want it in the header for discoverability
return [super logger];
}
- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view
{
[self logSuccessForEventNamed:[NSString stringWithFormat:@" [self setDateProperty:[NSDate date] forKey:[NSString stringWithFormat:@"last_success_}
- (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view
{
NSDictionary* attributes = @{ CKKSAnalyticsAttributeRecoverableError : @(YES),
CKKSAnalyticsAttributeZoneName : view.zoneName,
CKKSAnalyticsAttributeErrorDomain : error.domain,
CKKSAnalyticsAttributeErrorCode : @(error.code) };
[super logSoftFailureForEventNamed:event withAttributes:attributes];
}
- (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view
{
NSDictionary* attributes = @{ CKKSAnalyticsAttributeRecoverableError : @(NO),
CKKSAnalyticsAttributeZoneName : view.zoneName,
CKKSAnalyticsAttributeErrorDomain : error.domain,
CKKSAnalyticsAttributeErrorCode : @(error.code) };
[self logHardFailureForEventNamed:event withAttributes:attributes];
}
- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event inView:(CKKSKeychainView*)view
{
[self noteEventNamed:[NSString stringWithFormat:@"}
- (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view
{
return [self datePropertyForKey:[NSString stringWithFormat:@"last_success_}
- (NSDictionary*)extraValuesToUploadToServer
{
NSMutableDictionary* values = [NSMutableDictionary dictionary];
for (NSString* viewName in [CKKSViewManager viewList]) {
CKKSKeychainView* view = [CKKSViewManager findOrCreateView:viewName];
NSDate* dateOfLastSyncClassA = [self dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:view];
NSDate* dateOfLastSyncClassC = [self dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:view];
NSInteger fuzzyDaysSinceClassASync = [CKKSAnalyticsLogger fuzzyDaysSinceDate:dateOfLastSyncClassA];
NSInteger fuzzyDaysSinceClassCSync = [CKKSAnalyticsLogger fuzzyDaysSinceDate:dateOfLastSyncClassC];
[values setValue:@(fuzzyDaysSinceClassASync) forKey:[NSString stringWithFormat:@" [values setValue:@(fuzzyDaysSinceClassCSync) forKey:[NSString stringWithFormat:@"
BOOL hasTLKs = [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateReady];
BOOL syncedClassARecently = fuzzyDaysSinceClassASync < 7;
BOOL syncedClassCRecently = fuzzyDaysSinceClassCSync < 7;
BOOL incomingQueueIsErrorFree = view.lastIncomingQueueOperation.error == nil;
BOOL outgoingQueueIsErrorFree = view.lastOutgoingQueueOperation.error == nil;
NSString* hasTLKsKey = [NSString stringWithFormat:@" NSString* syncedClassARecentlyKey = [NSString stringWithFormat:@" NSString* syncedClassCRecentlyKey = [NSString stringWithFormat:@" NSString* incomingQueueIsErrorFreeKey = [NSString stringWithFormat:@" NSString* outgoingQueueIsErrorFreeKey = [NSString stringWithFormat:@"
values[hasTLKsKey] = @(hasTLKs);
values[syncedClassARecentlyKey] = @(syncedClassARecently);
values[syncedClassCRecentlyKey] = @(syncedClassCRecently);
values[incomingQueueIsErrorFreeKey] = @(incomingQueueIsErrorFree);
values[outgoingQueueIsErrorFreeKey] = @(outgoingQueueIsErrorFree);
BOOL weThinkWeAreInSync = hasTLKs && syncedClassARecently && syncedClassCRecently && incomingQueueIsErrorFree && outgoingQueueIsErrorFree;
NSString* inSyncKey = [NSString stringWithFormat:@" values[inSyncKey] = @(weThinkWeAreInSync);
}
return values;
}
@end
#endif // OCTAGON