mirror of https://github.com/oxen-io/session-ios
				
				
				
			Merge branch 'charlesmchen/analyticsStub'
						commit
						87719a3bfb
					
				| @ -0,0 +1,120 @@ | ||||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import subprocess  | ||||
| import datetime | ||||
| import argparse | ||||
| import commands | ||||
| 
 | ||||
| 
 | ||||
| git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip()) | ||||
| 
 | ||||
| 
 | ||||
| def splitall(path): | ||||
|     allparts = [] | ||||
|     while 1: | ||||
|         parts = os.path.split(path) | ||||
|         if parts[0] == path:  # sentinel for absolute paths | ||||
|             allparts.insert(0, parts[0]) | ||||
|             break | ||||
|         elif parts[1] == path: # sentinel for relative paths | ||||
|             allparts.insert(0, parts[1]) | ||||
|             break | ||||
|         else: | ||||
|             path = parts[0] | ||||
|             allparts.insert(0, parts[1]) | ||||
|     return allparts | ||||
|      | ||||
|      | ||||
| def process(filepath): | ||||
|     with open(filepath, 'rt') as f: | ||||
|         text = f.read() | ||||
|     original_text = text | ||||
|      | ||||
|     lines = text.split('\n') | ||||
|     while lines and lines[0].startswith('//'): | ||||
|         lines = lines[1:] | ||||
|     text = '\n'.join(lines) | ||||
|     text = text.strip() | ||||
| 
 | ||||
|     header = '''// | ||||
| //  Copyright (c) %s Open Whisper Systems. All rights reserved. | ||||
| // | ||||
| 
 | ||||
| ''' % (  | ||||
|     datetime.datetime.now().year, | ||||
|     ) | ||||
|     text = header + text + '\n' | ||||
| 
 | ||||
|     if original_text == text: | ||||
|         return | ||||
|      | ||||
|     short_filepath = filepath[len(git_repo_path):] | ||||
|     if short_filepath.startswith(os.sep): | ||||
|        short_filepath = short_filepath[len(os.sep):]  | ||||
|     print 'Updating:', short_filepath | ||||
|      | ||||
|     with open(filepath, 'wt') as f: | ||||
|         f.write(text) | ||||
| 
 | ||||
| 
 | ||||
| def should_ignore_path(path): | ||||
|     ignore_paths = [ | ||||
|         os.path.join(git_repo_path, '.git') | ||||
|     ] | ||||
|     for ignore_path in ignore_paths: | ||||
|         if path.startswith(ignore_path): | ||||
|             return True | ||||
|     for component in splitall(path): | ||||
|         if component.startswith('.'): | ||||
|             return True | ||||
|         if component.endswith('.framework'): | ||||
|             return True | ||||
|         if component in ('Pods', 'ThirdParty', 'Carthage',): | ||||
|             return True                 | ||||
|          | ||||
|     return False | ||||
|      | ||||
|      | ||||
| def process_if_appropriate(filepath): | ||||
|     filename = os.path.basename(filepath) | ||||
|     if filename.startswith('.'): | ||||
|         return | ||||
|     file_ext = os.path.splitext(filename)[1] | ||||
|     if file_ext not in ('.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift'): | ||||
|         return | ||||
|     if should_ignore_path(filepath): | ||||
|         return | ||||
|     process(filepath) | ||||
| 
 | ||||
|      | ||||
| if __name__ == "__main__": | ||||
|      | ||||
|     parser = argparse.ArgumentParser(description='Precommit script.') | ||||
|     parser.add_argument('--all', action='store_true', help='process all files in or below current dir') | ||||
|     args = parser.parse_args() | ||||
|      | ||||
|     if args.all: | ||||
|         for rootdir, dirnames, filenames in os.walk(git_repo_path): | ||||
|             for filename in filenames: | ||||
|                 file_path = os.path.abspath(os.path.join(rootdir, filename)) | ||||
|                 process_if_appropriate(file_path) | ||||
|     else: | ||||
|         filepaths = [] | ||||
|          | ||||
|         # Staging | ||||
|         output = commands.getoutput('git diff --cached --name-only --diff-filter=ACMR') | ||||
|         filepaths.extend([line.strip() for line in output.split('\n')]) | ||||
| 
 | ||||
