SFAnalytics.h
1 /* 2 * Copyright (c) 2017 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #if __OBJC2__ 25 #ifndef SFAnalytics_h 26 #define SFAnalytics_h 27 28 #import <Foundation/Foundation.h> 29 #import <Security/SFAnalyticsSampler.h> 30 #import <Security/SFAnalyticsMultiSampler.h> 31 #import <Security/SFAnalyticsActivityTracker.h> 32 33 NS_ASSUME_NONNULL_BEGIN 34 35 // this sampling interval will cause the sampler to run only at data reporting time 36 extern const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport; 37 38 typedef NS_ENUM(uint32_t, SFAnalyticsTimestampBucket) { 39 SFAnalyticsTimestampBucketSecond = 0, 40 SFAnalyticsTimestampBucketMinute = 1, 41 SFAnalyticsTimestampBucketHour = 2, 42 }; 43 44 @protocol SFAnalyticsProtocol <NSObject> 45 + (id<SFAnalyticsProtocol> _Nullable)logger; 46 47 - (void)logResultForEvent:(NSString*)eventName 48 hardFailure:(bool)hardFailure 49 result:(NSError* _Nullable)eventResultError; 50 - (void)logResultForEvent:(NSString*)eventName 51 hardFailure:(bool)hardFailure 52 result:(NSError* _Nullable)eventResultError 53 withAttributes:(NSDictionary* _Nullable)attributes; 54 55 - (SFAnalyticsMultiSampler* _Nullable)AddMultiSamplerForName:(NSString *)samplerName 56 withTimeInterval:(NSTimeInterval)timeInterval 57 block:(NSDictionary<NSString *,NSNumber *> *(^)(void))block; 58 59 - (SFAnalyticsActivityTracker* _Nullable)logSystemMetricsForActivityNamed:(NSString*)eventName 60 withAction:(void (^ _Nullable)(void))action; 61 - (SFAnalyticsActivityTracker* _Nullable)startLogSystemMetricsForActivityNamed:(NSString *)eventName; 62 @end 63 64 @interface SFAnalytics : NSObject <SFAnalyticsProtocol> 65 66 + (instancetype _Nullable)logger; 67 68 + (NSInteger)fuzzyDaysSinceDate:(NSDate*)date; 69 70 // Rounds to the nearest 5 (unless 1 or 2, that rounds to 5 as well) 71 + (NSInteger)fuzzyInteger:(NSInteger)num; 72 + (NSNumber*)fuzzyNumber:(NSNumber*)num; 73 74 + (void)addOSVersionToEvent:(NSMutableDictionary*)event; 75 // Help for the subclass to pick a prefered location 76 + (NSString *)defaultAnalyticsDatabasePath:(NSString *)basename; 77 78 + (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename uuid:(NSUUID * __nullable)userUuid; 79 + (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename; // uses current user UUID for path 80 81 - (void)dailyCoreAnalyticsMetrics:(NSString *)eventName; 82 83 // Log event-based metrics: create an event corresponding to some event in your feature 84 // and call the appropriate method based on the successfulness of that event 85 - (void)logSuccessForEventNamed:(NSString*)eventName; 86 - (void)logSuccessForEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 87 88 - (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes; 89 - (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 90 91 - (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes; 92 - (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 93 94 // or just log an event if it is not failable 95 - (void)noteEventNamed:(NSString*)eventName; 96 - (void)noteEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 97 98 - (void)logResultForEvent:(NSString*)eventName 99 hardFailure:(bool)hardFailure 100 result:(NSError* _Nullable)eventResultError; 101 - (void)logResultForEvent:(NSString*)eventName 102 hardFailure:(bool)hardFailure 103 result:(NSError* _Nullable)eventResultError 104 timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 105 - (void)logResultForEvent:(NSString*)eventName 106 hardFailure:(bool)hardFailure 107 result:(NSError* _Nullable)eventResultError 108 withAttributes:(NSDictionary* _Nullable)attributes; 109 - (void)logResultForEvent:(NSString*)eventName 110 hardFailure:(bool)hardFailure 111 result:(NSError* _Nullable)eventResultError 112 withAttributes:(NSDictionary* _Nullable)attributes 113 timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; 114 115 // Track the state of a named value over time 116 - (SFAnalyticsSampler* _Nullable)addMetricSamplerForName:(NSString*)samplerName 117 withTimeInterval:(NSTimeInterval)timeInterval 118 block:(NSNumber* (^)(void))block; 119 - (SFAnalyticsSampler* _Nullable)existingMetricSamplerForName:(NSString*)samplerName; 120 - (void)removeMetricSamplerForName:(NSString*)samplerName; 121 // Same idea, but log multiple named values in a single block 122 - (SFAnalyticsMultiSampler* _Nullable)AddMultiSamplerForName:(NSString*)samplerName 123 withTimeInterval:(NSTimeInterval)timeInterval 124 block:(NSDictionary<NSString*, NSNumber*>* (^)(void))block; 125 - (SFAnalyticsMultiSampler*)existingMultiSamplerForName:(NSString*)samplerName; 126 - (void)removeMultiSamplerForName:(NSString*)samplerName; 127 128 // Log measurements of arbitrary things 129 // System metrics measures how much time it takes to complete the action - possibly more in the future. The return value can be ignored if you only need to execute 1 block for your activity 130 - (SFAnalyticsActivityTracker* _Nullable)logSystemMetricsForActivityNamed:(NSString*)eventName 131 withAction:(void (^ _Nullable)(void))action; 132 133 // Same as above, but automatically starts the tracker, since you haven't given it any action to perform 134 - (SFAnalyticsActivityTracker* _Nullable)startLogSystemMetricsForActivityNamed:(NSString *)eventName; 135 136 - (void)logMetric:(NSNumber*)metric withName:(NSString*)metricName; 137 138 139 // -------------------------------- 140 // Things below are for subclasses 141 142 // Override to create a concrete logger instance 143 @property (readonly, class, nullable) NSString* databasePath; 144 145 // Storing dates 146 - (void)setDateProperty:(NSDate* _Nullable)date forKey:(NSString*)key; 147 - (NSDate* _Nullable)datePropertyForKey:(NSString*)key; 148 149 - (void)incrementIntegerPropertyForKey:(NSString*)key; 150 - (void)setNumberProperty:(NSNumber* _Nullable)number forKey:(NSString*)key; 151 - (NSNumber * _Nullable)numberPropertyForKey:(NSString*)key; 152 153 154 // -------------------------------- 155 // Things below are for unit testing 156 157 - (void)removeState; // removes DB object and any samplers 158 159 @end 160 161 NS_ASSUME_NONNULL_END 162 #endif 163 #endif