mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00

git-subtree-dir: submodules/HockeySDK-iOS git-subtree-mainline: 085acd26c4432939403765234266e3c1be0f3dd9 git-subtree-split: c7d0c7026303253e2ac576c02655691e5d314fe2
292 lines
9.5 KiB
Objective-C
292 lines
9.5 KiB
Objective-C
#import "HockeySDK.h"
|
|
|
|
#if HOCKEYSDK_FEATURE_METRICS
|
|
|
|
#import "BITMetricsManager.h"
|
|
#import "BITTelemetryContext.h"
|
|
#import "BITMetricsManagerPrivate.h"
|
|
#import "BITHockeyHelper.h"
|
|
#import "BITHockeyHelper+Application.h"
|
|
#import "HockeySDKPrivate.h"
|
|
#import "BITChannelPrivate.h"
|
|
#import "BITEventData.h"
|
|
#import "BITSession.h"
|
|
#import "BITSessionState.h"
|
|
#import "BITSessionStateData.h"
|
|
#import "BITPersistencePrivate.h"
|
|
#import "BITHockeyBaseManagerPrivate.h"
|
|
#import "BITSender.h"
|
|
|
|
NSString *const kBITApplicationWasLaunched = @"BITApplicationWasLaunched";
|
|
|
|
static char *const kBITMetricsEventQueue = "net.hockeyapp.telemetryEventQueue";
|
|
|
|
static NSString *const kBITSessionFileType = @"plist";
|
|
static NSString *const kBITApplicationDidEnterBackgroundTime = @"BITApplicationDidEnterBackgroundTime";
|
|
|
|
static NSString *const BITMetricsBaseURLString = @"https://gate.hockeyapp.net/";
|
|
static NSString *const BITMetricsURLPathString = @"v2/track";
|
|
|
|
@interface BITMetricsManager ()
|
|
|
|
@property (nonatomic, strong) id<NSObject> appWillEnterForegroundObserver;
|
|
@property (nonatomic, strong) id<NSObject> appDidEnterBackgroundObserver;
|
|
|
|
@end
|
|
|
|
@implementation BITMetricsManager
|
|
|
|
@synthesize channel = _channel;
|
|
@synthesize telemetryContext = _telemetryContext;
|
|
@synthesize persistence = _persistence;
|
|
@synthesize serverURL = _serverURL;
|
|
@synthesize userDefaults = _userDefaults;
|
|
|
|
#pragma mark - Create & start instance
|
|
|
|
- (instancetype)init {
|
|
if ((self = [super init])) {
|
|
_disabled = NO;
|
|
_metricsEventQueue = dispatch_queue_create(kBITMetricsEventQueue, DISPATCH_QUEUE_CONCURRENT);
|
|
_appBackgroundTimeBeforeSessionExpires = 20;
|
|
_serverURL = [NSString stringWithFormat:@"%@%@", BITMetricsBaseURLString, BITMetricsURLPathString];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithChannel:(BITChannel *)channel telemetryContext:(BITTelemetryContext *)telemetryContext persistence:(BITPersistence *)persistence userDefaults:(NSUserDefaults *)userDefaults {
|
|
if ((self = [self init])) {
|
|
_channel = channel;
|
|
_telemetryContext = telemetryContext;
|
|
_persistence = persistence;
|
|
_userDefaults = userDefaults;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)startManager {
|
|
self.sender = [[BITSender alloc] initWithPersistence:self.persistence serverURL:(NSURL *)[NSURL URLWithString:self.serverURL]];
|
|
[self.sender sendSavedDataAsync];
|
|
[self startNewSessionWithId:bit_UUID()];
|
|
[self registerObservers];
|
|
}
|
|
|
|
#pragma mark - Configuration
|
|
|
|
- (void)setDisabled:(BOOL)disabled {
|
|
if (_disabled == disabled) { return; }
|
|
_disabled = disabled;
|
|
if (disabled) {
|
|
[self unregisterObservers];
|
|
} else {
|
|
[self startManager];
|
|
}
|
|
}
|
|
|
|
#pragma mark - Sessions
|
|
|
|
- (void)registerObservers {
|
|
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
if (nil == self.appDidEnterBackgroundObserver) {
|
|
self.appDidEnterBackgroundObserver =
|
|
[center addObserverForName:UIApplicationDidEnterBackgroundNotification
|
|
object:nil
|
|
queue:NSOperationQueue.mainQueue
|
|
usingBlock:^(NSNotification __unused *note) {
|
|
typeof(self) strongSelf = weakSelf;
|
|
[strongSelf updateDidEnterBackgroundTime];
|
|
}];
|
|
}
|
|
if (nil == self.appWillEnterForegroundObserver) {
|
|
self.appWillEnterForegroundObserver =
|
|
[center addObserverForName:UIApplicationWillEnterForegroundNotification
|
|
object:nil
|
|
queue:NSOperationQueue.mainQueue
|
|
usingBlock:^(NSNotification __unused *note) {
|
|
typeof(self) strongSelf = weakSelf;
|
|
[strongSelf startNewSessionIfNeeded];
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (void)unregisterObservers {
|
|
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
|
id appDidEnterBackgroundObserver = self.appDidEnterBackgroundObserver;
|
|
if(appDidEnterBackgroundObserver) {
|
|
[center removeObserver:appDidEnterBackgroundObserver];
|
|
self.appDidEnterBackgroundObserver = nil;
|
|
}
|
|
id appWillEnterForegroundObserver = self.appWillEnterForegroundObserver;
|
|
if(appWillEnterForegroundObserver) {
|
|
[center removeObserver:appWillEnterForegroundObserver];
|
|
self.appWillEnterForegroundObserver = nil;
|
|
}
|
|
}
|
|
|
|
- (void)updateDidEnterBackgroundTime {
|
|
[self.userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kBITApplicationDidEnterBackgroundTime];
|
|
}
|
|
|
|
- (void)startNewSessionIfNeeded {
|
|
double appDidEnterBackgroundTime = [self.userDefaults doubleForKey:kBITApplicationDidEnterBackgroundTime];
|
|
// Add safeguard in case this returns a negative value
|
|
if(appDidEnterBackgroundTime < 0) {
|
|
appDidEnterBackgroundTime = 0;
|
|
[self.userDefaults setDouble:0 forKey:kBITApplicationDidEnterBackgroundTime];
|
|
}
|
|
double timeSinceLastBackground = [[NSDate date] timeIntervalSince1970] - appDidEnterBackgroundTime;
|
|
if (timeSinceLastBackground > self.appBackgroundTimeBeforeSessionExpires) {
|
|
[self startNewSessionWithId:bit_UUID()];
|
|
}
|
|
}
|
|
|
|
- (void)startNewSessionWithId:(NSString *)sessionId {
|
|
BITSession *newSession = [self createNewSessionWithId:sessionId];
|
|
[self.telemetryContext setSessionId:newSession.sessionId];
|
|
[self.telemetryContext setIsFirstSession:newSession.isFirst];
|
|
[self.telemetryContext setIsNewSession:newSession.isNew];
|
|
[self trackSessionWithState:BITSessionState_start];
|
|
}
|
|
|
|
- (BITSession *)createNewSessionWithId:(NSString *)sessionId {
|
|
BITSession *session = [BITSession new];
|
|
session.sessionId = sessionId;
|
|
session.isNew = @"true";
|
|
|
|
if (![self.userDefaults boolForKey:kBITApplicationWasLaunched]) {
|
|
session.isFirst = @"true";
|
|
[self.userDefaults setBool:YES forKey:kBITApplicationWasLaunched];
|
|
} else {
|
|
session.isFirst = @"false";
|
|
}
|
|
return session;
|
|
}
|
|
|
|
#pragma mark - Track telemetry
|
|
|
|
#pragma mark Sessions
|
|
|
|
- (void)trackSessionWithState:(BITSessionState)state {
|
|
if (self.disabled) {
|
|
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
|
|
return;
|
|
}
|
|
BITSessionStateData *sessionStateData = [BITSessionStateData new];
|
|
sessionStateData.state = state;
|
|
[self.channel enqueueTelemetryItem:sessionStateData];
|
|
}
|
|
|
|
#pragma mark Events
|
|
|
|
- (void)trackEventWithName:(nonnull NSString *)eventName {
|
|
if (!eventName) {
|
|
return;
|
|
}
|
|
if (self.disabled) {
|
|
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
|
|
return;
|
|
}
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
dispatch_group_t group = dispatch_group_create();
|
|
dispatch_group_async(group, self.metricsEventQueue, ^{
|
|
typeof(self) strongSelf = weakSelf;
|
|
BITEventData *eventData = [BITEventData new];
|
|
[eventData setName:eventName];
|
|
[strongSelf trackDataItem:eventData];
|
|
});
|
|
|
|
// If the app is running in the background.
|
|
UIApplication *application = [UIApplication sharedApplication];
|
|
BOOL applicationIsInBackground = ([BITHockeyHelper applicationState] == BITApplicationStateBackground);
|
|
if (applicationIsInBackground) {
|
|
[self.channel createBackgroundTaskWhileDataIsSending:application withWaitingGroup:group];
|
|
}
|
|
}
|
|
|
|
- (void)trackEventWithName:(nonnull NSString *)eventName
|
|
properties:(nullable NSDictionary<NSString *, NSString *> *)properties
|
|
measurements:(nullable NSDictionary<NSString *, NSNumber *> *)measurements {
|
|
if (!eventName) {
|
|
return;
|
|
}
|
|
if (self.disabled) {
|
|
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
|
|
return;
|
|
}
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
dispatch_group_t group = dispatch_group_create();
|
|
dispatch_group_async(group, self.metricsEventQueue, ^{
|
|
typeof(self) strongSelf = weakSelf;
|
|
BITEventData *eventData = [BITEventData new];
|
|
[eventData setName:eventName];
|
|
[eventData setProperties:(NSDictionary *)properties];
|
|
[eventData setMeasurements:measurements];
|
|
[strongSelf trackDataItem:eventData];
|
|
});
|
|
|
|
// If the app is running in the background.
|
|
UIApplication *application = [UIApplication sharedApplication];
|
|
BOOL applicationIsInBackground = ([BITHockeyHelper applicationState] == BITApplicationStateBackground);
|
|
if (applicationIsInBackground) {
|
|
[self.channel createBackgroundTaskWhileDataIsSending:application withWaitingGroup:group];
|
|
}
|
|
}
|
|
|
|
#pragma mark Track DataItem
|
|
|
|
- (void)trackDataItem:(BITTelemetryData *)dataItem {
|
|
if (self.disabled) {
|
|
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
|
|
return;
|
|
}
|
|
|
|
BITHockeyLogDebug(@"INFO: Enqueue telemetry item: %@", dataItem.name);
|
|
[self.channel enqueueTelemetryItem:dataItem];
|
|
}
|
|
|
|
#pragma mark - Custom getter
|
|
|
|
- (BITChannel *)channel {
|
|
@synchronized(self) {
|
|
if (!_channel) {
|
|
_channel = [[BITChannel alloc] initWithTelemetryContext:self.telemetryContext persistence:self.persistence];
|
|
}
|
|
return _channel;
|
|
}
|
|
}
|
|
|
|
- (BITTelemetryContext *)telemetryContext {
|
|
@synchronized(self) {
|
|
if (!_telemetryContext) {
|
|
_telemetryContext = [[BITTelemetryContext alloc] initWithAppIdentifier:self.appIdentifier persistence:self.persistence];
|
|
}
|
|
return _telemetryContext;
|
|
}
|
|
}
|
|
|
|
- (BITPersistence *)persistence {
|
|
@synchronized(self) {
|
|
if (!_persistence) {
|
|
_persistence = [BITPersistence new];
|
|
}
|
|
return _persistence;
|
|
}
|
|
}
|
|
|
|
- (NSUserDefaults *)userDefaults {
|
|
@synchronized(self) {
|
|
if (!_userDefaults) {
|
|
_userDefaults = [NSUserDefaults standardUserDefaults];
|
|
}
|
|
return _userDefaults;
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
#endif /* HOCKEYSDK_FEATURE_METRICS */
|