|         # Working | ||||
|         output = commands.getoutput('git diff --name-only --diff-filter=ACMR') | ||||
|         filepaths.extend([line.strip() for line in output.split('\n')]) | ||||
|          | ||||
|         # Only process each path once. | ||||
|         filepaths = sorted(set(filepaths)) | ||||
| 
 | ||||
|         for filepath in filepaths: | ||||
|             filepath = os.path.abspath(os.path.join(git_repo_path, filepath)) | ||||
|             process_if_appropriate(filepath) | ||||
| @ -0,0 +1,72 @@ | ||||
| //
 | ||||
| //  OWSAnalytics.h
 | ||||
| //
 | ||||
| //  Copyright (c) 2017 Open Whisper Systems. All rights reserved.
 | ||||
| //
 | ||||
| 
 | ||||
| typedef NS_ENUM(NSUInteger, OWSAnalyticsSeverity) { | ||||
|     OWSAnalyticsSeverityDebug = 0, | ||||
|     OWSAnalyticsSeverityInfo = 1, | ||||
|     OWSAnalyticsSeverityWarn = 2, | ||||
|     OWSAnalyticsSeverityError = 3, | ||||
|     // I suspect we'll stage the development of our analytics,
 | ||||
|     // initially building only a minimal solution: an endpoint which
 | ||||
|     // ignores most requests, and sends only the highest-severity
 | ||||
|     // events as email to developers.
 | ||||
|     //
 | ||||
|     // This "critical" level of severity is intended for that purpose (for now).
 | ||||
|     //
 | ||||
|     // We might want to have an additional level of severity for
 | ||||
|     // critical (crashing) bugs that occur during app startup. These
 | ||||
|     // events should be sent to the service immediately and the app
 | ||||
|     // should block until that request completes.
 | ||||
|     OWSAnalyticsSeverityCritical = 4, | ||||
|     OWSAnalyticsSeverityOff = 5 | ||||
| }; | ||||
| 
 | ||||
| // This is a placeholder. We don't yet serialize or transmit analytics events.
 | ||||
| //
 | ||||
| // If/when we take this on, we'll want to develop a solution that can be used
 | ||||
| // report user activity - especially serious bugs - without compromising user
 | ||||
| // privacy in any way.  We must _never_ include any identifying information.
 | ||||
| @interface OWSAnalytics : NSObject | ||||
| 
 | ||||
| // description: A non-empty string without any leading whitespace.
 | ||||
| // parameters: Optional.
 | ||||
| //             If non-nil, the keys should all be non-empty NSStrings.
 | ||||
| //             Values should be NSStrings or NSNumbers.
 | ||||
