Jonny Banana
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 750 additions and 0 deletions
-
66Logging/SCCoreCameraLogger.h
-
304Logging/SCCoreCameraLogger.m
-
53Logging/SCLogger+Camera.h
-
303Logging/SCLogger+Camera.m
-
24Logging/SCManiphestTicketCreator.h
@ -0,0 +1,66 @@ |
|||||
|
// |
||||
|
// SCCoreCameraLogger.h |
||||
|
// Snapchat |
||||
|
// |
||||
|
// Created by Chao Pang on 3/6/18. |
||||
|
// |
||||
|
|
||||
|
#import <Foundation/Foundation.h> |
||||
|
|
||||
|
/** |
||||
|
* CAMERA_CREATION_DELAY event |
||||
|
*/ |
||||
|
extern NSString *const kSCCameraCreationDelayEventStartTimeKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventStartTimeAdjustmentKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventEndTimeKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventCaptureSessionIdKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventFilterLensIdKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventNightModeDetectedKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventNightModeActiveKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventCameraApiKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventCameraLevelKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventCameraPositionKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventCameraOpenSourceKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventContentDurationKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventMediaTypeKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventStartTypeKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventStartSubTypeKey; |
||||
|
extern NSString *const kSCCameraCreationDelayEventAnalyticsVersion; |
||||
|
|
||||
|
@interface SCCoreCameraLogger : NSObject |
||||
|
|
||||
|
+ (instancetype)sharedInstance; |
||||
|
|
||||
|
/** |
||||
|
* CAMERA_CREATION_DELAY event |
||||
|
*/ |
||||
|
- (void)logCameraCreationDelayEventStartWithCaptureSessionId:(NSString *)captureSessionId |
||||
|
filterLensId:(NSString *)filterLensId |
||||
|
underLowLightCondition:(BOOL)underLowLightCondition |
||||
|
isNightModeActive:(BOOL)isNightModeActive |
||||
|
isBackCamera:(BOOL)isBackCamera |
||||
|
isMainCamera:(BOOL)isMainCamera; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointRecordingGestureFinished; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointStillImageCaptureApi:(NSString *)api; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreCaptureOperationRequested; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreCaptureOperationFinishedAt:(CFTimeInterval)time; |
||||
|
|
||||
|
- (void)updatedCameraCreationDelayWithContentDuration:(CFTimeInterval)duration; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointCameraCaptureContentReady; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewFinishedPreparation; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewDisplayedForImage:(BOOL)isImage; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewAnimationComplete:(BOOL)isImage; |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewFirstFramePlayed:(BOOL)isImage; |
||||
|
|
||||
|
- (void)cancelCameraCreationDelayEvent; |
||||
|
|
||||
|
@end |
@ -0,0 +1,304 @@ |
|||||
|
// |
||||
|
// SCCoreCameraLogger.m |
||||
|
// Snapchat |
||||
|
// |
||||
|
// Created by Chao Pang on 3/6/18. |
||||
|
// |
||||
|
|
||||
|
#import "SCCoreCameraLogger.h" |
||||
|
|
||||
|
#import <BlizzardSchema/SCAEvents.h> |
||||
|
#import <SCFoundation/SCQueuePerformer.h> |
||||
|
#import <SCGhostToSnappable/SCGhostToSnappableSignal.h> |
||||
|
#import <SCLogger/SCCameraMetrics+CameraCreationDelay.h> |
||||
|
|
||||
|
static const char *kSCCoreCameraLoggerQueueLabel = "com.snapchat.core-camera-logger-queue"; |
||||
|
|
||||
|
NSString *const kSCCameraCreationDelayEventStartTimeKey = @"start_time"; |
||||
|
NSString *const kSCCameraCreationDelayEventStartTimeAdjustmentKey = @"start_time_adjustment"; |
||||
|
NSString *const kSCCameraCreationDelayEventEndTimeKey = @"end_time"; |
||||
|
NSString *const kSCCameraCreationDelayEventCaptureSessionIdKey = @"capture_session_id"; |
||||
|
NSString *const kSCCameraCreationDelayEventFilterLensIdKey = @"filter_lens_id"; |
||||
|
NSString *const kSCCameraCreationDelayEventNightModeDetectedKey = @"night_mode_detected"; |
||||
|
NSString *const kSCCameraCreationDelayEventNightModeActiveKey = @"night_mode_active"; |
||||
|
NSString *const kSCCameraCreationDelayEventCameraApiKey = @"camera_api"; |
||||
|
NSString *const kSCCameraCreationDelayEventCameraLevelKey = @"camera_level"; |
||||
|
NSString *const kSCCameraCreationDelayEventCameraPositionKey = @"camera_position"; |
||||
|
NSString *const kSCCameraCreationDelayEventCameraOpenSourceKey = @"camera_open_source"; |
||||
|
NSString *const kSCCameraCreationDelayEventContentDurationKey = @"content_duration"; |
||||
|
NSString *const kSCCameraCreationDelayEventMediaTypeKey = @"media_type"; |
||||
|
NSString *const kSCCameraCreationDelayEventStartTypeKey = @"start_type"; |
||||
|
NSString *const kSCCameraCreationDelayEventStartSubTypeKey = @"start_sub_type"; |
||||
|
NSString *const kSCCameraCreationDelayEventAnalyticsVersion = @"ios_v1"; |
||||
|
|
||||
|
static inline NSUInteger SCTimeToMS(CFTimeInterval time) |
||||
|
{ |
||||
|
return (NSUInteger)(time * 1000); |
||||
|
} |
||||
|
|
||||
|
static NSString *SCDictionaryToJSONString(NSDictionary *dictionary) |
||||
|
{ |
||||
|
NSData *dictData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; |
||||
|
return [[NSString alloc] initWithData:dictData encoding:NSUTF8StringEncoding]; |
||||
|
} |
||||
|
|
||||
|
@implementation SCCoreCameraLogger { |
||||
|
SCQueuePerformer *_performer; |
||||
|
NSMutableDictionary *_cameraCreationDelayParameters; |
||||
|
NSMutableDictionary *_cameraCreationDelaySplits; |
||||
|
} |
||||
|
|
||||
|
- (instancetype)init |
||||
|
{ |
||||
|
self = [super init]; |
||||
|
if (self) { |
||||
|
_cameraCreationDelayParameters = [NSMutableDictionary dictionary]; |
||||
|
_cameraCreationDelaySplits = [NSMutableDictionary dictionary]; |
||||
|
_performer = [[SCQueuePerformer alloc] initWithLabel:kSCCoreCameraLoggerQueueLabel |
||||
|
qualityOfService:QOS_CLASS_UNSPECIFIED |
||||
|
queueType:DISPATCH_QUEUE_SERIAL |
||||
|
context:SCQueuePerformerContextCoreCamera]; |
||||
|
} |
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
+ (instancetype)sharedInstance |
||||
|
{ |
||||
|
static SCCoreCameraLogger *sharedInstance; |
||||
|
static dispatch_once_t onceToken; |
||||
|
dispatch_once(&onceToken, ^{ |
||||
|
sharedInstance = [[SCCoreCameraLogger alloc] init]; |
||||
|
}); |
||||
|
return sharedInstance; |
||||
|
} |
||||
|
|
||||
|
// Camera creation delay metrics |
||||
|
|
||||
|
- (void)logCameraCreationDelayEventStartWithCaptureSessionId:(NSString *)captureSessionId |
||||
|
filterLensId:(NSString *)filterLensId |
||||
|
underLowLightCondition:(BOOL)underLowLightCondition |
||||
|
isNightModeActive:(BOOL)isNightModeActive |
||||
|
isBackCamera:(BOOL)isBackCamera |
||||
|
isMainCamera:(BOOL)isMainCamera |
||||
|
{ |
||||
|
CFTimeInterval startTime = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[_cameraCreationDelayParameters removeAllObjects]; |
||||
|
[_cameraCreationDelaySplits removeAllObjects]; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeKey] = @(startTime); |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventCaptureSessionIdKey] = captureSessionId ?: @"null"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventFilterLensIdKey] = filterLensId ?: @"null"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeDetectedKey] = @(underLowLightCondition); |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeActiveKey] = @(isNightModeActive); |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraPositionKey] = |
||||
|
isBackCamera ? @"back" : @"front"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraOpenSourceKey] = |
||||
|
isMainCamera ? @"main_camera" : @"reply_camera"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTypeKey] = SCLaunchType() ?: @"null"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartSubTypeKey] = SCLaunchSubType() ?: @"null"; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointRecordingGestureFinished |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
CFTimeInterval endRecordingTimeOffset = |
||||
|
time - [_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeKey] doubleValue]; |
||||
|
NSNumber *recordStartTimeMillis = |
||||
|
(NSNumber *)_cameraCreationDelaySplits[kSCCameraSubmetricsPreCaptureOperationFinished]; |
||||
|
if (recordStartTimeMillis) { |
||||
|
CFTimeInterval timeDisplacement = ([recordStartTimeMillis doubleValue] / 1000.0) - endRecordingTimeOffset; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeAdjustmentKey] = @(timeDisplacement); |
||||
|
} |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsRecordingGestureFinished atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointStillImageCaptureApi:(NSString *)api |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
if (api) { |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraApiKey] = api; |
||||
|
} |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreCaptureOperationRequested atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreCaptureOperationRequested |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreCaptureOperationRequested atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreCaptureOperationFinishedAt:(CFTimeInterval)time |
||||
|
{ |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreCaptureOperationFinished atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)updatedCameraCreationDelayWithContentDuration:(CFTimeInterval)duration |
||||
|
{ |
||||
|
[_performer perform:^{ |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventContentDurationKey] = @(SCTimeToMS(duration)); |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointCameraCaptureContentReady |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsCameraCaptureContentReady atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewFinishedPreparation |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsCameraCaptureContentReady atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewDisplayedForImage:(BOOL)isImage |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreviewLayoutReady atTime:time]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewAnimationComplete:(BOOL)isImage |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreviewAnimationFinish atTime:time]; |
||||
|
if (_cameraCreationDelaySplits[kSCCameraSubmetricsPreviewPlayerReady]) { |
||||
|
[self _completeLogCameraCreationDelayEventWithIsImage:isImage atTime:time]; |
||||
|
} |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySplitPointPreviewFirstFramePlayed:(BOOL)isImage |
||||
|
{ |
||||
|
CFTimeInterval time = CACurrentMediaTime(); |
||||
|
[_performer perform:^{ |
||||
|
[self _addSplitPointForKey:kSCCameraSubmetricsPreviewPlayerReady atTime:time]; |
||||
|
if (_cameraCreationDelaySplits[kSCCameraSubmetricsPreviewAnimationFinish]) { |
||||
|
[self _completeLogCameraCreationDelayEventWithIsImage:isImage atTime:time]; |
||||
|
} |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)cancelCameraCreationDelayEvent |
||||
|
{ |
||||
|
[_performer perform:^{ |
||||
|
[_cameraCreationDelayParameters removeAllObjects]; |
||||
|
[_cameraCreationDelaySplits removeAllObjects]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
#pragma - Private methods |
||||
|
|
||||
|
- (void)_completeLogCameraCreationDelayEventWithIsImage:(BOOL)isImage atTime:(CFTimeInterval)time |
||||
|
{ |
||||
|
SCAssertPerformer(_performer); |
||||
|
if (_cameraCreationDelayParameters[kSCCameraCreationDelayEventCaptureSessionIdKey]) { |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventMediaTypeKey] = isImage ? @"image" : @"video"; |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventEndTimeKey] = @(time); |
||||
|
[self _logCameraCreationDelayBlizzardEvent]; |
||||
|
} |
||||
|
[_cameraCreationDelayParameters removeAllObjects]; |
||||
|
[_cameraCreationDelaySplits removeAllObjects]; |
||||
|
} |
||||
|
|
||||
|
- (void)_addSplitPointForKey:(NSString *)key atTime:(CFTimeInterval)time |
||||
|
{ |
||||
|
SCAssertPerformer(_performer); |
||||
|
if (key) { |
||||
|
CFTimeInterval timeOffset = |
||||
|
time - [_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeKey] doubleValue]; |
||||
|
NSNumber *timeAdjustment = |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeAdjustmentKey] ?: @(0); |
||||
|
_cameraCreationDelaySplits[key] = @(SCTimeToMS(timeOffset + [timeAdjustment doubleValue])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
- (void)_logCameraCreationDelayBlizzardEvent |
||||
|
{ |
||||
|
SCAssertPerformer(_performer); |
||||
|
SCASharedCameraMetricParams *sharedCameraMetricsParams = [[SCASharedCameraMetricParams alloc] init]; |
||||
|
[sharedCameraMetricsParams setAnalyticsVersion:kSCCameraCreationDelayEventAnalyticsVersion]; |
||||
|
NSString *mediaType = _cameraCreationDelayParameters[kSCCameraCreationDelayEventMediaTypeKey]; |
||||
|
if (mediaType) { |
||||
|
if ([mediaType isEqualToString:@"image"]) { |
||||
|
[sharedCameraMetricsParams setMediaType:SCAMediaType_IMAGE]; |
||||
|
} else if ([mediaType isEqualToString:@"video"]) { |
||||
|
[sharedCameraMetricsParams setMediaType:SCAMediaType_VIDEO]; |
||||
|
} |
||||
|
} |
||||
|
if (_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeDetectedKey] && |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeActiveKey]) { |
||||
|
BOOL isNightModeDetected = |
||||
|
[_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeDetectedKey] boolValue]; |
||||
|
BOOL isNightModeActive = |
||||
|
[_cameraCreationDelayParameters[kSCCameraCreationDelayEventNightModeActiveKey] boolValue]; |
||||
|
if (!isNightModeDetected) { |
||||
|
[sharedCameraMetricsParams setLowLightStatus:SCALowLightStatus_NOT_DETECTED]; |
||||
|
} else if (!isNightModeActive) { |
||||
|
[sharedCameraMetricsParams setLowLightStatus:SCALowLightStatus_DETECTED]; |
||||
|
} else if (isNightModeActive) { |
||||
|
[sharedCameraMetricsParams setLowLightStatus:SCALowLightStatus_ENABLED]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[sharedCameraMetricsParams setPowerMode:[[NSProcessInfo processInfo] isLowPowerModeEnabled] |
||||
|
? @"LOW_POWER_MODE_ENABLED" |
||||
|
: @"LOW_POWER_MODE_DISABLED"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setFilterLensId:_cameraCreationDelayParameters[kSCCameraCreationDelayEventFilterLensIdKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setCaptureSessionId:_cameraCreationDelayParameters[kSCCameraCreationDelayEventCaptureSessionIdKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setCameraApi:_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraApiKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setCameraPosition:_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraPositionKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setCameraOpenSource:_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraOpenSourceKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setCameraLevel:_cameraCreationDelayParameters[kSCCameraCreationDelayEventCameraLevelKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setStartType:_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTypeKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams |
||||
|
setStartSubType:_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartSubTypeKey] ?: @"null"]; |
||||
|
[sharedCameraMetricsParams setSplits:SCDictionaryToJSONString(_cameraCreationDelaySplits)]; |
||||
|
|
||||
|
SCACameraSnapCreateDelay *creationDelay = [[SCACameraSnapCreateDelay alloc] init]; |
||||
|
if (_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeKey] && |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventEndTimeKey]) { |
||||
|
double startTime = [_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeKey] doubleValue]; |
||||
|
double endTime = [_cameraCreationDelayParameters[kSCCameraCreationDelayEventEndTimeKey] doubleValue]; |
||||
|
NSNumber *timeAdjustment = |
||||
|
_cameraCreationDelayParameters[kSCCameraCreationDelayEventStartTimeAdjustmentKey] ?: @(0); |
||||
|
[creationDelay setLatencyMillis:SCTimeToMS(endTime - startTime + [timeAdjustment doubleValue])]; |
||||
|
} else { |
||||
|
[creationDelay setLatencyMillis:0]; |
||||
|
} |
||||
|
|
||||
|
if (_cameraCreationDelayParameters[kSCCameraCreationDelayEventContentDurationKey]) { |
||||
|
[creationDelay |
||||
|
setContentDurationMillis:SCTimeToMS( |
||||
|
[_cameraCreationDelayParameters[kSCCameraCreationDelayEventContentDurationKey] |
||||
|
doubleValue])]; |
||||
|
} else { |
||||
|
[creationDelay setContentDurationMillis:0]; |
||||
|
} |
||||
|
[creationDelay setSharedCameraMetricParams:sharedCameraMetricsParams]; |
||||
|
[[SCLogger sharedInstance] logUserTrackedEvent:creationDelay]; |
||||
|
} |
||||
|
|
||||
|
@end |
@ -0,0 +1,53 @@ |
|||||
|
// |
||||
|
// SCLogger+Camera.h |
||||
|
// Snapchat |
||||
|
// |
||||
|
// Created by Derek Peirce on 5/8/17. |
||||
|
// Copyright © 2017 Snapchat, Inc. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
#import "AVCameraViewEnums.h" |
||||
|
|
||||
|
#import <SCBase/SCSignPost.h> |
||||
|
#import <SCLogger/SCLogger.h> |
||||
|
|
||||
|
#import <CoreMedia/CoreMedia.h> |
||||
|
|
||||
|
typedef NS_ENUM(NSUInteger, CameraCreationDelayLoggingStatus) { |
||||
|
CAMERA_CREATION_DELAY_LOGGING_START, |
||||
|
CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP, |
||||
|
CAMERA_CREATION_DELAY_LOGGING_END, |
||||
|
}; |
||||
|
|
||||
|
@interface SCLogger (Camera) |
||||
|
|
||||
|
@property (nonatomic, strong) NSNumber *cameraCreationDelayLoggingStatus; |
||||
|
|
||||
|
- (void)logCameraCreationStartWithMethod:(SCCameraRecordingMethod)method |
||||
|
lensesEnabled:(BOOL)lensesEnabled |
||||
|
activeLensId:(NSString *)activeLensId |
||||
|
captureSessionId:(NSString *)captureSessionId; |
||||
|
- (void)logStillImageCaptureApi:(NSString *)api; |
||||
|
- (void)logPreCaptureOperationRequestedAt:(CFTimeInterval)requestTime; |
||||
|
- (void)logPreCaptureOperationFinishedAt:(CFTimeInterval)time; |
||||
|
- (void)logCameraCaptureRecordingGestureFinishedAtTime:(CFTimeInterval)endRecordingTime; |
||||
|
- (void)logCameraCaptureFinishedWithDuration:(CFTimeInterval)duration; |
||||
|
- (void)logCameraCaptureContentReady; |
||||
|
- (void)logPreviewFinishedPreparation; |
||||
|
- (void)logPreviewDisplayedForImage:(BOOL)isImage; |
||||
|
- (void)logPreviewAnimationComplete:(BOOL)isImage; |
||||
|
- (void)logPreviewFirstFramePlayed:(BOOL)isImage; |
||||
|
- (void)cancelCameraCreationEvent; |
||||
|
|
||||
|
- (void)logRecordingMayBeTooShortWithMethod:(SCCameraRecordingMethod)method; |
||||
|
- (void)logRecordingWasTooShortWithFirstFrame:(CMTime)firstFrame |
||||
|
frontFacingCamera:(BOOL)isFrontFacing |
||||
|
cameraFlips:(NSInteger)cameraFlips; |
||||
|
|
||||
|
- (void)logManagedCapturerSettingFailure:(NSString *)settingTask error:(NSError *)error; |
||||
|
- (void)logCameraExposureAdjustmentDelayStart; |
||||
|
- (void)logCameraExposureAdjustmentDelayEndWithStrategy:(NSString *)strategy; |
||||
|
- (void)logCameraCreationDelaySubMetricsStartWithSignCode:(kSCSignPostCodeEnum)signPostCode; |
||||
|
- (void)logCameraCreationDelaySubMetricsEndWithSignCode:(kSCSignPostCodeEnum)signPostCod; |
||||
|
|
||||
|
@end |
@ -0,0 +1,303 @@ |
|||||
|
// |
||||
|
// SCLogger+Camera.m |
||||
|
// Snapchat |
||||
|
// |
||||
|
// Created by Derek Peirce on 5/8/17. |
||||
|
// Copyright © 2017 Snapchat, Inc. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
#import "SCLogger+Camera.h" |
||||
|
|
||||
|
#import "SCCameraTweaks.h" |
||||
|
|
||||
|
#import <SCFoundation/SCTrace.h> |
||||
|
#import <SCFoundation/SCTraceODPCompatible.h> |
||||
|
#import <SCLogger/SCCameraMetrics+CameraCreationDelay.h> |
||||
|
#import <SCLogger/SCCameraMetrics.h> |
||||
|
#import <SCLogger/SCLogger+Performance.h> |
||||
|
|
||||
|
#import <objc/runtime.h> |
||||
|
|
||||
|
@implementation SCLogger (Camera) |
||||
|
|
||||
|
@dynamic cameraCreationDelayLoggingStatus; |
||||
|
|
||||
|
- (NSNumber *)cameraCreationDelayLoggingStatus |
||||
|
{ |
||||
|
return objc_getAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus)); |
||||
|
} |
||||
|
|
||||
|
- (void)setCameraCreationDelayLoggingStatus:(NSNumber *)status |
||||
|
{ |
||||
|
objc_setAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus), status, |
||||
|
OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
||||
|
} |
||||
|
|
||||
|
- (BOOL)shouldLogCameraCreationDelay |
||||
|
{ |
||||
|
return [[self cameraCreationDelayLoggingStatus] intValue] != CAMERA_CREATION_DELAY_LOGGING_END; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelayEnd |
||||
|
{ |
||||
|
if ([[self cameraCreationDelayLoggingStatus] intValue] == CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP) { |
||||
|
SCTraceSignPostEndForMetrics(kSCSignPostCameraCreationDelay, 0, 0, 0, 0); |
||||
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_END)]; |
||||
|
} else { |
||||
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP)]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationStartWithMethod:(SCCameraRecordingMethod)method |
||||
|
lensesEnabled:(BOOL)lensesEnabled |
||||
|
activeLensId:(NSString *)activeLensId |
||||
|
captureSessionId:(NSString *)captureSessionId |
||||
|
{ |
||||
|
NSMutableDictionary *parameters = [@{ |
||||
|
@"lens_ui_enabled" : @(lensesEnabled), |
||||
|
@"analytics_version" : kSCCameraDelayEventVersion, |
||||
|
@"method" : @(method), |
||||
|
} mutableCopy]; |
||||
|
if (lensesEnabled && activeLensId) { |
||||
|
[parameters setObject:activeLensId forKey:@"lens_id"]; |
||||
|
} |
||||
|
if (captureSessionId) { |
||||
|
[parameters setObject:captureSessionId forKey:@"capture_session_id"]; |
||||
|
} |
||||
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_START)]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCreationDelay]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraRecordingGestureFinished]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationRequested]; |
||||
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
isUniqueEvent:NO |
||||
|
parameters:parameters |
||||
|
shouldLogStartTime:YES]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraExposureAdjustmentDelayStart |
||||
|
{ |
||||
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraExposureAdjustmentDelay |
||||
|
uniqueId:@"" |
||||
|
isUniqueEvent:NO |
||||
|
parameters:nil |
||||
|
shouldLogStartTime:YES]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraExposureAdjustmentDelayEndWithStrategy:(NSString *)strategy |
||||
|
{ |
||||
|
[[SCLogger sharedInstance] logTimedEventEnd:kSCCameraExposureAdjustmentDelay |
||||
|
uniqueId:@"" |
||||
|
parameters:@{ |
||||
|
@"strategy" : strategy |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCaptureRecordingGestureFinishedAtTime:(CFTimeInterval)endRecordingTime |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraRecordingGestureFinished]; |
||||
|
[[SCLogger sharedInstance] |
||||
|
updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
update:^(NSMutableDictionary *startParameters) { |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
NSNumber *recordStartTime = |
||||
|
(NSNumber *)eventParameters[kSCCameraSubmetricsPreCaptureOperationFinished]; |
||||
|
CFTimeInterval endRecordingTimeOffset = |
||||
|
endRecordingTime - |
||||
|
[startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue]; |
||||
|
if (recordStartTime) { |
||||
|
CFTimeInterval timeDisplacement = |
||||
|
([recordStartTime doubleValue] / 1000.0) - endRecordingTimeOffset; |
||||
|
[eventParameters setObject:@(timeDisplacement) |
||||
|
forKey:SCPerformanceMetricsKey.kSCLoggerStartEventTimeAdjustmentKey]; |
||||
|
} |
||||
|
[self addSplitPoint:kSCCameraSubmetricsRecordingGestureFinished |
||||
|
atTime:endRecordingTime |
||||
|
toEvent:startParameters]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logStillImageCaptureApi:(NSString *)api |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady]; |
||||
|
CFTimeInterval requestTime = CACurrentMediaTime(); |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
update:^(NSMutableDictionary *startParameters) { |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
[eventParameters setObject:api forKey:@"api_type"]; |
||||
|
[eventParameters setObject:@(1) forKey:@"camera_api_level"]; |
||||
|
[self addSplitPoint:@"PRE_CAPTURE_OPERATION_REQUESTED" |
||||
|
atTime:requestTime |
||||
|
toEvent:startParameters]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreCaptureOperationRequestedAt:(CFTimeInterval)requestTime |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady]; |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
splitPoint:kSCCameraSubmetricsPreCaptureOperationRequested |
||||
|
time:requestTime]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreCaptureOperationFinishedAt:(CFTimeInterval)time |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationFinished]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewPlayerReady]; |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
splitPoint:kSCCameraSubmetricsPreCaptureOperationFinished |
||||
|
time:time]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCaptureFinishedWithDuration:(CFTimeInterval)duration |
||||
|
{ |
||||
|
[[SCLogger sharedInstance] |
||||
|
updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
update:^(NSMutableDictionary *startParameters) { |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
[eventParameters setObject:@(SCTimeInMillisecond(duration)) forKey:@"content_duration"]; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCaptureContentReady |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraCaptureContentReady]; |
||||
|
[[SCLogger sharedInstance] updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
splitPoint:kSCCameraSubmetricsCameraCaptureContentReady]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreviewFinishedPreparation |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewFinishPreparation]; |
||||
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewAnimationFinish]; |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
splitPoint:kSCCameraSubmetricsPreviewFinishPreparation]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreviewDisplayedForImage:(BOOL)isImage |
||||
|
{ |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewLayoutReady]; |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewLayoutReady]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreviewAnimationComplete:(BOOL)isImage |
||||
|
{ |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
splitPoint:kSCCameraSubmetricsPreviewAnimationFinish]; |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewAnimationFinish]; |
||||
|
[self logCameraCreationDelayEnd]; |
||||
|
[self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
parameters:@{ |
||||
|
@"type" : isImage ? @"image" : @"video", |
||||
|
} |
||||
|
shouldLog:^BOOL(NSDictionary *startParameters) { |
||||
|
// For video, PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH can happen in either |
||||
|
// order. So here we check for existence of this key, and end timer if the other |
||||
|
// event have happened. |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
return eventParameters[kSCCameraSubmetricsPreviewPlayerReady] != nil; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logPreviewFirstFramePlayed:(BOOL)isImage |
||||
|
{ |
||||
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewPlayerReady]; |
||||
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewPlayerReady]; |
||||
|
[self logCameraCreationDelayEnd]; |
||||
|
[self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent |
||||
|
uniqueId:@"" |
||||
|
parameters:@{ |
||||
|
@"type" : isImage ? @"image" : @"video", |
||||
|
} |
||||
|
shouldLog:^BOOL(NSDictionary *startParameters) { |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
// See the comment above for PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH. |
||||
|
return eventParameters[kSCCameraSubmetricsPreviewAnimationFinish] != nil; |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)cancelCameraCreationEvent |
||||
|
{ |
||||
|
[self cancelLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@""]; |
||||
|
} |
||||
|
|
||||
|
- (void)logRecordingMayBeTooShortWithMethod:(SCCameraRecordingMethod)method |
||||
|
{ |
||||
|
[[SCLogger sharedInstance] cancelLogTimedEvent:kSCCameraMetricsRecordingTooShort uniqueId:@""]; |
||||
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraMetricsRecordingTooShort |
||||
|
uniqueId:@"" |
||||
|
isUniqueEvent:NO |
||||
|
parameters:@{ |
||||
|
@"method" : @(method), |
||||
|
@"analytics_version" : kSCCameraRecordingTooShortVersion, |
||||
|
} |
||||
|
shouldLogStartTime:YES]; |
||||
|
} |
||||
|
|
||||
|
- (void)logRecordingWasTooShortWithFirstFrame:(CMTime)firstFrame |
||||
|
frontFacingCamera:(BOOL)isFrontFacing |
||||
|
cameraFlips:(NSInteger)cameraFlips |
||||
|
{ |
||||
|
[self logTimedEventEnd:kSCCameraMetricsRecordingTooShort |
||||
|
uniqueId:@"" |
||||
|
update:^(NSDictionary *startParameters, CFTimeInterval eventEndTime, CFTimeInterval adjustedTime) { |
||||
|
NSMutableDictionary *eventParameters = |
||||
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey]; |
||||
|
if (CMTIME_IS_VALID(firstFrame)) { |
||||
|
CFTimeInterval startTime = |
||||
|
[startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue]; |
||||
|
CFTimeInterval firstFrameRelative = CMTimeGetSeconds(firstFrame) - startTime; |
||||
|
[eventParameters setObject:@(firstFrameRelative) forKey:@"first_frame_s"]; |
||||
|
} |
||||
|
[eventParameters setObject:@(isFrontFacing) forKey:@"is_front_facing"]; |
||||
|
if (cameraFlips) { |
||||
|
[eventParameters setObject:@(cameraFlips > 0) forKey:@"has_camera_been_flipped"]; |
||||
|
} |
||||
|
}]; |
||||
|
} |
||||
|
|
||||
|
- (void)logManagedCapturerSettingFailure:(NSString *)settingTask error:(NSError *)error |
||||
|
{ |
||||
|
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; |
||||
|
parameters[@"setting_task"] = settingTask; |
||||
|
if (error) { |
||||
|
parameters[@"setting error"] = error; |
||||
|
} |
||||
|
[[SCLogger sharedInstance] logTimedEventEnd:kSCCameraManagedCaptureSettingFailure |
||||
|
uniqueId:@"" |
||||
|
parameters:parameters]; |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySubMetricsStartWithSignCode:(kSCSignPostCodeEnum)signPostCode |
||||
|
{ |
||||
|
if ([self shouldLogCameraCreationDelay]) { |
||||
|
SCTraceSignPostStartForMetrics(signPostCode, 0, 0, 0, 0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
- (void)logCameraCreationDelaySubMetricsEndWithSignCode:(kSCSignPostCodeEnum)signPostCode |
||||
|
{ |
||||
|
if ([self shouldLogCameraCreationDelay]) { |
||||
|
SCTraceSignPostEndForMetrics(signPostCode, 0, 0, 0, 0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@end |
@ -0,0 +1,24 @@ |
|||||
|
// |
||||
|
// SCManiphestTicketCreator.h |
||||
|
// SCCamera |
||||
|
// |
||||
|
// Created by Michel Loenngren on 4/16/18. |
||||
|
// |
||||
|
|
||||
|
#import <Foundation/Foundation.h> |
||||
|
|
||||
|
/** |
||||
|
Protocol for filing jira tickets and beta s2r. |
||||
|
*/ |
||||
|
@protocol SCManiphestTicketCreator |
||||
|
|
||||
|
- (void)createAndFile:(NSData *)image |
||||
|
creationTime:(long)reportCreationTime |
||||
|
description:(NSString *)bugDescription |
||||
|
email:(NSString *)otherEmail |
||||
|
project:(NSString *)projectName |
||||
|
subproject:(NSString *)subprojectName; |
||||
|
|
||||
|
- (void)createAndFileBetaReport:(NSString *)msg; |
||||
|
|
||||
|
@end |
Write
Preview
Loading…
Cancel
Save
Reference in new issue