所謂埋點就是在應用中特定的流程收集一些信息,用來跟蹤應用使用的狀況,后續(xù)用來進一步優(yōu)化產品或是提供運營的數(shù)據(jù)支撐。那么埋點方案又該如何設計呢?首先來定義一下通用的數(shù)據(jù)模型和格式, 便于在每個應用中可重復使用, 統(tǒng)一ETL處理。
數(shù)據(jù)模型和格式
用戶行為數(shù)據(jù)格式
用戶行為數(shù)據(jù)[Action]代表的是歷史上已經發(fā)生過用戶行為事件,一般來說不應該需要進行更新 [比如登錄,注冊,戰(zhàn)斗,消費等等
數(shù)據(jù)上報Json格式
{
"type": "action", // type為action, 代表是event事件
"event": "$register",// 事件名字
"uid": "01cc9e2b80b5c37281b3c3f4974f8ef6", // 賬號唯一ID
"uid_type": "guest", // 賬號類型
"time": 1435290195610, // 上報的13位時間戳
"properties": { //事件屬性
"device_no": "dsfhksdfsklljljdh",
"device_name": "oppo",
"device_type": "idfa",
"os": "ios", // 操作系統(tǒng)
}
}
設備行為數(shù)據(jù)格式
沒有用戶ID, 只有設備ID時的行為, 比如應用商店的點擊,曝光,下載和啟動游戲激活等事件
數(shù)據(jù)上報Json格式
{
"type": "device",// 必選, 事件為event[不可更改的日志],
"event": "$ad_view",// 必選, 廣告事件名字
"device_no": "device_no10",// 設備唯一id
"device_type": "idfa",// 獲取設備的類型
"device_name": "device_no1_name",// 設備名
"time": 13243423432,// 上報的時間戳
"properties": {// 投放渠道包信息填寫
"os": "ios", // 操作系統(tǒng)
"media": "今日頭條",// 廣告媒體
"optimizer": "小小",// 廣告優(yōu)化師
"advertiser": "大大" // 廣告商
}
}
用戶屬性數(shù)據(jù)格式
記錄和收集用戶畫像,描述用戶的長期屬性(也即 Profile),比如金幣,等級等,可以增刪改
{
"type": "profile_set", // type為profile_set, 代表是user實體設置
"uid": "01cc9e2b80b5c37281b3c3f4974f8ef6", // 唯一賬號id
"uid_type": "guest", // 賬號類型
"time": 1435290195610, // 上報的時間戳
"properties": { // 變化的用戶屬性
"level":33,
"vip": 3
}
}
數(shù)據(jù)上報服務設計
以上數(shù)據(jù)格式, 可以滿足不同應用的埋點, 那么數(shù)據(jù)采集有幾種方式可以選擇, 一種是采集Log日志,另一種是設計數(shù)據(jù)接收服務。
采集Log日志的方式, 需要過濾掉很多無效日志, 同時每臺服務器需要部署采集器,而接收服務可以集中處理所有有效數(shù)據(jù), 統(tǒng)一打印日志, 采集到Kafka, 以下對該服務的設計做一個簡單分析。
- 可以接收批量數(shù)據(jù), 減少QPS
- 對IP進行統(tǒng)一解析并拆分為地區(qū)和網(wǎng)絡信息
接口協(xié)議
請求方式
- https://xxxxxx/data_api/events_report
- Method: POST
- Content-Type: application/json
請求參數(shù):
| 字段 | 數(shù)據(jù)類型 | 是否必選 | 備注 |
|---|---|---|---|
| apiKey | string | 是 | 接口驗證key, 生成算法:md5(EventReport_$appId_secret) |
| appId | int | 是 | 應用唯一id, 由數(shù)據(jù)中心提供 |
| timezone | string | 是 | 時區(qū),示例:Asia/Shanghai(不要使用 utc+8 方式) |
| dataList | []map[string]interface{} | 是 | 上報數(shù)據(jù)格式 []map[string]interface{} , 具體下文見數(shù)據(jù)模型和格式 |
| compression | string | 否 | 壓縮算法, 默認是none代表不壓縮 |
返回參數(shù)
http.StatusCode != 200, 說明參數(shù)解析有問題
| 參數(shù)名 | 類型 | 說明 |
|---|---|---|
| code | int32 | 0為正常, 1000為異常,1001 為用戶請求參數(shù)錯誤 |
| message | string | 顯示正常或異常信息 |
| data.fail_index | int32 | 顯示上報失敗的數(shù)據(jù)條數(shù)index |
接口案例
{
"apiKey": "6a35d36770b4b2e34d2d0af6cf7daeec",
"appId": 2,
"timezone": "Asia/Shanghai",
"dataList": [
{
"type": "action", //代表是類型, 從上面三種數(shù)據(jù)格式中確認
"event": "$register", // 事件名字
"uid": "01cc9e2b80b5c37281b3c3f4974f8ef6",// 唯一賬號id
"uid_type": "guest", // 賬號類型
"time": 1435290195610,// 上報的時間戳, 13位毫秒級
"properties": {
"device_no": "dfjsdfgjsfs",
"device_name": "oppo",
"device_type": "idfa"
}
},
{
"type": "action", //代表是類型, 從上面三種數(shù)據(jù)格式中確認
"event": "$login", // 事件名字
"uid": "01cc9e2b80b5c37281b3c3f4974f8ef6",// 唯一賬號id
"uid_type": "guest", // 賬號類型
"time": 1435290195610,// 上報的時間戳, 13位毫秒級
"properties": {
}
}
],
"compression": "none"
}
技術方案
1.apiKey在創(chuàng)建游戲的時候生成, 可更改, 緩存到Redis。
2.批量處理數(shù)據(jù), 解析IP, 打印日志
數(shù)據(jù)上報SDK
- 將數(shù)據(jù)模型進行封裝, 封裝具體接口調用過程, 用戶無需關心具體實現(xiàn)
- 數(shù)據(jù)上報封裝成批量, 定時, 異步的方式, 提供傳輸性能
- 錯誤處理只限于內部代碼, 無需拋給調用者, 打印錯誤日志即可。
架構設計

開源代碼
Go SDK: https://gitee.com/carollia/data-sdk-go
Java SDK: https://gitee.com/carollia/data-sdk-java
Lua SDK: https://gitee.com/carollia/data-sdk-lua
系列文章
第一篇: Ambari自動化部署
第二篇: 數(shù)據(jù)埋點設計和SDK源碼
第三篇: 數(shù)據(jù)采集和驗證方案
第四篇: ETL實時方案: Kafka->Flink->Hive
第五篇: ETL用戶數(shù)據(jù)處理: kafka->spark->kudu
第六篇: Presto分析模型SQL和UDF函數(shù)