2014 snapchat source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
14 KiB

  1. //
  2. // SCLogger+Camera.m
  3. // Snapchat
  4. //
  5. // Created by Derek Peirce on 5/8/17.
  6. // Copyright © 2017 Snapchat, Inc. All rights reserved.
  7. //
  8. #import "SCLogger+Camera.h"
  9. #import "SCCameraTweaks.h"
  10. #import <SCFoundation/SCTrace.h>
  11. #import <SCFoundation/SCTraceODPCompatible.h>
  12. #import <SCLogger/SCCameraMetrics+CameraCreationDelay.h>
  13. #import <SCLogger/SCCameraMetrics.h>
  14. #import <SCLogger/SCLogger+Performance.h>
  15. #import <objc/runtime.h>
  16. @implementation SCLogger (Camera)
  17. @dynamic cameraCreationDelayLoggingStatus;
  18. - (NSNumber *)cameraCreationDelayLoggingStatus
  19. {
  20. return objc_getAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus));
  21. }
  22. - (void)setCameraCreationDelayLoggingStatus:(NSNumber *)status
  23. {
  24. objc_setAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus), status,
  25. OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  26. }
  27. - (BOOL)shouldLogCameraCreationDelay
  28. {
  29. return [[self cameraCreationDelayLoggingStatus] intValue] != CAMERA_CREATION_DELAY_LOGGING_END;
  30. }
  31. - (void)logCameraCreationDelayEnd
  32. {
  33. if ([[self cameraCreationDelayLoggingStatus] intValue] == CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP) {
  34. SCTraceSignPostEndForMetrics(kSCSignPostCameraCreationDelay, 0, 0, 0, 0);
  35. [self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_END)];
  36. } else {
  37. [self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP)];
  38. }
  39. }
  40. - (void)logCameraCreationStartWithMethod:(SCCameraRecordingMethod)method
  41. lensesEnabled:(BOOL)lensesEnabled
  42. activeLensId:(NSString *)activeLensId
  43. captureSessionId:(NSString *)captureSessionId
  44. {
  45. NSMutableDictionary *parameters = [@{
  46. @"lens_ui_enabled" : @(lensesEnabled),
  47. @"analytics_version" : kSCCameraDelayEventVersion,
  48. @"method" : @(method),
  49. } mutableCopy];
  50. if (lensesEnabled && activeLensId) {
  51. [parameters setObject:activeLensId forKey:@"lens_id"];
  52. }
  53. if (captureSessionId) {
  54. [parameters setObject:captureSessionId forKey:@"capture_session_id"];
  55. }
  56. [self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_START)];
  57. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCreationDelay];
  58. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraRecordingGestureFinished];
  59. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
  60. [[SCLogger sharedInstance] logTimedEventStart:kSCCameraCaptureDelayEvent
  61. uniqueId:@""
  62. isUniqueEvent:NO
  63. parameters:parameters
  64. shouldLogStartTime:YES];
  65. }
  66. - (void)logCameraExposureAdjustmentDelayStart
  67. {
  68. [[SCLogger sharedInstance] logTimedEventStart:kSCCameraExposureAdjustmentDelay
  69. uniqueId:@""
  70. isUniqueEvent:NO
  71. parameters:nil
  72. shouldLogStartTime:YES];
  73. }
  74. - (void)logCameraExposureAdjustmentDelayEndWithStrategy:(NSString *)strategy
  75. {
  76. [[SCLogger sharedInstance] logTimedEventEnd:kSCCameraExposureAdjustmentDelay
  77. uniqueId:@""
  78. parameters:@{
  79. @"strategy" : strategy
  80. }];
  81. }
  82. - (void)logCameraCaptureRecordingGestureFinishedAtTime:(CFTimeInterval)endRecordingTime
  83. {
  84. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraRecordingGestureFinished];
  85. [[SCLogger sharedInstance]
  86. updateLogTimedEvent:kSCCameraCaptureDelayEvent
  87. uniqueId:@""
  88. update:^(NSMutableDictionary *startParameters) {
  89. NSMutableDictionary *eventParameters =
  90. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  91. NSNumber *recordStartTime =
  92. (NSNumber *)eventParameters[kSCCameraSubmetricsPreCaptureOperationFinished];
  93. CFTimeInterval endRecordingTimeOffset =
  94. endRecordingTime -
  95. [startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue];
  96. if (recordStartTime) {
  97. CFTimeInterval timeDisplacement =
  98. ([recordStartTime doubleValue] / 1000.0) - endRecordingTimeOffset;
  99. [eventParameters setObject:@(timeDisplacement)
  100. forKey:SCPerformanceMetricsKey.kSCLoggerStartEventTimeAdjustmentKey];
  101. }
  102. [self addSplitPoint:kSCCameraSubmetricsRecordingGestureFinished
  103. atTime:endRecordingTime
  104. toEvent:startParameters];
  105. }];
  106. }
  107. - (void)logStillImageCaptureApi:(NSString *)api
  108. {
  109. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
  110. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
  111. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady];
  112. CFTimeInterval requestTime = CACurrentMediaTime();
  113. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent
  114. uniqueId:@""
  115. update:^(NSMutableDictionary *startParameters) {
  116. NSMutableDictionary *eventParameters =
  117. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  118. [eventParameters setObject:api forKey:@"api_type"];
  119. [eventParameters setObject:@(1) forKey:@"camera_api_level"];
  120. [self addSplitPoint:@"PRE_CAPTURE_OPERATION_REQUESTED"
  121. atTime:requestTime
  122. toEvent:startParameters];
  123. }];
  124. }
  125. - (void)logPreCaptureOperationRequestedAt:(CFTimeInterval)requestTime
  126. {
  127. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
  128. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
  129. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady];
  130. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent
  131. uniqueId:@""
  132. splitPoint:kSCCameraSubmetricsPreCaptureOperationRequested
  133. time:requestTime];
  134. }
  135. - (void)logPreCaptureOperationFinishedAt:(CFTimeInterval)time
  136. {
  137. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
  138. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewPlayerReady];
  139. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent
  140. uniqueId:@""
  141. splitPoint:kSCCameraSubmetricsPreCaptureOperationFinished
  142. time:time];
  143. }
  144. - (void)logCameraCaptureFinishedWithDuration:(CFTimeInterval)duration
  145. {
  146. [[SCLogger sharedInstance]
  147. updateLogTimedEvent:kSCCameraCaptureDelayEvent
  148. uniqueId:@""
  149. update:^(NSMutableDictionary *startParameters) {
  150. NSMutableDictionary *eventParameters =
  151. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  152. [eventParameters setObject:@(SCTimeInMillisecond(duration)) forKey:@"content_duration"];
  153. }];
  154. }
  155. - (void)logCameraCaptureContentReady
  156. {
  157. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraCaptureContentReady];
  158. [[SCLogger sharedInstance] updateLogTimedEvent:kSCCameraCaptureDelayEvent
  159. uniqueId:@""
  160. splitPoint:kSCCameraSubmetricsCameraCaptureContentReady];
  161. }
  162. - (void)logPreviewFinishedPreparation
  163. {
  164. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewFinishPreparation];
  165. [self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewAnimationFinish];
  166. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent
  167. uniqueId:@""
  168. splitPoint:kSCCameraSubmetricsPreviewFinishPreparation];
  169. }
  170. - (void)logPreviewDisplayedForImage:(BOOL)isImage
  171. {
  172. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewLayoutReady];
  173. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewLayoutReady];
  174. }
  175. - (void)logPreviewAnimationComplete:(BOOL)isImage
  176. {
  177. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent
  178. uniqueId:@""
  179. splitPoint:kSCCameraSubmetricsPreviewAnimationFinish];
  180. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewAnimationFinish];
  181. [self logCameraCreationDelayEnd];
  182. [self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent
  183. uniqueId:@""
  184. parameters:@{
  185. @"type" : isImage ? @"image" : @"video",
  186. }
  187. shouldLog:^BOOL(NSDictionary *startParameters) {
  188. // For video, PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH can happen in either
  189. // order. So here we check for existence of this key, and end timer if the other
  190. // event have happened.
  191. NSMutableDictionary *eventParameters =
  192. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  193. return eventParameters[kSCCameraSubmetricsPreviewPlayerReady] != nil;
  194. }];
  195. }
  196. - (void)logPreviewFirstFramePlayed:(BOOL)isImage
  197. {
  198. [self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewPlayerReady];
  199. [self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewPlayerReady];
  200. [self logCameraCreationDelayEnd];
  201. [self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent
  202. uniqueId:@""
  203. parameters:@{
  204. @"type" : isImage ? @"image" : @"video",
  205. }
  206. shouldLog:^BOOL(NSDictionary *startParameters) {
  207. NSMutableDictionary *eventParameters =
  208. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  209. // See the comment above for PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH.
  210. return eventParameters[kSCCameraSubmetricsPreviewAnimationFinish] != nil;
  211. }];
  212. }
  213. - (void)cancelCameraCreationEvent
  214. {
  215. [self cancelLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@""];
  216. }
  217. - (void)logRecordingMayBeTooShortWithMethod:(SCCameraRecordingMethod)method
  218. {
  219. [[SCLogger sharedInstance] cancelLogTimedEvent:kSCCameraMetricsRecordingTooShort uniqueId:@""];
  220. [[SCLogger sharedInstance] logTimedEventStart:kSCCameraMetricsRecordingTooShort
  221. uniqueId:@""
  222. isUniqueEvent:NO
  223. parameters:@{
  224. @"method" : @(method),
  225. @"analytics_version" : kSCCameraRecordingTooShortVersion,
  226. }
  227. shouldLogStartTime:YES];
  228. }
  229. - (void)logRecordingWasTooShortWithFirstFrame:(CMTime)firstFrame
  230. frontFacingCamera:(BOOL)isFrontFacing
  231. cameraFlips:(NSInteger)cameraFlips
  232. {
  233. [self logTimedEventEnd:kSCCameraMetricsRecordingTooShort
  234. uniqueId:@""
  235. update:^(NSDictionary *startParameters, CFTimeInterval eventEndTime, CFTimeInterval adjustedTime) {
  236. NSMutableDictionary *eventParameters =
  237. startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
  238. if (CMTIME_IS_VALID(firstFrame)) {
  239. CFTimeInterval startTime =
  240. [startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue];
  241. CFTimeInterval firstFrameRelative = CMTimeGetSeconds(firstFrame) - startTime;
  242. [eventParameters setObject:@(firstFrameRelative) forKey:@"first_frame_s"];
  243. }
  244. [eventParameters setObject:@(isFrontFacing) forKey:@"is_front_facing"];
  245. if (cameraFlips) {
  246. [eventParameters setObject:@(cameraFlips > 0) forKey:@"has_camera_been_flipped"];
  247. }
  248. }];
  249. }
  250. - (void)logManagedCapturerSettingFailure:(NSString *)settingTask error:(NSError *)error
  251. {
  252. NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
  253. parameters[@"setting_task"] = settingTask;
  254. if (error) {
  255. parameters[@"setting error"] = error;
  256. }
  257. [[SCLogger sharedInstance] logTimedEventEnd:kSCCameraManagedCaptureSettingFailure
  258. uniqueId:@""
  259. parameters:parameters];
  260. }
  261. - (void)logCameraCreationDelaySubMetricsStartWithSignCode:(kSCSignPostCodeEnum)signPostCode
  262. {
  263. if ([self shouldLogCameraCreationDelay]) {
  264. SCTraceSignPostStartForMetrics(signPostCode, 0, 0, 0, 0);
  265. }
  266. }
  267. - (void)logCameraCreationDelaySubMetricsEndWithSignCode:(kSCSignPostCodeEnum)signPostCode
  268. {
  269. if ([self shouldLogCameraCreationDelay]) {
  270. SCTraceSignPostEndForMetrics(signPostCode, 0, 0, 0, 0);
  271. }
  272. }
  273. @end