| + (void)logEvent:(NSString *)description | ||||
|         severity:(OWSAnalyticsSeverity)severity | ||||
|       parameters:(NSDictionary *)parameters | ||||
|         location:(const char *)location; | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| #define OWSAnalyticsLogEvent(severityLevel, frmt, ...)                                                                 \ | ||||
|     [OWSAnalytics logEvent:[NSString stringWithFormat:frmt, ##__VA_ARGS__]                                             \ | ||||
|                   severity:severityLevel                                                                               \ | ||||
|                 parameters:nil                                                                                         \ | ||||
|                   location:__PRETTY_FUNCTION__]; | ||||
| 
 | ||||
| #define OWSAnalyticsLogEventWithParameters(severityLevel, frmt, params)                                                \ | ||||
|     [OWSAnalytics logEvent:frmt severity:severityLevel parameters:params location:__PRETTY_FUNCTION__]; | ||||
| 
 | ||||
| #define OWSAnalyticsDebug(frmt, ...) OWSAnalyticsLogEvent(OWSAnalyticsSeverityDebug, frmt, ##__VA_ARGS__) | ||||
| #define OWSAnalyticsDebugWithParameters(description, params)                                                           \ | ||||
|     OWSAnalyticsLogEventWithParameters(OWSAnalyticsSeverityDebug, description, params) | ||||
| 
 | ||||
| #define OWSAnalyticsInfo(frmt, ...) OWSAnalyticsLogEvent(OWSAnalyticsSeverityInfo, frmt, ##__VA_ARGS__) | ||||
| #define OWSAnalyticsInfoWithParameters(description, params)                                                            \ | ||||
|     OWSAnalyticsLogEventWithParameters(OWSAnalyticsSeverityInfo, description, params) | ||||
| 
 | ||||
| #define OWSAnalyticsWarn(frmt, ...) OWSAnalyticsLogEvent(OWSAnalyticsSeverityWarn, frmt, ##__VA_ARGS__) | ||||
| #define OWSAnalyticsWarnWithParameters(description, params)                                                            \ | ||||
|     OWSAnalyticsLogEventWithParameters(OWSAnalyticsSeverityWarn, description, params) | ||||
| 
 | ||||
| #define OWSAnalyticsError(frmt, ...) OWSAnalyticsLogEvent(OWSAnalyticsSeverityError, frmt, ##__VA_ARGS__) | ||||
| #define OWSAnalyticsErrorWithParameters(description, params)                                                           \ | ||||
|     OWSAnalyticsLogEventWithParameters(OWSAnalyticsSeverityError, description, params) | ||||
| 
 | ||||
| #define OWSAnalyticsCritical(frmt, ...) OWSAnalyticsLogEvent(OWSAnalyticsSeverityCritical, frmt, ##__VA_ARGS__) | ||||
| #define OWSAnalyticsCriticalWithParameters(description, params)                                                        \ | ||||
|     OWSAnalyticsLogEventWithParameters(OWSAnalyticsSeverityCritical, description, params) | ||||
| @ -0,0 +1,76 @@ | ||||
| // | ||||
| //  OWSAnalytics.m | ||||
| // | ||||
| //  Copyright (c) 2017 Open Whisper Systems. All rights reserved. | ||||
| // | ||||
| 
 | ||||
| #import <CocoaLumberjack/CocoaLumberjack.h> | ||||
| 
 | ||||
| #import "OWSAnalytics.h" | ||||
| 
 | ||||
| @implementation OWSAnalytics | ||||
| 
 | ||||
| + (instancetype)sharedInstance | ||||
| { | ||||
|     static OWSAnalytics *instance = nil; | ||||
|     static dispatch_once_t onceToken; | ||||
|     dispatch_once(&onceToken, ^{ | ||||
|         instance = [self new]; | ||||
|         // TODO: If we ever log these events to disk, | ||||
|         // we may want to protect these file(s) like TSStorageManager. | ||||
|     }); | ||||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| + (void)logEvent:(NSString *)description | ||||
|         severity:(OWSAnalyticsSeverity)severity | ||||
|       parameters:(NSDictionary *)parameters | ||||
|         location:(const char *)location | ||||
| { | ||||
| 
 | ||||
|     [[self sharedInstance] logEvent:description severity:severity parameters:parameters location:location]; | ||||
| } | ||||
| 
 | ||||
| - (void)logEvent:(NSString *)description | ||||
|         severity:(OWSAnalyticsSeverity)severity | ||||
|       parameters:(NSDictionary *)parameters | ||||
|         location:(const char *)location | ||||
| { | ||||
| 
 | ||||
|     DDLogFlag logFlag; | ||||
|     BOOL async = YES; | ||||
|     switch (severity) { | ||||
|         case OWSAnalyticsSeverityDebug: | ||||
|             logFlag = DDLogFlagDebug; | ||||
|             break; | ||||
|         case OWSAnalyticsSeverityInfo: | ||||
|             logFlag = DDLogFlagInfo; | ||||
|             break; | ||||
|         case OWSAnalyticsSeverityWarn: | ||||
|             logFlag = DDLogFlagWarning; | ||||
|             break; | ||||
|         case OWSAnalyticsSeverityError: | ||||
|             logFlag = DDLogFlagError; | ||||
|             async = NO; | ||||
|             break; | ||||
|         case OWSAnalyticsSeverityCritical: | ||||
|             logFlag = DDLogFlagError; | ||||
|             async = NO; | ||||
|             break; | ||||
|         default: | ||||
|             OWSAssert(0); | ||||
|             logFlag = DDLogFlagDebug; | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     // Log the event. | ||||
|     if (!parameters) { | ||||
|         LOG_MAYBE(async, LOG_LEVEL_DEF, logFlag, 0, nil, location, @"%@", description); | ||||
|     } else { | ||||
|         LOG_MAYBE(async, LOG_LEVEL_DEF, logFlag, 0, nil, location, @"%@ %@", description, parameters); | ||||
|     } | ||||
| 
 | ||||
|     // Do nothing.  We don't yet serialize or transmit analytics events. | ||||
| } | ||||
| 
 | ||||
| @end | ||||
					Loading…
					
					
				
		Reference in New Issue