Commit eea2869b authored by 井庆林's avatar 井庆林

phobos重构

parent 2e1dbac1
...@@ -131,12 +131,12 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) { ...@@ -131,12 +131,12 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
* *
* @since 0.0.1 * @since 0.0.1
*/ */
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes; + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes;
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow; + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow;
+ (void)track:(NSString *)eventId; + (void)track:(NSString *)eventName;
/** /**
* @brief 自定义事件,数量统计 7730 精准曝光. * @brief 自定义事件,数量统计 7730 精准曝光/数据链路.
* *
* @param eventId 事件Id * @param eventId 事件Id
* @attributes 参数 * @attributes 参数
...@@ -144,9 +144,9 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) { ...@@ -144,9 +144,9 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
* @currentAPI 当前传过来的API * @currentAPI 当前传过来的API
* @ * @
*/ */
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes currentAPI:(NSString *)currentAPI; + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes currentAPI:(NSString *)currentAPI;
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI; + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI;
+ (void)track:(NSString *)eventId currentAPI:(NSString *)currentAPI; + (void)track:(NSString *)eventName currentAPI:(NSString *)currentAPI;
/** /**
* @author 翟国钧, 16-02-03 16:02:30 * @author 翟国钧, 16-02-03 16:02:30
......
...@@ -28,12 +28,25 @@ static NSString *sdkVersion = @"110"; ...@@ -28,12 +28,25 @@ static NSString *sdkVersion = @"110";
/* 每一条埋点数据的物理ID,自增,生命周期和sessionId相同。特别注意:在sessionOver的时候,要把他置为0 */ /* 每一条埋点数据的物理ID,自增,生命周期和sessionId相同。特别注意:在sessionOver的时候,要把他置为0 */
@property (assign, nonatomic) NSInteger serialId; @property (assign, nonatomic) NSInteger serialId;
// 用来记录除serverAPI以外的API
@property (strong, nonatomic) NSMutableArray *APIArray;
@end @end
@implementation Phobos @implementation Phobos {
}
static dispatch_semaphore_t _realTimeSemaphore;
static dispatch_semaphore_t _normalSemaphore;
static NSInteger _normalCount;
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_realTimeSemaphore = dispatch_semaphore_create(1);
_normalSemaphore = dispatch_semaphore_create(1);
_normalCount;
});
}
+ (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{ + (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{
return [[self alloc] initWithAppName:appName channelId:channelId]; return [[self alloc] initWithAppName:appName channelId:channelId];
...@@ -60,7 +73,6 @@ static NSString *sdkVersion = @"110"; ...@@ -60,7 +73,6 @@ static NSString *sdkVersion = @"110";
_greyType = @""; _greyType = @"";
_userType = [[NSMutableDictionary alloc] initWithCapacity:0]; _userType = [[NSMutableDictionary alloc] initWithCapacity:0];
_appVersion = [PhobosUtil getAppVersion]; _appVersion = [PhobosUtil getAppVersion];
_APIArray = [NSMutableArray array];
_signingType = PhobosSigningTypeUndefined; _signingType = PhobosSigningTypeUndefined;
[self setupNotification]; [self setupNotification];
[self handleSessionStart]; [self handleSessionStart];
...@@ -188,7 +200,7 @@ static NSString *sdkVersion = @"110"; ...@@ -188,7 +200,7 @@ static NSString *sdkVersion = @"110";
phobosLog(@"handleAppInForeground"); phobosLog(@"handleAppInForeground");
[self handleSessionStart]; [self handleSessionStart];
[self handleEventDeviceOpened]; [self handleEventDeviceOpened];
[self fetchDataAndSend]; [self sendImmediatelyNormalData];
[self handlePVEventAppInForeground]; [self handlePVEventAppInForeground];
} }
...@@ -201,7 +213,7 @@ static NSString *sdkVersion = @"110"; ...@@ -201,7 +213,7 @@ static NSString *sdkVersion = @"110";
phobosLog(@"handleAppInBackgound"); phobosLog(@"handleAppInBackgound");
[self handlePVEventAppInBackgound]; [self handlePVEventAppInBackgound];
[self handleSessionOver]; [self handleSessionOver];
[self fetchDataAndSend]; [self sendImmediatelyNormalData];
} }
/** /**
...@@ -256,78 +268,6 @@ static NSString *sdkVersion = @"110"; ...@@ -256,78 +268,6 @@ static NSString *sdkVersion = @"110";
} }
} }
#pragma mark - track event handler
+ (void)track:(NSString *)eventId{
[Phobos track:eventId attributes:@{}];
}
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes{
[self track:eventId attributes:attributes sendNow:NO];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
//超过一定数量的话,统一发送一次
if (array.count > PhobosShardCount) {
[sharedClient sendArray:array cleanCacheRightNow:YES];
}
}
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow{
NSDictionary *dict = [sharedClient prepareDictionaryForEvent:eventId attributes:attributes];
if (sendNow) {
NSArray *array = @[dict];
// 实时发送的埋点,不能立即清楚缓存
[sharedClient sendArray:array cleanCacheRightNow:NO];
}else{
[sharedClient save:dict];
}
}
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes currentAPI:(NSString *)currentAPI {
[self track:eventId attributes:attributes sendNow:NO currentAPI:currentAPI];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]];
//超过一定数量的话,统一发送一次
if (array.count > PhobosShardCount) {
[sharedClient sendArray:array currentAPI:currentAPI cleanCacheRightNow:YES];
}
}
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI {
[sharedClient addNewApi:currentAPI]; // 记录新的API
NSDictionary *dict = [sharedClient prepareDictionaryForEvent:eventId attributes:attributes];
if (sendNow) {
NSArray *array = @[dict];
// 实时发送的埋点,不能立即清楚缓存
[sharedClient sendArray:array currentAPI:currentAPI cleanCacheRightNow:NO];
}else{
[sharedClient save:dict currentAPI:currentAPI];
}
}
+ (void)track:(NSString *)eventId currentAPI:(NSString *)currentAPI {
[Phobos track:eventId attributes:@{} currentAPI:currentAPI];
}
+ (void)trackJsEvent:(NSString *)jsonString{
@try {
NSData *data = [jsonString dataUsingEncoding:NSUnicodeStringEncoding];
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
id pa = dict[@"params"];
NSDictionary *json;
if ([pa isKindOfClass:[NSString class]]) {
NSError *jsonError;
NSData *objectData = [pa dataUsingEncoding:NSUTF8StringEncoding];
json = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
[Phobos track:dict[@"type"] attributes:json];
}else{
[Phobos track:dict[@"type"]];
}
}
@catch (NSException *exception) {
phobosLog(exception);
}
}
#pragma mark - PV #pragma mark - PV
- (void)onPVStart:(UIResponder<PhobosPVProtocol> *)page { - (void)onPVStart:(UIResponder<PhobosPVProtocol> *)page {
// 必须在此处调用一下referer,因为onControllerStart // 必须在此处调用一下referer,因为onControllerStart
...@@ -341,7 +281,7 @@ static NSString *sdkVersion = @"110"; ...@@ -341,7 +281,7 @@ static NSString *sdkVersion = @"110";
if (![PhobosUtil isNonEmpty:page.pageName] || !page.needLogPV) { if (![PhobosUtil isNonEmpty:page.pageName] || !page.needLogPV) {
return; return;
} }
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
@try { @try {
[dict setObject:[PhobosUtil currentTime] forKey:@"out"]; [dict setObject:[PhobosUtil currentTime] forKey:@"out"];
...@@ -382,45 +322,44 @@ static NSString *sdkVersion = @"110"; ...@@ -382,45 +322,44 @@ static NSString *sdkVersion = @"110";
} }
} }
#pragma mark - 事件存储、发送
/** /**
* @brief 将埋点时间封装成词典数据 * @brief 将埋点时间封装成词典数据
* *
* @since 0.0.1 * @since 0.0.1
*/ */
- (NSDictionary *)prepareDictionaryForEvent:(NSString *)eventId attributes:(NSDictionary *)attributes{ - (NSDictionary *)prepareDictionaryForEvent:(NSString *)eventName attributes:(NSDictionary *)attributes{
[self catchNullForEvent:eventId attributes:attributes]; [self catchNullForEvent:eventName attributes:attributes];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
@try { @try {
NSString *currentTime = [PhobosUtil currentTime]; NSString *currentTime = [PhobosUtil currentTime];
NSMutableDictionary *deviceParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString],@"idfa", NSMutableDictionary *deviceParams = [NSMutableDictionary new];
[[[UIDevice currentDevice] identifierForVendor] UUIDString],@"idfv", [deviceParams setValue:[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString] forKey:@"idfa"];
[PhobosUtil deviceId],@"device_id", [deviceParams setValue:[[[UIDevice currentDevice] identifierForVendor] UUIDString] forKey:@"idfv"];
@"ios",@"device_type", [deviceParams setValue:[PhobosUtil deviceId] forKey:@"device_id"];
@"Apple",@"manufacturer", [deviceParams setValue:@"ios" forKey:@"device_type"];
@(self.gps.coordinate.latitude),@"lat", [deviceParams setValue:@"Apple" forKey:@"manufacturer"];
@(self.gps.coordinate.longitude),@"lng", [deviceParams setValue:@(self.gps.coordinate.latitude) forKey:@"lat"];
_netStatus,@"is_WiFi", [deviceParams setValue:@(self.gps.coordinate.longitude) forKey:@"lng"];
[PhobosUtil getIPAddress:YES],@"ip",nil]; [deviceParams setValue:_netStatus forKey:@"is_WiFi"];
[deviceParams setValue:[PhobosUtil getIPAddress:YES] forKey:@"ip"];
[deviceParams setValue:_networkStatus forKey:@"net_type"]; [deviceParams setValue:_networkStatus forKey:@"net_type"];
[deviceParams setValue:[UIDevice platform] forKey:@"model"]; [deviceParams setValue:[UIDevice platform] forKey:@"model"];
[deviceParams setValue:[UIDevice currentDevice].systemVersion forKey:@"sys_version"]; [deviceParams setValue:[UIDevice currentDevice].systemVersion forKey:@"sys_version"];
NSMutableDictionary *appParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
_greyType, @"grey_type", NSMutableDictionary *appParams = [NSMutableDictionary new];
self.appName, @"name", [appParams setValue:_greyType forKey:@"grey_type"];
self.appVersion, @"version", [appParams setValue:_appName forKey:@"name"];
self.channelId,@"channel", [appParams setValue:_appVersion forKey:@"version"];
_userType,@"user_type", [appParams setValue:_channelId forKey:@"channel"];
self.currentCityId,@"current_city_id", [appParams setValue:_userType forKey:@"net_type"];
@(_serialId++), @"serial_id",nil]; [appParams setValue:_currentCityId forKey:@"current_city_id"];
[appParams setValue:@(_serialId++) forKey:@"serial_id"];
if (_signingType == PhobosSigningTypeDebug || _signingType == PhobosSigningTypeRelease) { if (_signingType == PhobosSigningTypeDebug || _signingType == PhobosSigningTypeRelease) {
[dict setObject:@(0) forKey:@"is_release"]; [dict setObject:@(0) forKey:@"is_release"];
} }
[dict setObject:eventId forKey:@"type"]; [dict setObject:eventName forKey:@"type"];
[dict setObject:appParams forKey:@"app"]; [dict setObject:appParams forKey:@"app"];
[dict setObject:sdkVersion forKey:@"version"]; [dict setObject:sdkVersion forKey:@"version"];
[dict setObject:deviceParams forKey:@"device"]; [dict setObject:deviceParams forKey:@"device"];
...@@ -435,124 +374,41 @@ static NSString *sdkVersion = @"110"; ...@@ -435,124 +374,41 @@ static NSString *sdkVersion = @"110";
return dict; return dict;
} }
/** #pragma mark - helpers
* @brief 保存数据到缓存层 - (void)catchNullForEvent:(NSString *)eventName attributes:(NSDictionary *)attributes {
* dispatch_async(dispatch_get_global_queue(0, 0), ^{
* @param data 数据 @try {
* for (NSString *key in attributes.allKeys) {
* @since 0.0.1 if ([attributes[key] isMemberOfClass:[NSNull class]]) {
*/ if (self.captureNullExpection) {
- (void)save:(NSDictionary *)data self.captureNullExpection(eventName, attributes);
{
if (_logEnabled) {
phobosLog([NSString stringWithFormat:@"save dictionary: %@",data]);
}
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
if (dataArray) {
#ifdef POD_CONFIGURATION_APP_STORE
[dataArray addObject:data];
#else
if (data[@"type"] && [data[@"type"] isEqualToString:@"page_view"]) {
NSDictionary *pageParams = data[@"params"];
long long pageInTime = [pageParams[@"in"] longLongValue];
long long pageOutTime = [pageParams[@"out"] longLongValue];
// phobosLog(@"pageInTime------%lld",pageInTime);
// phobosLog(@"pageOutTime------%lld",pageOutTime);
if (pageInTime && pageOutTime) {
__block BOOL checkTimeError;
for (int i = 0; i < dataArray.count; i++) {
NSDictionary *obj = dataArray[i];
if (obj[@"type"] && [obj[@"type"] isEqualToString:@"page_view"]) {
NSDictionary *params = obj[@"params"];
long long objInTime = [params[@"in"] longLongValue];
long long objOutTime = [params[@"out"] longLongValue];
if ( (fabsl(objInTime - pageInTime)) < 1 || (fabsl(objOutTime - pageOutTime)) < 1) {
phobosLog(@"两个埋点inTime 时间差------%f", (fabsl(objInTime - pageInTime)));
phobosLog(@"两个埋点outTime 时间差------%f", (fabsl(objOutTime - pageOutTime)));
checkTimeError = YES;
phobosLog(@"%s____数据校验失败", __func__);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *stringTitle = [NSString stringWithFormat:@"%@ PV埋点可能重复", data];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:stringTitle message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alertView show];
});
break;
}
} }
break;
} }
} }
} @catch (NSException *exception) {
} }
// 不管成功还是失败 给开发提示方便DEBUG });
// phobosLog(@"%s____数据校验成功", __func__);
[dataArray addObject:data];
#endif
} else {
dataArray = [NSMutableArray arrayWithObject:data];
}
[GMCache storeObjectAtDocumentPathWithkey:PhobosCacheKey object:dataArray];
}
/**
* @brief 保存数据到缓存层
*
* @param data 数据
*
*/
- (void)save:(NSDictionary *)data currentAPI:(NSString *)currentAPI
{
if (_logEnabled) {
phobosLog([NSString stringWithFormat:@"save dictionary: %@",data]);
}
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]];
if (dataArray) {
[dataArray addObject:data];
}else{
dataArray = [NSMutableArray arrayWithObject:data];
}
[GMCache storeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI] object:dataArray];
}
/**
* @brief 从缓存中获取数据,并发送
*
* @since 0.0.1
*/
- (void)fetchDataAndSend{
NSArray *paramsArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
if (paramsArray.count>0) {
[self sendArray:paramsArray cleanCacheRightNow:YES];
}
// 其他接口的埋点
for (NSString *newApi in self.APIArray) {
NSArray *paramsArray = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:newApi]];
if (paramsArray.count>0) {
[self sendArray:paramsArray currentAPI:newApi cleanCacheRightNow:YES];
}
}
} }
/* #pragma mark - track event handler
从缓存区获取数据,发给服务器,请求成功的时候,把缓存区的数据删除掉 + (void)trackJsEvent:(NSString *)jsonString{
*/
- (void)sendArray {
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey];
if (_logEnabled) {
NSData *data = [NSJSONSerialization dataWithJSONObject:dataArray options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
phobosLog([NSString stringWithFormat:@"array prepare to fly --✈: %@", jsonString]);
}
@try { @try {
NSData *JSON = [PhobosUtil encodeJSON:dataArray]; NSData *data = [jsonString dataUsingEncoding:NSUnicodeStringEncoding];
NSData *compressedData = [PhobosUtil compressData:JSON]; NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (compressedData) {
[PhobosUtil sendData:compressedData success:^(NSInteger code) { id pa = dict[@"params"];
phobosLog(@"✈ ---------- ✈ data arrived Mars"); NSDictionary *json;
[GMCache removeObjectAtDocumentPathWithkey:PhobosTempCacheKey]; if ([pa isKindOfClass:[NSString class]]) {
}]; NSError *jsonError;
NSData *objectData = [pa dataUsingEncoding:NSUTF8StringEncoding];
json = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
[Phobos track:dict[@"type"] attributes:json];
}else{
[Phobos track:dict[@"type"]];
} }
} }
@catch (NSException *exception) { @catch (NSException *exception) {
...@@ -560,109 +416,170 @@ static NSString *sdkVersion = @"110"; ...@@ -560,109 +416,170 @@ static NSString *sdkVersion = @"110";
} }
} }
/* + (void)track:(NSString *)eventName{
从缓存区获取数据,发给服务器,请求成功的时候,把缓存区的数据删除掉 [self track:eventName attributes:@{} sendNow:NO currentAPI:sharedClient.serverAPI];
*/ }
- (void)sendArrayWithCurrentAPI:(NSString *)currentAPI {
NSString *PhobosTempCacheKeyStr = [PhobosUtil MD5String:[PhobosUtil MD5String:currentAPI]]; // 两次加密作为key值,和缓存的key值作区分 + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes{
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr]; [self track:eventName attributes:attributes sendNow:NO currentAPI:sharedClient.serverAPI];
if (_logEnabled) { }
NSData *data = [NSJSONSerialization dataWithJSONObject:dataArray options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow{
phobosLog([NSString stringWithFormat:@"array prepare to fly --✈: %@", jsonString]); [self track:eventName attributes:attributes sendNow:sendNow currentAPI:sharedClient.serverAPI];
} }
@try {
NSData *JSON = [PhobosUtil encodeJSON:dataArray]; + (void)track:(NSString *)eventName currentAPI:(NSString *)currentAPI {
NSData *compressedData = [PhobosUtil compressData:JSON]; [self track:eventName attributes:@{} sendNow:NO currentAPI:currentAPI];
if (compressedData) { }
[PhobosUtil sendData:compressedData currentAPI:currentAPI success:^(NSInteger code) {
phobosLog(@"✈ ---------- ✈ data arrived Mars"); + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes currentAPI:(NSString *)currentAPI {
[GMCache removeObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr]; [self track:eventName attributes:attributes sendNow:NO currentAPI:currentAPI];
}]; }
}
} + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI {
@catch (NSException *exception) { NSDictionary *dataDict = [sharedClient prepareDictionaryForEvent:eventName attributes:attributes];
phobosLog(exception); if (sendNow) {
[self sendImmediatelyPhobosWithURL:currentAPI data:dataDict];
} else{
[self trackPhobosWithURL:currentAPI data:dataDict];
} }
} }
#pragma mark - 事件存储、发送
/** /**
该方法有改动,现在的逻辑是:当前方法只接受发送的请求,然后把数据转存到另一个缓存区, * 普通埋点
让sendArray方法负责发送,数据一旦转移到缓存区,就把原有的数据干掉。 * @param url 接口url
@author zhaiguojun 16-10-17 in (null) * @param dataArray 埋点数据
@param array 参数 * @param nowSend 是否需要发送当前缓存数据(app进入到后台、前台等情况)
@param clean 是否立即清楚缓存
*/ */
- (void)sendArray:(NSArray *)array cleanCacheRightNow:(BOOL)clean { - (void)sendImmediatelyNormalData {
@try { [Phobos trackPhobosWithURL:nil data:nil immediate:YES];
//1.获取缓存区的数据,把新数据追加进去 }
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey]; + (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data {
if (dataArray) { [self trackPhobosWithURL:url data:data immediate:NO];
[dataArray addObjectsFromArray:array]; }
}else{
dataArray = [NSMutableArray arrayWithArray:array]; + (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data immediate:(BOOL)immediate {
} dispatch_semaphore_wait(_normalSemaphore, DISPATCH_TIME_FOREVER);
[GMCache storeObjectAtDocumentPathWithkey:PhobosTempCacheKey object:dataArray]; NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey] mutableCopy];
//2.把缓存区的数据发送给服务器 NSInteger count = 0;
[self sendArray]; if (!immediate) {
//3.把原有的数据删除 dataDict = [self dataDict:dataDict setObject:data forKey:url];
if (clean) { for (NSArray *phobosData in dataDict.allValues) {
[GMCache removeObjectAtDocumentPathWithkey:PhobosCacheKey]; count += phobosData.count;
} }
} }
@catch (NSException *exception) { [GMCache storeObjectAtDocumentPathWithkey:PhobosNormalCacheKey object:dataDict];
phobosLog(exception); if (immediate || count >= 50) { // 数据超过一定数量 或 进入后台等逻辑,统一进行发送普通埋点数据
[dataDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) {
[self sendImmediatelyPhobosWithURL:key data:obj];
}];
[GMCache removeObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
} }
dispatch_semaphore_signal(_normalSemaphore);
} }
/** /// 实时埋点
上边方法新加了一个API字段 + (void)sendImmediatelyPhobosWithURL:(NSString *)url data:(NSDictionary *)data {
*/ dispatch_semaphore_wait(_realTimeSemaphore, DISPATCH_TIME_FOREVER);
- (void)sendArray:(NSArray *)array currentAPI:(NSString *)currentAPI cleanCacheRightNow:(BOOL)clean { __block NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosRealTimeCacheKeys] mutableCopy];
@try { dataDict = [self dataDict:dataDict setObject:data forKey:url];
//1.获取缓存区的数据,把新数据追加进去
NSString *PhobosTempCacheKeyStr = [PhobosUtil MD5String:[PhobosUtil MD5String:currentAPI]]; // 两次加密作为key值,和缓存的key值作区分 NSInteger allCount = dataDict.allKeys.count;// 请求个数
NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr]; __block finishCount = 0;// 请求完成次数,不是请求成功次数,能在最后保证未发送成功的数据,能一次保存下来,等待下次发送
if (dataArray) {
[dataArray addObjectsFromArray:array]; dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);// 因为网络请求是异步回调,需要保证数据安全
}else{ [dataDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) {
dataArray = [NSMutableArray arrayWithArray:array]; [self sendDataWithAPI:key data:obj successBlock:^(BOOL success) {
} dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[GMCache storeObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr object:dataArray]; finishCount++;
//2.把缓存区的数据发送给服务器 if (success) {// 如果数据请求成功,删除当前数据的缓存
[self sendArrayWithCurrentAPI:currentAPI]; [dataDict removeObjectForKey:key];
//3.把原有的数据删除 }
[GMCache removeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]]; if (finishCount == allCount) {// 所有数据都请求完成,重新进行数据缓存
[GMCache storeObjectAtDocumentPathWithkey:PhobosRealTimeCacheKeys object:dataDict];
dispatch_semaphore_signal(_realTimeSemaphore);
}
dispatch_semaphore_signal(semaphore);
phobosLog(@"✈ ---------- ✈ data arrived Mars");
}];
}];
}
+ (NSMutableDictionary *)dataDict:(NSMutableDictionary *)dataDict setObject:(id)object forKey:(NSString *)key {
if (!dataDict) {
dataDict = [NSMutableDictionary new];
} }
@catch (NSException *exception) { // 判断数据类型,统一转换成数组
phobosLog(exception); NSMutableArray *dataArray = [dataDict.allKeys containsObject:key] ? [dataDict[key] mutableCopy] : [NSMutableArray new];
#ifdef POD_CONFIGURATION_APP_STORE
NSArray *data = [object isKindOfClass:[NSArray class]] ? object :@[object];
[dataArray addObjectsFromArray:data];
#else
if (![self verifyPVPhobos:dataArray data:object]) {
NSArray *data = [object isKindOfClass:[NSArray class]] ? object :@[object];
[dataArray addObjectsFromArray:data];
} }
} #endif
#pragma mark - helpers [dataDict setValue:dataArray forKey:key];
- (void)catchNullForEvent:(NSString *)eventId attributes:(NSDictionary *)attributes { return dataDict;
dispatch_async(dispatch_get_global_queue(0, 0), ^{ }
@try {
for (NSString *key in attributes.allKeys) { // 校验PV埋点是否有问题,默认返回NO
if ([attributes[key] isMemberOfClass:[NSNull class]]) { + (BOOL)verifyPVPhobos:(NSArray *)dataArray data:(NSDictionary *)data {
if (self.captureNullExpection) { if (data[@"type"] && [data[@"type"] isEqualToString:@"page_view"]) {
self.captureNullExpection(eventId, attributes); NSDictionary *pageParams = data[@"params"];
long long pageInTime = [pageParams[@"in"] longLongValue];
long long pageOutTime = [pageParams[@"out"] longLongValue];
if (pageInTime && pageOutTime) {
BOOL checkTimeError;
for (int i = 0; i < dataArray.count; i++) {
NSDictionary *obj = dataArray[i];
if (obj[@"type"] && [obj[@"type"] isEqualToString:@"page_view"]) {
NSDictionary *params = obj[@"params"];
long long objInTime = [params[@"in"] longLongValue];
long long objOutTime = [params[@"out"] longLongValue];
if ( (fabsl(objInTime - pageInTime)) < 1 || (fabsl(objOutTime - pageOutTime)) < 1) {
phobosLog(@"两个埋点inTime 时间差------%f", (fabsl(objInTime - pageInTime)));
phobosLog(@"两个埋点outTime 时间差------%f", (fabsl(objOutTime - pageOutTime)));
checkTimeError = YES;
phobosLog(@"%s____数据校验失败", __func__);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *stringTitle = [NSString stringWithFormat:@"%@ PV埋点可能重复", data];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:stringTitle message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alertView show];
});
break;
} }
break;
} }
} }
} @catch (NSException *exception) { return checkTimeError;
} }
}); }
return NO;
} }
// 发送埋点数据
- (void)addNewApi:(NSString *)api { + (void)sendDataWithAPI:(NSString *)api data:(NSArray *)dataArray successBlock:(SendDataSuccessBlock)successBlock {
for (NSString *item in self.APIArray) { if (sharedClient.logEnabled) {
if ([api isEqualToString:item]) { NSData *data = [NSJSONSerialization dataWithJSONObject:dataArray options:NSJSONWritingPrettyPrinted error:nil];
break; NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
phobosLog([NSString stringWithFormat:@"array prepare to fly --✈: %@", jsonString]);
}
@try {
NSData *JSON = [PhobosUtil encodeJSON:dataArray];
NSData *compressedData = [PhobosUtil compressData:JSON];
if (compressedData) {
[PhobosUtil sendData:compressedData currentAPI:api success:successBlock];
} }
[self.APIArray addObject:api]; }
@catch (NSException *exception) {
phobosLog(exception);
} }
} }
@end @end
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
#define PhobosHaveOpenApp @"PhobosHaveOpenApp" //是否打开过APP #define PhobosHaveOpenApp @"PhobosHaveOpenApp" //是否打开过APP
#define PhobosBeginTime @"PhobosBeginTime" //记录APP打开|从后台启动时的时间戳 #define PhobosBeginTime @"PhobosBeginTime" //记录APP打开|从后台启动时的时间戳
#define PhobosEndTime @"PhobosEndTime" //记录APP退出|退到后台时的时间戳 #define PhobosEndTime @"PhobosEndTime" //记录APP退出|退到后台时的时间戳
#define PhobosCacheKey @"PhobosCacheKey" //存放持久化埋点数据的key #define PhobosNormalCacheKey @"PhobosNormalCacheKey" //存放持久化埋点数据的key
#define PhobosRealTimeCacheKeys @"PhobosRealTimeCacheKey" //存放持久化实时埋点数据的key
#define PhobosTempCacheKey @"PhobosTempCacheKey" //临时存放待发送埋点数据的key #define PhobosTempCacheKey @"PhobosTempCacheKey" //临时存放待发送埋点数据的key
#define PhobosShardCount 50 //收集数据分段发送的个数 #define PhobosShardCount 50 //收集数据分段发送的个数
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
typedef void (^SendDataSuccessBlock)(NSInteger code); typedef void (^SendDataSuccessBlock)(BOOL success);
@interface PhobosUtil : NSObject @interface PhobosUtil : NSObject
......
...@@ -123,11 +123,8 @@ ...@@ -123,11 +123,8 @@
// sendAsynchronousRequest 在iOS9以后y被废除了 // sendAsynchronousRequest 在iOS9以后y被废除了
NSURLSession *session = [NSURLSession sharedSession]; NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) { if (success) {
//没有错误,返回正确; success(!error ? YES : NO);
if (success) {
success(200);
}
} }
}]; }];
[dataTask resume]; [dataTask resume];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment