Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
GMPhobos
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
GMPhobos
Commits
eea2869b
Commit
eea2869b
authored
Jun 24, 2019
by
井庆林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
phobos重构
parent
2e1dbac1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
228 additions
and
313 deletions
+228
-313
Phobos.h
GMPhobos/Classes/Phobos.h
+7
-7
Phobos.m
GMPhobos/Classes/Phobos.m
+216
-299
PhobosConfig.h
GMPhobos/Classes/PhobosConfig.h
+2
-1
PhobosUtil.h
GMPhobos/Classes/PhobosUtil.h
+1
-1
PhobosUtil.m
GMPhobos/Classes/PhobosUtil.m
+2
-5
No files found.
GMPhobos/Classes/Phobos.h
View file @
eea2869b
...
...
@@ -131,12 +131,12 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
*
* @since 0.0.1
*/
+
(
void
)
track
:(
NSString
*
)
event
Id
attributes
:(
NSDictionary
*
)
attributes
;
+
(
void
)
track
:(
NSString
*
)
event
Id
attributes
:(
NSDictionary
*
)
attributes
sendNow
:(
BOOL
)
sendNow
;
+
(
void
)
track
:(
NSString
*
)
event
Id
;
+
(
void
)
track
:(
NSString
*
)
event
Name
attributes
:(
NSDictionary
*
)
attributes
;
+
(
void
)
track
:(
NSString
*
)
event
Name
attributes
:(
NSDictionary
*
)
attributes
sendNow
:(
BOOL
)
sendNow
;
+
(
void
)
track
:(
NSString
*
)
event
Name
;
/**
* @brief 自定义事件,数量统计 7730 精准曝光.
* @brief 自定义事件,数量统计 7730 精准曝光
/数据链路
.
*
* @param eventId 事件Id
* @attributes 参数
...
...
@@ -144,9 +144,9 @@ typedef NS_ENUM (NSInteger, PhobosSigningType) {
* @currentAPI 当前传过来的API
* @
*/
+
(
void
)
track
:(
NSString
*
)
event
Id
attributes
:(
NSDictionary
*
)
attributes
currentAPI
:(
NSString
*
)
currentAPI
;
+
(
void
)
track
:(
NSString
*
)
event
Id
attributes
:(
NSDictionary
*
)
attributes
sendNow
:(
BOOL
)
sendNow
currentAPI
:(
NSString
*
)
currentAPI
;
+
(
void
)
track
:(
NSString
*
)
event
Id
currentAPI
:(
NSString
*
)
currentAPI
;
+
(
void
)
track
:(
NSString
*
)
event
Name
attributes
:(
NSDictionary
*
)
attributes
currentAPI
:(
NSString
*
)
currentAPI
;
+
(
void
)
track
:(
NSString
*
)
event
Name
attributes
:(
NSDictionary
*
)
attributes
sendNow
:(
BOOL
)
sendNow
currentAPI
:(
NSString
*
)
currentAPI
;
+
(
void
)
track
:(
NSString
*
)
event
Name
currentAPI
:(
NSString
*
)
currentAPI
;
/**
* @author 翟国钧, 16-02-03 16:02:30
...
...
GMPhobos/Classes/Phobos.m
View file @
eea2869b
...
...
@@ -28,12 +28,25 @@ static NSString *sdkVersion = @"110";
/* 每一条埋点数据的物理ID,自增,生命周期和sessionId相同。特别注意:在sessionOver的时候,要把他置为0 */
@property
(
assign
,
nonatomic
)
NSInteger
serialId
;
// 用来记录除serverAPI以外的API
@property
(
strong
,
nonatomic
)
NSMutableArray
*
APIArray
;
@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
{
return
[[
self
alloc
]
initWithAppName
:
appName
channelId
:
channelId
];
...
...
@@ -60,7 +73,6 @@ static NSString *sdkVersion = @"110";
_greyType
=
@""
;
_userType
=
[[
NSMutableDictionary
alloc
]
initWithCapacity
:
0
];
_appVersion
=
[
PhobosUtil
getAppVersion
];
_APIArray
=
[
NSMutableArray
array
];
_signingType
=
PhobosSigningTypeUndefined
;
[
self
setupNotification
];
[
self
handleSessionStart
];
...
...
@@ -188,7 +200,7 @@ static NSString *sdkVersion = @"110";
phobosLog
(
@"handleAppInForeground"
);
[
self
handleSessionStart
];
[
self
handleEventDeviceOpened
];
[
self
fetchDataAndSend
];
[
self
sendImmediatelyNormalData
];
[
self
handlePVEventAppInForeground
];
}
...
...
@@ -201,7 +213,7 @@ static NSString *sdkVersion = @"110";
phobosLog
(
@"handleAppInBackgound"
);
[
self
handlePVEventAppInBackgound
];
[
self
handleSessionOver
];
[
self
fetchDataAndSend
];
[
self
sendImmediatelyNormalData
];
}
/**
...
...
@@ -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
-
(
void
)
onPVStart
:
(
UIResponder
<
PhobosPVProtocol
>
*
)
page
{
// 必须在此处调用一下referer,因为onControllerStart
...
...
@@ -341,7 +281,7 @@ static NSString *sdkVersion = @"110";
if
(
!
[
PhobosUtil
isNonEmpty
:
page
.
pageName
]
||
!
page
.
needLogPV
)
{
return
;
}
NSMutableDictionary
*
dict
=
[[
NSMutableDictionary
alloc
]
init
];
@try
{
[
dict
setObject
:[
PhobosUtil
currentTime
]
forKey
:
@"out"
];
...
...
@@ -382,45 +322,44 @@ static NSString *sdkVersion = @"110";
}
}
#pragma mark - 事件存储、发送
/**
* @brief 将埋点时间封装成词典数据
*
* @since 0.0.1
*/
-
(
NSDictionary
*
)
prepareDictionaryForEvent
:
(
NSString
*
)
event
Id
attributes
:
(
NSDictionary
*
)
attributes
{
[
self
catchNullForEvent
:
event
Id
attributes
:
attributes
];
-
(
NSDictionary
*
)
prepareDictionaryForEvent
:
(
NSString
*
)
event
Name
attributes
:
(
NSDictionary
*
)
attributes
{
[
self
catchNullForEvent
:
event
Name
attributes
:
attributes
];
NSMutableDictionary
*
dict
=
[[
NSMutableDictionary
alloc
]
init
];
@try
{
NSString
*
currentTime
=
[
PhobosUtil
currentTime
];
NSMutableDictionary
*
deviceParams
=
[
NSMutableDictionary
dictionaryWithObjectsAndKeys
:
[[[
ASIdentifierManager
sharedManager
]
advertisingIdentifier
]
UUIDString
],
@"idfa"
,
[[[
UIDevice
currentDevice
]
identifierForVendor
]
UUIDString
],
@"idfv"
,
[
PhobosUtil
deviceId
],
@"device_id"
,
@"ios"
,
@"device_type"
,
@"Apple"
,
@"manufacturer"
,
@
(
self
.
gps
.
coordinate
.
latitude
),
@"lat"
,
@
(
self
.
gps
.
coordinate
.
longitude
),
@"lng"
,
_netStatus
,
@"is_WiFi"
,
[
PhobosUtil
getIPAddress
:
YES
],
@"ip"
,
nil
];
NSMutableDictionary
*
deviceParams
=
[
NSMutableDictionary
new
];
[
deviceParams
setValue
:[[[
ASIdentifierManager
sharedManager
]
advertisingIdentifier
]
UUIDString
]
forKey
:
@"idfa"
];
[
deviceParams
setValue
:[[[
UIDevice
currentDevice
]
identifierForVendor
]
UUIDString
]
forKey
:
@"idfv"
];
[
deviceParams
setValue
:[
PhobosUtil
deviceId
]
forKey
:
@"device_id"
];
[
deviceParams
setValue
:
@"ios"
forKey
:
@"device_type"
];
[
deviceParams
setValue
:
@"Apple"
forKey
:
@"manufacturer"
];
[
deviceParams
setValue
:
@
(
self
.
gps
.
coordinate
.
latitude
)
forKey
:
@"lat"
];
[
deviceParams
setValue
:
@
(
self
.
gps
.
coordinate
.
longitude
)
forKey
:
@"lng"
];
[
deviceParams
setValue
:
_netStatus
forKey
:
@"is_WiFi"
];
[
deviceParams
setValue
:[
PhobosUtil
getIPAddress
:
YES
]
forKey
:
@"ip"
];
[
deviceParams
setValue
:
_networkStatus
forKey
:
@"net_type"
];
[
deviceParams
setValue
:[
UIDevice
platform
]
forKey
:
@"model"
];
[
deviceParams
setValue
:[
UIDevice
currentDevice
].
systemVersion
forKey
:
@"sys_version"
];
NSMutableDictionary
*
appParams
=
[
NSMutableDictionary
dictionaryWithObjectsAndKeys
:
_greyType
,
@"grey_type"
,
self
.
appName
,
@"name"
,
self
.
appVersion
,
@"version"
,
self
.
channelId
,
@"channel"
,
_userType
,
@"user_type"
,
self
.
currentCityId
,
@"current_city_id"
,
@
(
_serialId
++
),
@"serial_id"
,
nil
];
NSMutableDictionary
*
appParams
=
[
NSMutableDictionary
new
];
[
appParams
setValue
:
_greyType
forKey
:
@"grey_type"
];
[
appParams
setValue
:
_appName
forKey
:
@"name"
];
[
appParams
setValue
:
_appVersion
forKey
:
@"version"
];
[
appParams
setValue
:
_channelId
forKey
:
@"channel"
];
[
appParams
setValue
:
_userType
forKey
:
@"net_type"
];
[
appParams
setValue
:
_currentCityId
forKey
:
@"current_city_id"
];
[
appParams
setValue
:
@
(
_serialId
++
)
forKey
:
@"serial_id"
];
if
(
_signingType
==
PhobosSigningTypeDebug
||
_signingType
==
PhobosSigningTypeRelease
)
{
[
dict
setObject
:
@
(
0
)
forKey
:
@"is_release"
];
}
[
dict
setObject
:
event
Id
forKey
:
@"type"
];
[
dict
setObject
:
event
Name
forKey
:
@"type"
];
[
dict
setObject
:
appParams
forKey
:
@"app"
];
[
dict
setObject
:
sdkVersion
forKey
:
@"version"
];
[
dict
setObject
:
deviceParams
forKey
:
@"device"
];
...
...
@@ -435,124 +374,41 @@ static NSString *sdkVersion = @"110";
return
dict
;
}
/**
* @brief 保存数据到缓存层
*
* @param data 数据
*
* @since 0.0.1
*/
-
(
void
)
save
:
(
NSDictionary
*
)
data
{
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
;
}
#pragma mark - helpers
-
(
void
)
catchNullForEvent
:
(
NSString
*
)
eventName
attributes
:
(
NSDictionary
*
)
attributes
{
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
),
^
{
@try
{
for
(
NSString
*
key
in
attributes
.
allKeys
)
{
if
([
attributes
[
key
]
isMemberOfClass
:[
NSNull
class
]])
{
if
(
self
.
captureNullExpection
)
{
self
.
captureNullExpection
(
eventName
,
attributes
);
}
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
];
}
}
});
}
/*
从缓存区获取数据,发给服务器,请求成功的时候,把缓存区的数据删除掉
*/
-
(
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
]);
}
#pragma mark - track event handler
+
(
void
)
trackJsEvent
:
(
NSString
*
)
jsonString
{
@try
{
NSData
*
JSON
=
[
PhobosUtil
encodeJSON
:
dataArray
];
NSData
*
compressedData
=
[
PhobosUtil
compressData
:
JSON
];
if
(
compressedData
)
{
[
PhobosUtil
sendData
:
compressedData
success
:
^
(
NSInteger
code
)
{
phobosLog
(
@"✈ ---------- ✈ data arrived Mars"
);
[
GMCache
removeObjectAtDocumentPathWithkey
:
PhobosTempCacheKey
];
}];
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
)
{
...
...
@@ -560,109 +416,170 @@ static NSString *sdkVersion = @"110";
}
}
/*
从缓存区获取数据,发给服务器,请求成功的时候,把缓存区的数据删除掉
*/
-
(
void
)
sendArrayWithCurrentAPI
:
(
NSString
*
)
currentAPI
{
NSString
*
PhobosTempCacheKeyStr
=
[
PhobosUtil
MD5String
:[
PhobosUtil
MD5String
:
currentAPI
]];
// 两次加密作为key值,和缓存的key值作区分
NSMutableArray
*
dataArray
=
[
GMCache
fetchObjectAtDocumentPathWithkey
:
PhobosTempCacheKeyStr
];
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
{
NSData
*
JSON
=
[
PhobosUtil
encodeJSON
:
dataArray
];
NSData
*
compressedData
=
[
PhobosUtil
compressData
:
JSON
];
if
(
compressedData
)
{
[
PhobosUtil
sendData
:
compressedData
currentAPI
:
currentAPI
success
:^
(
NSInteger
code
)
{
phobosLog
(
@"✈ ---------- ✈ data arrived Mars"
);
[
GMCache
removeObjectAtDocumentPathWithkey
:
PhobosTempCacheKeyStr
];
}];
}
}
@catch
(
NSException
*
exception
)
{
phobosLog
(
exception
);
+
(
void
)
track
:
(
NSString
*
)
eventName
{
[
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
];
}
+
(
void
)
track
:
(
NSString
*
)
eventName
attributes
:
(
NSDictionary
*
)
attributes
sendNow
:
(
BOOL
)
sendNow
{
[
self
track
:
eventName
attributes
:
attributes
sendNow
:
sendNow
currentAPI
:
sharedClient
.
serverAPI
];
}
+
(
void
)
track
:
(
NSString
*
)
eventName
currentAPI
:
(
NSString
*
)
currentAPI
{
[
self
track
:
eventName
attributes
:@{}
sendNow
:
NO
currentAPI
:
currentAPI
];
}
+
(
void
)
track
:
(
NSString
*
)
eventName
attributes
:
(
NSDictionary
*
)
attributes
currentAPI
:
(
NSString
*
)
currentAPI
{
[
self
track
:
eventName
attributes
:
attributes
sendNow
:
NO
currentAPI
:
currentAPI
];
}
+
(
void
)
track
:
(
NSString
*
)
eventName
attributes
:
(
NSDictionary
*
)
attributes
sendNow
:
(
BOOL
)
sendNow
currentAPI
:
(
NSString
*
)
currentAPI
{
NSDictionary
*
dataDict
=
[
sharedClient
prepareDictionaryForEvent
:
eventName
attributes
:
attributes
];
if
(
sendNow
)
{
[
self
sendImmediatelyPhobosWithURL
:
currentAPI
data
:
dataDict
];
}
else
{
[
self
trackPhobosWithURL
:
currentAPI
data
:
dataDict
];
}
}
#pragma mark - 事件存储、发送
/**
该方法有改动,现在的逻辑是:当前方法只接受发送的请求,然后把数据转存到另一个缓存区,
让sendArray方法负责发送,数据一旦转移到缓存区,就把原有的数据干掉。
@author zhaiguojun 16-10-17 in (null)
@param array 参数
@param clean 是否立即清楚缓存
* 普通埋点
* @param url 接口url
* @param dataArray 埋点数据
* @param nowSend 是否需要发送当前缓存数据(app进入到后台、前台等情况)
*/
-
(
void
)
send
Array
:
(
NSArray
*
)
array
cleanCacheRightNow
:
(
BOOL
)
clean
{
@try
{
//1.获取缓存区的数据,把新数据追加进去
-
(
void
)
send
ImmediatelyNormalData
{
[
Phobos
trackPhobosWithURL
:
nil
data
:
nil
immediate
:
YES
];
}
NSMutableArray
*
dataArray
=
[
GMCache
fetchObjectAtDocumentPathWithkey
:
PhobosTempCacheKey
];
if
(
dataArray
)
{
[
dataArray
addObjectsFromArray
:
array
];
}
else
{
dataArray
=
[
NSMutableArray
arrayWithArray
:
array
];
}
[
GMCache
storeObjectAtDocumentPathWithkey
:
PhobosTempCacheKey
object
:
dataArra
y
];
//2.把缓存区的数据发送给服务器
[
self
sendArray
];
//3.把原有的数据删除
if
(
clean
)
{
[
GMCache
removeObjectAtDocumentPathWithkey
:
PhobosCacheKey
]
;
+
(
void
)
trackPhobosWithURL
:
(
NSString
*
)
url
data
:
(
NSDictionary
*
)
data
{
[
self
trackPhobosWithURL
:
url
data
:
data
immediate
:
NO
];
}
+
(
void
)
trackPhobosWithURL
:
(
NSString
*
)
url
data
:
(
NSDictionary
*
)
data
immediate
:
(
BOOL
)
immediate
{
dispatch_semaphore_wait
(
_normalSemaphore
,
DISPATCH_TIME_FOREVER
);
NSMutableDictionary
*
dataDict
=
[[
GMCache
fetchObjectAtDocumentPathWithkey
:
PhobosNormalCacheKey
]
mutableCop
y
];
NSInteger
count
=
0
;
if
(
!
immediate
)
{
dataDict
=
[
self
dataDict
:
dataDict
setObject
:
data
forKey
:
url
];
for
(
NSArray
*
phobosData
in
dataDict
.
allValues
)
{
count
+=
phobosData
.
count
;
}
}
@catch
(
NSException
*
exception
)
{
phobosLog
(
exception
);
[
GMCache
storeObjectAtDocumentPathWithkey
:
PhobosNormalCacheKey
object
:
dataDict
];
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
)
sendArray
:
(
NSArray
*
)
array
currentAPI
:
(
NSString
*
)
currentAPI
cleanCacheRightNow
:
(
BOOL
)
clean
{
@try
{
//1.获取缓存区的数据,把新数据追加进去
NSString
*
PhobosTempCacheKeyStr
=
[
PhobosUtil
MD5String
:[
PhobosUtil
MD5String
:
currentAPI
]];
// 两次加密作为key值,和缓存的key值作区分
NSMutableArray
*
dataArray
=
[
GMCache
fetchObjectAtDocumentPathWithkey
:
PhobosTempCacheKeyStr
];
if
(
dataArray
)
{
[
dataArray
addObjectsFromArray
:
array
];
}
else
{
dataArray
=
[
NSMutableArray
arrayWithArray
:
array
];
}
[
GMCache
storeObjectAtDocumentPathWithkey
:
PhobosTempCacheKeyStr
object
:
dataArray
];
//2.把缓存区的数据发送给服务器
[
self
sendArrayWithCurrentAPI
:
currentAPI
];
//3.把原有的数据删除
[
GMCache
removeObjectAtDocumentPathWithkey
:[
PhobosUtil
MD5String
:
currentAPI
]];
/// 实时埋点
+
(
void
)
sendImmediatelyPhobosWithURL
:
(
NSString
*
)
url
data
:
(
NSDictionary
*
)
data
{
dispatch_semaphore_wait
(
_realTimeSemaphore
,
DISPATCH_TIME_FOREVER
);
__block
NSMutableDictionary
*
dataDict
=
[[
GMCache
fetchObjectAtDocumentPathWithkey
:
PhobosRealTimeCacheKeys
]
mutableCopy
];
dataDict
=
[
self
dataDict
:
dataDict
setObject
:
data
forKey
:
url
];
NSInteger
allCount
=
dataDict
.
allKeys
.
count
;
// 请求个数
__block
finishCount
=
0
;
// 请求完成次数,不是请求成功次数,能在最后保证未发送成功的数据,能一次保存下来,等待下次发送
dispatch_semaphore_t
semaphore
=
dispatch_semaphore_create
(
1
);
// 因为网络请求是异步回调,需要保证数据安全
[
dataDict
enumerateKeysAndObjectsUsingBlock
:
^
(
NSString
*
_Nonnull
key
,
NSArray
*
_Nonnull
obj
,
BOOL
*
_Nonnull
stop
)
{
[
self
sendDataWithAPI
:
key
data
:
obj
successBlock
:^
(
BOOL
success
)
{
dispatch_semaphore_wait
(
semaphore
,
DISPATCH_TIME_FOREVER
);
finishCount
++
;
if
(
success
)
{
// 如果数据请求成功,删除当前数据的缓存
[
dataDict
removeObjectForKey
:
key
];
}
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
];
}
}
#pragma mark - helpers
-
(
void
)
catchNullForEvent
:
(
NSString
*
)
eventId
attributes
:
(
NSDictionary
*
)
attributes
{
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
),
^
{
@try
{
for
(
NSString
*
key
in
attributes
.
allKeys
)
{
if
([
attributes
[
key
]
isMemberOfClass
:[
NSNull
class
]])
{
if
(
self
.
captureNullExpection
)
{
self
.
captureNullExpection
(
eventId
,
attributes
);
#endif
[
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
;
}
break
;
}
}
}
@catch
(
NSException
*
exception
)
{
return
checkTimeError
;
}
});
}
return
NO
;
}
-
(
void
)
addNewApi
:
(
NSString
*
)
api
{
for
(
NSString
*
item
in
self
.
APIArray
)
{
if
([
api
isEqualToString
:
item
])
{
break
;
// 发送埋点数据
+
(
void
)
sendDataWithAPI
:
(
NSString
*
)
api
data
:
(
NSArray
*
)
dataArray
successBlock
:
(
SendDataSuccessBlock
)
successBlock
{
if
(
sharedClient
.
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
{
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
GMPhobos/Classes/PhobosConfig.h
View file @
eea2869b
...
...
@@ -18,7 +18,8 @@
#define PhobosHaveOpenApp @"PhobosHaveOpenApp" //是否打开过APP
#define PhobosBeginTime @"PhobosBeginTime" //记录APP打开|从后台启动时的时间戳
#define PhobosEndTime @"PhobosEndTime" //记录APP退出|退到后台时的时间戳
#define PhobosCacheKey @"PhobosCacheKey" //存放持久化埋点数据的key
#define PhobosNormalCacheKey @"PhobosNormalCacheKey" //存放持久化埋点数据的key
#define PhobosRealTimeCacheKeys @"PhobosRealTimeCacheKey" //存放持久化实时埋点数据的key
#define PhobosTempCacheKey @"PhobosTempCacheKey" //临时存放待发送埋点数据的key
#define PhobosShardCount 50 //收集数据分段发送的个数
...
...
GMPhobos/Classes/PhobosUtil.h
View file @
eea2869b
...
...
@@ -8,7 +8,7 @@
#import <Foundation/Foundation.h>
typedef
void
(
^
SendDataSuccessBlock
)(
NSInteger
code
);
typedef
void
(
^
SendDataSuccessBlock
)(
BOOL
success
);
@interface
PhobosUtil
:
NSObject
...
...
GMPhobos/Classes/PhobosUtil.m
View file @
eea2869b
...
...
@@ -123,11 +123,8 @@
// sendAsynchronousRequest 在iOS9以后y被废除了
NSURLSession
*
session
=
[
NSURLSession
sharedSession
];
NSURLSessionDataTask
*
dataTask
=
[
session
dataTaskWithRequest
:
request
completionHandler
:
^
(
NSData
*
_Nullable
data
,
NSURLResponse
*
_Nullable
response
,
NSError
*
_Nullable
error
)
{
if
(
!
error
)
{
//没有错误,返回正确;
if
(
success
)
{
success
(
200
);
}
if
(
success
)
{
success
(
!
error
?
YES
:
NO
);
}
}];
[
dataTask
resume
];
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment