目錄
- 背景與目標(biāo)
- 埋點系統(tǒng)架構(gòu)
- 新精準(zhǔn)曝光系統(tǒng)
- 埋點驗證可視化
- 成果與展望
1背景與目標(biāo)
如圖所示,京東到家埋點的研發(fā)鏈路可以大致分為四步:
- 首先是在埋點需求平臺進行 埋點需求的收集
- 然后在需求平臺( 天河系統(tǒng): 基于web前端的到家埋點需求管理平臺,產(chǎn)品的埋點需求在這個平臺與開發(fā)對齊 )上 按照埋點數(shù)據(jù)模板進行開發(fā)
- 開發(fā)完成后,通過上報 日志對埋點進行 人工驗證
- 最后測試通過埋點數(shù)據(jù)展示平臺,通過 數(shù)據(jù)的回溯進行埋點數(shù)據(jù)驗證
開發(fā)和驗證階段是對埋點數(shù)據(jù)準(zhǔn)確性影響最大的兩個節(jié)點。從到家埋點落地以來,準(zhǔn)確性一直不高。目前的App端埋點系統(tǒng)已經(jīng)不足以支撐越來越復(fù)雜的業(yè)務(wù)需求,冗余埋點參數(shù)一直得不到有效的清理,埋點系統(tǒng)對業(yè)務(wù)的侵入性也越來越大,開發(fā)過程中要寫很多與業(yè)務(wù)無關(guān)的代碼來適配埋點的需求,清晰的模塊化結(jié)構(gòu)因此產(chǎn)生了不少的耦合。
對埋點鏈路的各個節(jié)點的痛點進行了總結(jié):
- 無效埋點數(shù)據(jù) :露出上報并沒有反映真實用戶行為,由于精準(zhǔn)曝光規(guī)則的缺失,在頁面滑動過程中,用戶沒看見的元素也被當(dāng)成曝光行為進行上報,產(chǎn)生了大量 無效 埋點數(shù)據(jù)
- 曝光局限性 :由于埋點規(guī)則不可調(diào)整的局限性,可視區(qū)域的規(guī)則區(qū)分粒度比較粗,所以導(dǎo)致埋點不準(zhǔn)確
- 開發(fā)效率低 :埋點需求占用了大量的開發(fā)時間,同時埋點與業(yè)務(wù)模塊間耦合嚴(yán)重
- 準(zhǔn)確性不高 :依靠人工驗證埋點,很難對已上線的埋點進行二次校驗。而埋點的需求迭代又有可能影響到已有埋點,導(dǎo)致線上埋點數(shù)據(jù)使用的過程中,大約有10%的埋點數(shù)據(jù)不準(zhǔn)確,不能有效對產(chǎn)品需求進行支撐
通過原鏈路各個節(jié)點的痛點分析,我們對需要解決的問題進行了合并和歸納,總結(jié)出來項目核心目標(biāo)。
核心目標(biāo)
到家精準(zhǔn)埋點系統(tǒng)旨在實現(xiàn)三個業(yè)務(wù)上的目標(biāo):
- 統(tǒng)一 埋點規(guī)則 設(shè)計 ,將埋點的各種行為進行區(qū)分和細(xì)化。(埋點數(shù)據(jù)的業(yè)務(wù)定義,通過整理所有歷史的埋點,將不規(guī)則的埋點進行優(yōu)化調(diào)整,以達到埋點規(guī)則的統(tǒng)一)
- 提升埋點 準(zhǔn)確率達到99% 以上
- 過濾埋點無效數(shù)據(jù),更加精準(zhǔn)進行上報,降低埋點數(shù)據(jù)成本(硬件成本和網(wǎng)絡(luò)成本)
技術(shù)實現(xiàn)將圍繞三個目標(biāo):
- 降低 埋點 開發(fā)成本
- 曝光規(guī)則可配置, 不同埋點規(guī)則靈活可變
- 埋點可以進行 有效的機器校驗以及可視化校驗
2埋點系統(tǒng)架構(gòu)
埋點規(guī)則與新系統(tǒng)架構(gòu)設(shè)計
目前, App端埋點 采集策略分為 點擊、 頁面以及曝光埋點三種:
- 點擊埋點與業(yè)務(wù)耦合性最高,但是觸發(fā)條件以及使用上是最簡單的一個,可優(yōu)化的地方并不多。
- 頁面埋點主要負(fù)責(zé)記錄頁面的生命周期,用以還原 頁面 使用的完整軌跡。功能實現(xiàn)由基礎(chǔ)模塊統(tǒng)一處理,這塊業(yè)務(wù)耦合性最低,對業(yè)務(wù)的侵入性也最低,在業(yè)務(wù)開發(fā)的時候?qū)τ诖祟惵顸c幾乎無感知。
- 曝光埋點則較為復(fù)雜,各種業(yè)務(wù)的埋點規(guī)則各不相同,有的重復(fù)露出不需要埋點上報,而有的重復(fù)露出就需要多次上報,對業(yè)務(wù)代碼的侵入較大,也是占用開發(fā)時間最多的埋點種類。
原先的曝光系統(tǒng)以控件的露出作為上報時機,以全局唯一標(biāo)識id對相同曝光埋點進行聚合,當(dāng)App端收集滿十條,切頁或切后臺時,將收集的埋點文件上報,最終將數(shù)據(jù)上傳到埋點數(shù)據(jù)庫。由于對控件露出判斷以及各種埋點參數(shù)的傳遞,影響到正常業(yè)務(wù)模塊的邏輯實現(xiàn),所以解決埋點露出判斷和埋點參數(shù)的傳遞就成為架構(gòu)設(shè)計中的重要考量。
如上圖所示,我們將整個埋點系統(tǒng)架構(gòu)拆分為了埋點適配層,埋點驗證層,埋點服務(wù)層三個層級。
埋點適配層
埋點適配層(埋點上層服務(wù)層)主要用以消除不同應(yīng)用之間的差距, 針對不同業(yè)務(wù)進行 參數(shù)的傳遞適配。結(jié)合客戶端自身業(yè)務(wù),提供曝光、PV和Click的埋點服務(wù)協(xié)議聲明,不負(fù)責(zé)具體埋點服務(wù)的實現(xiàn)。
埋點驗證層
埋點驗證層與埋點需求平臺進行聯(lián)動,通過埋點需求平臺提供的埋點模板數(shù)據(jù),與客戶端上傳的真實數(shù)據(jù)進行數(shù)據(jù)正確性校驗。實現(xiàn)方式上我們選擇以AOP形式切入,降低埋點驗證與業(yè)務(wù)的影響,將驗證與埋點系統(tǒng)隔離。
埋點服務(wù)層
埋點服務(wù)層(埋點底層服務(wù)層)包括精準(zhǔn)曝光系統(tǒng)、曝光聚合系統(tǒng)以及埋點數(shù)據(jù)文件上傳等服務(wù)功能。
精準(zhǔn)曝光系統(tǒng)將所需要的服務(wù)進行封裝,接入App配置系統(tǒng)下發(fā)的曝光規(guī)則來進行曝光規(guī)則的調(diào)整,然后通過埋點適配層的調(diào)用以及容器的傳入來監(jiān)聽客戶端曝光容器(EPView)的曝光事件,觸發(fā)曝光埋點上傳,最終流向到家埋點數(shù)據(jù)庫,進行數(shù)據(jù)歸檔。
3新精準(zhǔn)曝光系統(tǒng)
以曝光舉例,之前的埋點流程:
原先的曝光系統(tǒng)痛點:
- 開發(fā)成本大,業(yè)務(wù)方需要編寫大量的代碼來添加埋點,往往添加一個埋點成本就需要至少50行代碼,并且同一容器的不同埋點代碼中存在許多重復(fù)的代碼邏輯
- 精準(zhǔn)曝光的缺失,不支持對露出比例以及時長的判斷
- 不支持對可見區(qū)域不同的判斷,如有的頁面帶導(dǎo)航欄,有的沒有導(dǎo)航欄,一律按照沒有導(dǎo)航欄處理, 埋點不夠精確
- 針對部分埋點計算沒有優(yōu)化,將傳入的所有追蹤實例遍歷計算, 計算效率低
- 不支持云端配置下發(fā), 曝光規(guī)則單一
如果可以將大量的重復(fù)性的代碼收口統(tǒng)一管理,開發(fā)只需要一行代碼搞定,那么埋點開發(fā)測的效率就提高了許多。但是中間有比較多的問題需要解決。App端控件容器種類較多,想要收口統(tǒng)一管理,需要適配 不同類型的容器控件 。原系統(tǒng)之所以沒能收口,就是因為無法在 黑盒的情況下適配 各種業(yè)務(wù)場景 。
新精準(zhǔn)曝光系統(tǒng)
新精準(zhǔn)曝光系統(tǒng)在原有的系統(tǒng)上進行優(yōu)化,新增功能點支撐:
- 過濾掉業(yè)務(wù)端的重復(fù)添加曝光
- 將跟蹤加入的業(yè)務(wù)視圖滑動/拖動/動畫/隱藏等,與UE相關(guān)行動因子內(nèi)置進曝光系統(tǒng)內(nèi)部
- 數(shù)據(jù)可配置,露出比例/時長/云端配置等功能內(nèi)置
- 埋點聚合/文件寫入/文件上傳
該系統(tǒng)最初的核心設(shè)計目標(biāo)就是將大量業(yè)務(wù)重復(fù)邏輯植入到系統(tǒng)內(nèi)部,針對不同的滑動控件進行匹配判斷,實現(xiàn)容器的自動追蹤;針對不同的刷新模式,自動進行是否重復(fù)上報邏輯判斷;提供不同的接口以適應(yīng)不同業(yè)務(wù);對容器的展開和收起的自動判斷等。
而將業(yè)務(wù)的大量代碼,通過無痕方式切入,存在許多需要攻克的 技術(shù)難點 :
- 滑動控件并不是統(tǒng)一的,有滑動的控件,也有非滑動控件。如何適配并且無痕自動追蹤滑動/切頁而產(chǎn)生的控件露出事件?
我們的方案是針對不同的容器的種類進行判斷匹配,通過KVO的方式追蹤容器本身屬性的變化作為露出的觸發(fā)點,而計時器作為頁面無滑動時的補充手段,從而達到無痕追蹤的效果。
- 作 為 黑 盒 系 統(tǒng) , 需要追蹤所有埋點業(yè)務(wù)視圖的露出 事件, 所以要保存埋點業(yè)務(wù)視 圖與埋點行為的 對應(yīng)關(guān) 系 。 如何保證埋點業(yè)務(wù)視圖與埋點數(shù)據(jù)的對應(yīng)?
在前期系統(tǒng)適配模型中建立輸入口,通過傳入系統(tǒng)初始化模型,來進行業(yè)務(wù)視圖埋點數(shù)據(jù)key的傳入。
- 為了避免造成控件生命周期混亂的問題,如何管理對象強弱引用,保證內(nèi)部引用與外部生命周期一致?
通過對關(guān)系的梳理,確定從滑動容器/滑動容器模型 –> 事件模型的綁定關(guān)系,將內(nèi)部模型生命周期與外部視圖進行綁定,來實現(xiàn)外部視圖銷毀后,事件追蹤模型也會銷毀。下面會進行詳細(xì)展開說明。
- 曝光追蹤是否存在性能問題?
在計算追蹤的時候,因為需要調(diào)用UIKit的frame進行位置獲取,這一步必須在主線程完成,為了不影響性能,需要進行計算量的優(yōu)化。為了盡量減少需要計算的數(shù)量,我們設(shè)計了兩層漏斗進行過濾:第一層過濾是通過遞歸判斷容器及其父容器是否隱藏,排除掉不活躍的容器;第二層過濾是在活躍的容器中,排除掉其內(nèi)部不活躍的子容器。最后剩余的容器才進行frame的計算,這樣每次滑動的時候,計算量均值大約在10個左右,對性能影響降到最低。
上述技術(shù)難點的實現(xiàn)細(xì)節(jié)受限于篇幅不再一一展開。下面列舉iOS端,來說明如何通過 管理 引用機制來 解決 生命周期混亂的問題 。
iOS端追蹤與引用機制
通過分析整體埋點機制可知, 埋點視圖(EPView) 存在從數(shù)據(jù)模型(Model)到埋點數(shù)據(jù) (EPModel) 的對應(yīng)關(guān)系,所以建立埋點控件到埋點數(shù)據(jù)的映射關(guān)系是可行的,順著這個切入點來進行整個生命周期管理的設(shè)計。
新版埋點系統(tǒng)提供了兩種埋點追蹤方式:埋點視圖(EPView)或者埋點數(shù)據(jù)(EPModel)來與埋點行為進行一一對應(yīng),通過建立內(nèi)部EPView/EPModel → UUID → 埋點行為模型(TrackerObj)的映射對所有埋點狀態(tài)進行追蹤。業(yè)務(wù)方將需要追蹤的容器傳入,通過容器類型判斷進行滑動/拖動/動畫/隱藏等行為的監(jiān)聽。
系統(tǒng)為了不影響外部生命周期,對外部引用重新做了梳理。
圖中綠色代表弱引用,紅線代表強引用。如圖所示,系統(tǒng)內(nèi)部使用兩個弱引用map表來儲存所需的信息,而每個子容器的滑動容器則通過追蹤模型來追蹤。這樣建立起從EPView –> 追蹤模型 –> 滑動容器的綁定關(guān)系。當(dāng)外部業(yè)務(wù)視圖(EPView)或者業(yè)務(wù)模型(EPModel)被釋放的時候,業(yè)務(wù)不需要回調(diào)曝光系統(tǒng)進行相應(yīng)的銷毀,該鍵值會被自動釋放,這樣極大地縮減了接入的成本。
對外收口的部分,通過精準(zhǔn)曝光埋點提供的API 來明確埋點追蹤的綁定關(guān)系 :
/// 添加ep進入追蹤 需要傳入該資源位唯一識別碼
/// 適用場景:刷新之后,刷了模型,但是資源位沒變化,不需要重新報的場景
/// @param epView 需要追蹤的epView
/// @param epUID epUID為該資源位唯一識別碼,只要這個碼不變,并且在屏幕內(nèi),即使多次添加不會再次回調(diào)
/// @param userAction 與此epview綁定的數(shù)據(jù)model的userAction
/// @param containers 底部需要追蹤的滾動容器
/// @param visibleRect 需要曝光的可視區(qū)域 坐標(biāo)系相對于UIWindow
/// @param callback 埋點回調(diào),此處需要手動去處理數(shù)據(jù)拼接以及埋點
- (void)addEPView:(UIView *)epView
epUniqueID:(NSString *)epUID
userAction:(NSString *)userAction
containers:(NSArray<UIView *> *)containers
visibleRect:(CGRect)visibleRect
epEventCallback:(void (^)(UIView * _Nonnull epView))callback;
/// 添加ep進入追蹤 需要傳入數(shù)據(jù)Model
/// 適用場景:刷新之后,模型發(fā)生了改變并且需要重新曝光的場景
/// @param epView 需要追蹤的epView
/// @param model 與此epview綁定的數(shù)據(jù)model,模型一旦發(fā)生改變(對同一個資源位來說模型地址發(fā)生變化),則會再次觸發(fā)回調(diào)
/// @param userAction 與此epview綁定的數(shù)據(jù)model的userAction
/// @param containers 底部需要追蹤的滾動容器
/// @param visibleRect 需要曝光的可視區(qū)域 坐標(biāo)系相對于UIWindow
/// @param callback 埋點回調(diào),此處需要手動去處理數(shù)據(jù)拼接以及埋點
- (void)addEPView:(UIView *)epView
model:(NSObject *)model
userAction:(NSString *)userAction
containers:(NSArray<UIView *> *)containers
visibleRect:(CGRect)visibleRect
epEventCallback:(void (^)(UIView * _Nonnull epView))callback;
i OS使用系統(tǒng)的KVO機制, 輔助針對視圖的動畫/隱藏等監(jiān)聽來實現(xiàn)。 系統(tǒng)KVO機制雖然好用,但是存在一個致命的缺陷,就是監(jiān)聽實體釋放的時候,需要監(jiān)聽者手動釋放,不然就會導(dǎo)致崩潰。而代理KVO機制則很好地 解決了這個問題,使用代理代替原先的監(jiān)聽者進行監(jiān)聽,而代理者與被監(jiān)聽的控件生命周期保持一致。 這樣便 無需主動解除監(jiān)聽, 彌補了被監(jiān)聽的實體釋放而無法通知監(jiān)聽實體釋放問題。
業(yè)務(wù)方傳入的無論是 業(yè)務(wù)視圖(EPView)或者業(yè)務(wù)模型(EPModel),都采取統(tǒng)一轉(zhuǎn)換為UUID的形式 ,保證了KV鍵值的統(tǒng)一,提升排查問題的便捷性。
接口層上,區(qū)分了曝光的追蹤服務(wù)、曝光節(jié)點的回調(diào)服務(wù)以及底層上報服務(wù)三個接口,分別由三個不同的實例實現(xiàn),保證不同業(yè)務(wù)服務(wù)之間的隔離。
針對曝光埋點設(shè)計了兩個追蹤的節(jié)點,目的是判斷是否需要上報曝光埋點:
- 第一個是每0.5秒鐘觸發(fā)定時timer,此timer會輪詢所有的已添加進來的需要曝光的視圖進行計算
- 第二個是追蹤節(jié)點為容器滑動回調(diào)(KVO機制實現(xiàn)),此回調(diào)僅會將滑動容器所綁定的EPView進行計算
在節(jié)點觸發(fā)的時候,會從兩個EPMap中直接獲取所需數(shù)據(jù),不需要額外的過濾操作,降低了計算的次數(shù),提高整體計算效率。
4 埋點驗證可視化
業(yè)務(wù)側(cè)痛點收集和分析
- 埋點測試效率 較低 :一次滑動產(chǎn)生大量埋點數(shù)據(jù)。之前的驗證方式是通過打日志方式、抓包或者數(shù)據(jù)展示平臺直接查看來進行驗證,數(shù)據(jù)無直觀關(guān)聯(lián),需要人眼主動進行關(guān)聯(lián),驗證效率非常低
- 多次上報的曝光次數(shù)驗證困難:有很多其他數(shù)據(jù)干擾,直接抓包或者數(shù)據(jù)展示平臺無法區(qū)分不同的session,只能通過時間節(jié)點方式進行人工關(guān)聯(lián),容易出錯
- 相關(guān)數(shù)據(jù)難以查找:在數(shù)據(jù)展示平臺上只提供了一級信息的搜索,沒辦法更加詳細(xì)的相關(guān)信息的篩選
技術(shù)側(cè)痛點
- 缺乏驗測模型數(shù)據(jù):要做數(shù)據(jù)驗證,沒有相關(guān)的數(shù)據(jù)模型進行支撐,無法對本次埋點結(jié)果進行自動化的機器校驗
- 很難做數(shù)據(jù)掛鉤:通過AOP切面方式接入埋點驗證,最大化不干擾業(yè)務(wù)端,帶來的弊端就是很難做數(shù)據(jù)掛鉤,捕捉到的埋點視圖也很難與埋點數(shù)據(jù)進行匹配識別。 數(shù)據(jù)平臺上的數(shù)據(jù)密集且難尋,用肉眼驗證相當(dāng)復(fù)雜 且容易出錯
埋點驗證功能設(shè)計
埋點驗證主要包含以下功能點:
- 曝光埋點狀態(tài)、數(shù)據(jù)以及上報次數(shù)可視化驗證
- 埋點數(shù)據(jù)列表展示以及埋點搜索篩選
- 天河模板下發(fā)以及數(shù)據(jù)自動校驗 曝光埋點狀態(tài)、數(shù)據(jù)以及上報次數(shù)可視化驗證
為了盡可能追蹤埋點狀態(tài),根據(jù)曝光埋點鏈條的不同節(jié)點,將曝光埋點行為狀態(tài)化分拆成三種狀態(tài):
- 追蹤中【紅色】:埋點已經(jīng)添加進來,還未判斷為露出狀態(tài)
- 控件露出【黃色】:控件根據(jù)精準(zhǔn)曝光條件判斷為露出,但未上報狀態(tài)
- 已上報【綠色】:曝光時長滿足延遲時間,已經(jīng)回調(diào)并且上報
在業(yè)務(wù)端這三種狀態(tài)以不同顏色來表示,通過給埋點控件染色,以達到狀態(tài)可視化效果。驗測的時候, 只需要判斷顏色的變化是否符合預(yù)期,則可以判定埋點節(jié)點的準(zhǔn)確性 。
通過對控件的上報埋點回溯綁定當(dāng)前控件的埋點數(shù)據(jù),可以實現(xiàn)使用過程中, 長按控件即顯示該控件目前的埋點數(shù)據(jù) 。這樣快速追蹤控件的埋點數(shù)據(jù),極大地縮短在海量數(shù)據(jù)中尋找控件數(shù)據(jù)的時間。并且 在控件最上層添加信息label,展示當(dāng)前已經(jīng)上報過埋點的次數(shù),方便進行上報次數(shù)的正確性校驗 。
埋點可視化驗證
埋點數(shù)據(jù)列表展示以及埋點搜索篩選
開發(fā)過程中,上報的埋點數(shù)據(jù)列表,以時間為單位進行排序,并且提供搜索功能。搜索的加入能夠方便進行埋點數(shù)據(jù)的歸類查找。而篩選功能可以方便驗測人員直接進行埋點日志的過濾。
App端內(nèi)部埋點日志展示與篩選查詢
天河模板下發(fā)以及數(shù)據(jù)自動校驗
前端系統(tǒng)與天河系統(tǒng)打通,通過下載天河系統(tǒng)的數(shù)據(jù)模板和上報數(shù)據(jù)進行比對,提前發(fā)現(xiàn)埋點問題。App端拿到天河系統(tǒng)提供的Key值進行校驗,最終驗證該埋點數(shù)據(jù)的準(zhǔn)確性,如果key值缺失,進行toast提示提醒,這樣在開發(fā)驗測階段就可以輕易發(fā)現(xiàn)有問題的埋點。
5成果與展望
業(yè)務(wù)滲透
目前在App端,已完成 80% 相關(guān)頁面的切換
成本節(jié)約
統(tǒng)計近5期的版本,清理 15.08% 的冗余埋點數(shù)據(jù),節(jié)約了成本
埋點準(zhǔn)確率提升
準(zhǔn)確率從原先的90%提升至 98%
開發(fā)提效
代碼行數(shù)極大得縮減,從原先的平均50行到1行,代碼縮減比例達到98%。從而將3天/期/人的埋點開發(fā)時間縮短至 0.5天/期/人 的埋點開發(fā)時間。目前到家3個ToC端App已經(jīng)全面接入使用,針對不同app環(huán)境均作了適配,實現(xiàn) 系統(tǒng)的復(fù)用 。
驗測提效
驗測時間縮短了60%,效率 提升了兩倍 以上
展望
到家新版埋點系統(tǒng)已經(jīng)穩(wěn)定運作多版本,目前已經(jīng)初步達到技術(shù)側(cè)以及業(yè)務(wù)側(cè)定的目標(biāo)。當(dāng)然,在埋點鏈路的優(yōu)化建設(shè)上還有許多不足的地方,如:
- 埋點實踐只在App端進行了落地,而針對H5、RN的兩端的落地,現(xiàn)在還在改造中,很快就會實現(xiàn)三端的對齊
- 結(jié)合已有能力進行拓寬,借助數(shù)據(jù)模型到數(shù)據(jù)下發(fā)的閉環(huán),提升至100%的埋點準(zhǔn)確率
- 在效率方面,針對標(biāo)準(zhǔn)化后的埋點進行基類統(tǒng)一處理的方案,將最后的一行代碼也優(yōu)化掉
到家App團隊接下來會在這幾個方面繼續(xù)深耕,探索并落地更加完善的埋點系統(tǒng)實踐。
作者:盧葦白
來源:微信公眾號:達達集團技術(shù)
出處:https://mp.weixin.qq.com/s?__biz=MzAwMzg1ODMwNw==&mid=2653796170&idx=1&sn=f1efb5623ec6a236f393df32a1c29975
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 sumchina520@foxmail.com 舉報,一經(jīng)查實,本站將立刻刪除。