Commit 2814756f authored by 井庆林's avatar 井庆林

埋点库重构、重写单元测试

parent eea2869b
......@@ -41,7 +41,7 @@ NSString *const MockCityId = @"beijing";
[phobos setLogEnabled:NO]; // 调试打Log模式,看情况开启
phobos.signingType = PhobosSigningTypeDebug;
phobos.userId = @"";
[Phobos setSharedClient:phobos];
// [Phobos setSharedClient:phobos];
NSString *inDate = [PhobosUtil currentTime];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
......
......@@ -19,7 +19,8 @@
- (void)setUp {
[super setUp];
NSString *url = @"http://log.test.gengmei.cc/log/collect";
[Phobos setSharedClient:[Phobos clientWithAppName:@"gengmei_test" channelId:@"AppStore"]];
[Phobos clientWithAppName:@"gengmei_test" channelId:@"AppStore"];
// [Phobos setSharedClient:[Phobos clientWithAppName:@"gengmei_test" channelId:@"AppStore"]];
[Phobos sharedClient].serverAPI = url;
_mockArray = [[NSMutableArray alloc] init];
for (int i=0; i<50; i++) {
......@@ -63,9 +64,9 @@
XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method Works!"];
NSData *mockData = [self encodeAndCompressArray:_mockArray];
[PhobosUtil sendData:mockData success:^(NSInteger code) {
[PhobosUtil sendData:mockData success:^(BOOL success) {
[expectation fulfill];
XCTAssertEqual(code, 200);
XCTAssertEqual(success, YES);
}];
//如果超时,则认为发送失败
......
......@@ -9,8 +9,6 @@
#import <XCTest/XCTest.h>
#import <GMPhobos/Phobos.h>
#import "GMPhobosController.h"
#define PhobosCacheKey @"PhobosCacheKey"
@import GMCache;
NSString *const MockAppName = @"gengmei_test";
NSString *const MockChannelId = @"AppStore";
......@@ -31,14 +29,14 @@ NSString *const MockCityId = @"beijing";
[_client setLogEnabled:NO]; // 调试打Log模式,看情况开启
_client.signingType = PhobosSigningTypeDebug;
_client.userId = @"";
[Phobos setSharedClient:_client];
// [Phobos setSharedClient:_client];
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
[GMCache removeObjectAtDocumentPathWithkey:PhobosCacheKey];
[GMCache removeObjectAtDocumentPathWithkey:PhobosTempCacheKey];
[Phobos removeAllNormalPhobosData];
[Phobos removeAllImmediatelyPhobosData];
}
/**
......@@ -50,7 +48,7 @@ NSString *const MockCityId = @"beijing";
[_client setUserId:MockUserId];
[_client setCurrentCityId:MockCityId];
[Phobos track:MockEventId];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
NSArray *array = [Phobos normalPhobosDataForURL:_client.serverAPI];//[GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
......@@ -64,7 +62,7 @@ NSString *const MockCityId = @"beijing";
*/
- (void)testTrackEventWithoutAttr{
[Phobos track:MockEventId];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
NSArray *array = [Phobos normalPhobosDataForURL:_client.serverAPI];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
......@@ -79,7 +77,7 @@ NSString *const MockCityId = @"beijing";
- (void)testTrackEventWithAttr{
NSDictionary *attr = @{@"attr":@"track_attr"};
[Phobos track:MockEventId attributes:attr];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
NSArray *array = [Phobos normalPhobosDataForURL:_client.serverAPI];
XCTAssertTrue(array.count == 1, @"array is empty");
NSDictionary *dict = [array objectAtIndex:0];
[self verfiyDict:dict];
......@@ -100,8 +98,7 @@ NSString *const MockCityId = @"beijing";
// When
[Phobos track:MockEventId attributes:attr sendNow:YES];
// Then
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 0, @"array should be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 0, @"phobos datas should be empty");
}
/**
......@@ -118,8 +115,7 @@ NSString *const MockCityId = @"beijing";
// When
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count != 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] != 0, @"phobos datas shouldn't be empty");
}
/**
......@@ -133,16 +129,13 @@ NSString *const MockCityId = @"beijing";
// 因为实时埋点是异步删除,所以这个位置暂时延时取数据,待优化 TODO
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos immediatelyPhobosCountForURL:_client.serverAPI] == 0, @"phobos datas should be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos immediatelyPhobosCountForURL:_client.serverAPI] == 0, @"phobos datas should be empty");
[Phobos track:MockEventId attributes:attr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 0, @"phobos datas should be empty");
});
});
}
......@@ -153,23 +146,23 @@ NSString *const MockCityId = @"beijing";
* @since 1.1.4
*/
- (void)testTrackEventWithDoubleAttrAndNoSendNow {
[Phobos removeAllNormalPhobosData];
[Phobos removeAllImmediatelyPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[Phobos track:MockEventId attributes:attr];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
}
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
[Phobos track:MockEventId attributes:attr];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"There should be two data in the phobos datas");
}
/**
......@@ -184,29 +177,23 @@ NSString *const MockCityId = @"beijing";
for (int i = 0; i < 30; i++) {
[Phobos track:MockEventId attributes:attr];
}
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 30, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 30, @"There should be 30 data in the phobos datas");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 30, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 30, @"There should be 30 data in the phobos datas");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 30, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 30, @"There should be 30 data in the phobos datas");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 30, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 30, @"There should be 30 data in the phobos datas");
[Phobos track:MockEventId attributes:attr];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 31, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 31, @"There should be 31 data in the phobos datas");
}
/**
......@@ -219,29 +206,23 @@ NSString *const MockCityId = @"beijing";
NSDictionary *sendNowAttr = @{@"attr":@"track_attr_send_now"};
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 0, @"phobos datas should be empty");
[Phobos track:MockEventId attributes:attr];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
[Phobos track:MockEventId attributes:attr];
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 2, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"There should be two data in the phobos datas");
[Phobos track:MockEventId attributes:sendNowAttr sendNow:YES];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 2, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"There should be two data in the phobos datas");
[Phobos track:MockEventId attributes:attr];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 3, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 3, @"There should be three data in the phobos datas");
}
/**
......@@ -250,23 +231,22 @@ NSString *const MockCityId = @"beijing";
* @since 1.1.4
*/
- (void)testTrackEventWithSendNowAndNoSendNowThree {
[Phobos removeAllNormalPhobosData];
[Phobos removeAllImmediatelyPhobosData];
NSDictionary *attr = @{@"attr":@"track_attr"};
//
[Phobos track:MockEventId attributes:attr];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array shouldn't be empty");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
// PhobosCacheKey超过50条数据会自动上报,模拟此情况
for (int i = 0; i < 50; i++) {
[Phobos track:MockEventId attributes:attr];
NSLog(@"%s------%d--%d", __func__, [Phobos normalPhobosCountForURL:_client.serverAPI], [Phobos normalPhobosCount]);
}
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 0, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"array shouldn't be empty");
[Phobos track:MockEventId attributes:attr];
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"There should be two data in the phobos datas");
}
- (void)verfiyDict:(NSDictionary *)dict{
......@@ -309,7 +289,7 @@ NSString *const MockCityId = @"beijing";
[controller viewWillAppear:true];
[controller viewWillDisappear:true];
[self paramUnNilCheck];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
NSArray *array = [Phobos normalPhobosDataForURL:_client.serverAPI];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = array[0][@"params"];
......@@ -323,7 +303,7 @@ NSString *const MockCityId = @"beijing";
}
- (void)paramUnNilCheck {
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
NSArray *array = [Phobos normalPhobosDataForURL:_client.serverAPI];
XCTAssertTrue(array.count != 0, @"PhobosCacheKey 下面应该有数据");
NSDictionary *dic = array[0][@"params"];
......@@ -341,8 +321,10 @@ NSString *const MockCityId = @"beijing";
XCTAssertFalse(controller.needLogPV, @"needLogPV赋值为NO时应该NO");
}
/** 校验PV事件,相差时间较短不应该发送,暂时废弃,现在还是正常插入 *//*
- (void)testCheckPVPhobos {
[GMCache removeObjectAtDocumentPathWithkey:PhobosCacheKey];
NSString *inDate = [PhobosUtil currentTime];
[NSThread sleepForTimeInterval:1];//模拟浏览页面,让out和in时间相差1s
......@@ -358,12 +340,10 @@ NSString *const MockCityId = @"beijing";
[dict setObject:@"" forKey:@"referrer_tab_name"];
[dict setObject:@(0) forKey:@"is_push"];
[Phobos track:@"page_view" attributes:dict];
NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"PhobosCacheKey 下面应该有数据");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"There should be one data in the phobos datas");
[Phobos track:@"page_view" attributes:dict];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 1, @"PhobosCacheKey 上条数据不应该发送");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 1, @"PhobosCacheKey 上条数据不应该发送");
[NSThread sleepForTimeInterval:2];//模拟浏览页面,让第二次浏览和上一次时间相差2s
......@@ -371,15 +351,12 @@ NSString *const MockCityId = @"beijing";
[NSThread sleepForTimeInterval:1];//模拟浏览页面,让out和in时间相差1s
[dict setObject:[PhobosUtil currentTime] forKey:@"out"];
[Phobos track:@"page_view" attributes:dict];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 2, @"PhobosCacheKey 上条数据应该发送");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"PhobosCacheKey 上条数据应该发送");
[Phobos track:@"page_view" attributes:dict];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 2, @"PhobosCacheKey 上条数据不应该发送");
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 2, @"PhobosCacheKey 上条数据不应该发送");
[Phobos track:@"test" attributes:dict];
array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
XCTAssertTrue(array.count == 3, @"PhobosCacheKey 上条数据应该发送");
}
XCTAssertTrue([Phobos normalPhobosCountForURL:_client.serverAPI] == 3, @"PhobosCacheKey 上条数据应该发送s");
}*/
#pragma mark - 其它方法test
......
......@@ -31,13 +31,14 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
*/
+ (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId;
+ (instancetype)sharedClient;
+ (void)setSharedClient:(Phobos *)client;
+ (instancetype) alloc __attribute__((deprecated));
- (instancetype) init __attribute__((deprecated));
+ (instancetype) new __attribute__((deprecated));
#pragma mark - SDK配置
@property (class, readonly, strong) Phobos *sharedClient;
// Phobos在处理业务端传递来的参数时会检查是否某个value为空,如果为空会调用这个block以通知业务层,业务层可以上报这个异常,以助解决问题
@property(nonatomic, copy) void (^captureNullExpection) (NSString *eventId, NSDictionary *info);
......@@ -181,4 +182,41 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
*/
- (void)simulativePV:(NSString *)pageName businessId:(NSString *)bid referer:(NSString *)referer;
@end
@interface Phobos (UtilTest)
/** 获取所有非立即发送埋点数量 */
+ (NSInteger)normalPhobosCount;
/** 获取所有非立即发送埋点数据 */
+ (NSDictionary *)normalPhobosData;
/** 获取url的非立即发送埋点数量 */
+ (NSInteger)normalPhobosCountForURL:(NSString *)url;
/** 获取url的非立即发送埋点数据 */
+ (NSArray *)normalPhobosDataForURL:(NSString *)url;
/** 获取所有立即发送埋点数据 */
+ (NSDictionary *)immediatelyPhobosData;
/** 获取url的立即发送埋点数据 */
+ (NSArray *)immediatelyPhobosDataForURL:(NSString *)url;
/** 获取url的立即发送埋点数量 */
+ (NSUInteger)immediatelyPhobosCountForURL:(NSString *)url;
/** 清除非立即发送埋点数据缓存 */
+ (void)removeAllNormalPhobosData;
/** 清除立即发送埋点数据缓存 */
+ (void)removeAllImmediatelyPhobosData;
/** 获取将要发送的数据 */
@property (nonatomic, copy) void (^phobosSendDataBlock)(NSArray *datas);
@end
......@@ -15,8 +15,9 @@
#import "PhobosCustomVisibleController.h"
#import "UIDevice+Resolutions.h"
#import <GMCache/GMCache.h>
static Phobos *sharedClient = nil;
static NSString *sdkVersion = @"110";
#import <objc/runtime.h>
static Phobos *_sharedClient;
static NSString *sdkVersion = @"1.3.0";
@interface Phobos ()
@property (strong, nonatomic) UIViewController *visibleController;
......@@ -28,58 +29,78 @@ static NSString *sdkVersion = @"110";
/* 每一条埋点数据的物理ID,自增,生命周期和sessionId相同。特别注意:在sessionOver的时候,要把他置为0 */
@property (assign, nonatomic) NSInteger serialId;
//@property (nonatomic, weak) dispatch_semaphore_t immediatelySemaphore;// 保障需要立即发送的埋点数据安全
//@property (nonatomic, weak) dispatch_semaphore_t normalSemaphore;// 保障普通埋点数据安全
@property (nonatomic, assign) NSInteger normalCount;// 记录普通埋点数量
@end
@implementation Phobos {
}
@implementation Phobos
static dispatch_semaphore_t _realTimeSemaphore;
static dispatch_semaphore_t _immediatelySemaphore;
static dispatch_semaphore_t _normalSemaphore;
static NSInteger _normalCount;
+ (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{
Phobos.sharedClient.appName = appName;
Phobos.sharedClient.channelId = channelId;
return Phobos.sharedClient;
}
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_realTimeSemaphore = dispatch_semaphore_create(1);
_immediatelySemaphore = dispatch_semaphore_create(1);
_normalSemaphore = dispatch_semaphore_create(1);
_normalCount;
});
}
+ (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{
return [[self alloc] initWithAppName:appName channelId:channelId];
- (instancetype)init {
if (self = [super init]) {
self.appName = @"";
self.channelId = @"";
self.logEnabled = NO;
self.userId = @"";
self.netStatus = @"";
self.currentCityId = @"";
self.serverAPI = @"";
self.greyType = @"";
self.userType = [[NSMutableDictionary alloc] initWithCapacity:0];
self.appVersion = [PhobosUtil getAppVersion];
self.signingType = PhobosSigningTypeUndefined;
// self.immediatelySemaphore = dispatch_semaphore_create(1);
// self.normalSemaphore = dispatch_semaphore_create(1);
NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey] mutableCopy];
for (NSArray *data in dataDict.allValues) {
self.normalCount += data.count;
}
[self setupNotification];
[self handleSessionStart];
[self synchronizePhobosKey];
}
return self;
}
+ (Phobos *)sharedClient{
return sharedClient;
+ (id)allocWithZone:(struct _NSZone *)zone {
return Phobos.sharedClient;
}
+ (void)setSharedClient:(Phobos *)client{
sharedClient = client;
- (id)copyWithZone:(struct _NSZone *)zone {
return Phobos.sharedClient;
}
- (instancetype)initWithAppName:(NSString *)appName channelId:(NSString *)channelId{
self = [super init];
if (self) {
_appName = appName;
_channelId = channelId;
_logEnabled = NO;
_userId = @"";
_netStatus = @"";
_currentCityId = @"";
_serverAPI = @"";
_greyType = @"";
_userType = [[NSMutableDictionary alloc] initWithCapacity:0];
_appVersion = [PhobosUtil getAppVersion];
_signingType = PhobosSigningTypeUndefined;
[self setupNotification];
[self handleSessionStart];
[self synchronizePhobosKey];
phobosLog(@"starts to orbit");
}
return self;
+ (Phobos *)sharedClient{// 使用单例设计模式,保证Phobos只有一个实例,并提供了全局访问点
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[super allocWithZone:NULL] init];
});
return _sharedClient;
}
- (void)setAppName:(NSString *)appName channelId:(NSString *)channelId {
self.appName = appName;
self.channelId = channelId;
}
/**
......@@ -417,15 +438,15 @@ static NSInteger _normalCount;
}
+ (void)track:(NSString *)eventName{
[self track:eventName attributes:@{} sendNow:NO currentAPI:sharedClient.serverAPI];
[self track:eventName attributes:@{} sendNow:NO currentAPI:_sharedClient.serverAPI];
}
+ (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes{
[self track:eventName attributes:attributes sendNow:NO currentAPI:sharedClient.serverAPI];
[self track:eventName attributes:attributes sendNow:NO currentAPI:_sharedClient.serverAPI];
}
+ (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow{
[self track:eventName attributes:attributes sendNow:sendNow currentAPI:sharedClient.serverAPI];
[self track:eventName attributes:attributes sendNow:sendNow currentAPI:_sharedClient.serverAPI];
}
+ (void)track:(NSString *)eventName currentAPI:(NSString *)currentAPI {
......@@ -437,11 +458,11 @@ static NSInteger _normalCount;
}
+ (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI {
NSDictionary *dataDict = [sharedClient prepareDictionaryForEvent:eventName attributes:attributes];
NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:eventName attributes:attributes];
if (sendNow) {
[self sendImmediatelyPhobosWithURL:currentAPI data:dataDict];
[_sharedClient sendImmediatelyPhobosWithURL:currentAPI data:dataDict];
} else{
[self trackPhobosWithURL:currentAPI data:dataDict];
[_sharedClient trackPhobosWithURL:currentAPI data:dataDict];
}
}
......@@ -454,37 +475,40 @@ static NSInteger _normalCount;
* @param nowSend 是否需要发送当前缓存数据(app进入到后台、前台等情况)
*/
- (void)sendImmediatelyNormalData {
[Phobos trackPhobosWithURL:nil data:nil immediate:YES];
[self trackPhobosWithURL:nil data:nil immediate:YES];
}
+ (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data {
- (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data {
[self trackPhobosWithURL:url data:data immediate:NO];
}
+ (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data immediate:(BOOL)immediate {
- (void)trackPhobosWithURL:(NSString *)url data:(NSDictionary *)data immediate:(BOOL)immediate {
dispatch_semaphore_wait(_normalSemaphore, DISPATCH_TIME_FOREVER);
NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey] mutableCopy];
NSInteger count = 0;
_normalCount++;
if (!immediate) {
dataDict = [self dataDict:dataDict setObject:data forKey:url];
for (NSArray *phobosData in dataDict.allValues) {
count += phobosData.count;
}
[GMCache storeObjectAtDocumentPathWithkey:PhobosNormalCacheKey object:dataDict];
}
[GMCache storeObjectAtDocumentPathWithkey:PhobosNormalCacheKey object:dataDict];
if (immediate || count >= 50) { // 数据超过一定数量 或 进入后台等逻辑,统一进行发送普通埋点数据
if (immediate || self.normalCount >= 50) { // 数据超过一定数量 或 进入后台等逻辑,统一进行发送普通埋点数据
[dataDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) {
[self sendImmediatelyPhobosWithURL:key data:obj];
if (obj && obj.count > 0) {
[self sendImmediatelyPhobosWithURL:key data:obj];
}
}];
[GMCache removeObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
}
dispatch_semaphore_signal(_normalSemaphore);
}
/// 实时埋点
+ (void)sendImmediatelyPhobosWithURL:(NSString *)url data:(NSDictionary *)data {
dispatch_semaphore_wait(_realTimeSemaphore, DISPATCH_TIME_FOREVER);
__block NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosRealTimeCacheKeys] mutableCopy];
/**
* 即时发送埋点接口
* @param url : 接口url
* @param data : 使用id类型是因为直接调用实时埋点传过来的是Dict,而普通埋点过来的则是Array类型
*/
- (void)sendImmediatelyPhobosWithURL:(NSString *)url data:(id)data {
dispatch_semaphore_wait(_immediatelySemaphore, DISPATCH_TIME_FOREVER);
__block NSMutableDictionary *dataDict = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey] mutableCopy];
dataDict = [self dataDict:dataDict setObject:data forKey:url];
NSInteger allCount = dataDict.allKeys.count;// 请求个数
......@@ -499,8 +523,8 @@ static NSInteger _normalCount;
[dataDict removeObjectForKey:key];
}
if (finishCount == allCount) {// 所有数据都请求完成,重新进行数据缓存
[GMCache storeObjectAtDocumentPathWithkey:PhobosRealTimeCacheKeys object:dataDict];
dispatch_semaphore_signal(_realTimeSemaphore);
[GMCache storeObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey object:dataDict];
dispatch_semaphore_signal(_immediatelySemaphore);
}
dispatch_semaphore_signal(semaphore);
phobosLog(@"✈ ---------- ✈ data arrived Mars");
......@@ -508,69 +532,77 @@ static NSInteger _normalCount;
}];
}
+ (NSMutableDictionary *)dataDict:(NSMutableDictionary *)dataDict setObject:(id)object forKey:(NSString *)key {
/**
* 将数据存入到字典中
* @param dataDict 需要存入的字典
* @param object 需要存入的数据
* @param key 需要将数据存入到dataDict的key所在的数据中
*/
- (NSMutableDictionary *)dataDict:(NSMutableDictionary *)dataDict setObject:(id)object forKey:(NSString *)key {
if (!dataDict) {
dataDict = [NSMutableDictionary new];
}
// 判断数据类型,统一转换成数组
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];
}
#ifndef POD_CONFIGURATION_APP_STORE
[self verifyPVPhobos:dataArray data:object];
#endif
[dataArray addObjectsFromArray:data];
[dataDict setValue:dataArray forKey:key];
return dataDict;
}
// 校验PV埋点是否有问题,默认返回NO
+ (BOOL)verifyPVPhobos:(NSArray *)dataArray data:(NSDictionary *)data {
if (data[@"type"] && [data[@"type"] isEqualToString:@"page_view"]) {
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;
- (BOOL)verifyPVPhobos:(NSArray *)dataArray data:(id)data {
if ([data isKindOfClass:[NSDictionary class]]) {
NSDictionary *dataDict = (NSDictionary *)data;
if (dataDict[@"type"] && [dataDict[@"type"] isEqualToString:@"page_view"]) {
NSDictionary *pageParams = dataDict[@"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;
}
}
}
return checkTimeError;
}
return checkTimeError;
}
}
return NO;
}
// 发送埋点数据
+ (void)sendDataWithAPI:(NSString *)api data:(NSArray *)dataArray successBlock:(SendDataSuccessBlock)successBlock {
if (sharedClient.logEnabled) {
- (void)sendDataWithAPI:(NSString *)api data:(NSArray *)dataArray successBlock:(SendDataSuccessBlock)successBlock {
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 {
if (self.phobosSendDataBlock) {
self.phobosSendDataBlock(dataArray);
}
NSData *JSON = [PhobosUtil encodeJSON:dataArray];
NSData *compressedData = [PhobosUtil compressData:JSON];
if (compressedData) {
......@@ -583,3 +615,67 @@ static NSInteger _normalCount;
}
@end
@implementation Phobos (UtilTest)
/** 获取所有非立即发送埋点数量 */
+ (NSInteger)normalPhobosCount {
return Phobos.sharedClient.normalCount;
}
/** 获取所有非立即发送埋点数据 */
+ (NSDictionary *)normalPhobosData {
return [GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
}
/** 获取url的非立即发送埋点数量 */
+ (NSUInteger)normalPhobosCountForURL:(NSString *)url {
NSDictionary *dict = [GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
NSArray *urlData = dict[url];
return urlData ? urlData.count : 0;
}
/** 获取url的非立即发送埋点数据 */
+ (NSArray *)normalPhobosDataForURL:(NSString *)url {
NSDictionary *dict = [GMCache fetchObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
return dict[url];
}
/** 获取所有立即发送埋点数据 */
+ (NSDictionary *)immediatelyPhobosData {
return [GMCache fetchObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey];
}
/** 获取url的立即发送埋点数据 */
+ (NSArray *)immediatelyPhobosDataForURL:(NSString *)url {
NSDictionary *dict = [GMCache fetchObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey];
return dict[url];
}
+ (NSUInteger)immediatelyPhobosCountForURL:(NSString *)url {
NSDictionary *dict = [GMCache fetchObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey];
NSArray *urlData = dict[url];
return urlData ? urlData.count : 0;
}
/** 清除非立即发送埋点数据缓存 */
+ (void)removeAllNormalPhobosData {
Phobos.sharedClient.normalCount = 0;
[GMCache removeObjectAtDocumentPathWithkey:PhobosNormalCacheKey];
}
/** 清除立即发送埋点数据缓存 */
+ (void)removeAllImmediatelyPhobosData {
[GMCache removeObjectAtDocumentPathWithkey:PhobosImmediatelyCacheKey];
}
- (void)setPhobosSendDataBlock:(void (^)(NSArray *))phobosSendDataBlock {
objc_setAssociatedObject(self, @selector(phobosSendDataBlock), phobosSendDataBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void (^)(NSArray *))phobosSendDataBlock {
return objc_getAssociatedObject(self, @selector(phobosSendDataBlock));
}
@end
......@@ -18,9 +18,8 @@
#define PhobosHaveOpenApp @"PhobosHaveOpenApp" //是否打开过APP
#define PhobosBeginTime @"PhobosBeginTime" //记录APP打开|从后台启动时的时间戳
#define PhobosEndTime @"PhobosEndTime" //记录APP退出|退到后台时的时间戳
#define PhobosNormalCacheKey @"PhobosNormalCacheKey" //存放持久化埋点数据的key
#define PhobosRealTimeCacheKeys @"PhobosRealTimeCacheKey" //存放持久化实时埋点数据的key
#define PhobosTempCacheKey @"PhobosTempCacheKey" //临时存放待发送埋点数据的key
#define PhobosNormalCacheKey @"PhobosNormalCacheKey" //存放持久化埋点数据的key
#define PhobosImmediatelyCacheKey @"PhobosImmediatelyCacheKey" //存放持久化实时埋点数据的key
#define PhobosShardCount 50 //收集数据分段发送的个数
......
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