前言 : 在4月25日,我參加了前端早早聊的在線直播話題---前端如何搞監控。 聽完以後收穫很大。我將把會議總結爲前端搞監控的價值、須要監控的內容等方向去描述,並以自研監控SDK的經驗爲例,進一步瞭解前端搞監控的技術點所在。前端
一 前端監控系統概覽:
1 爲何要作一套前端監控系統?
經過用戶行爲採集分析,當前端及客戶端線上出現異常時,能夠經過用戶行爲鏈及設備環境,快速定位線上環境的問題所在。android
齊次,當功能上線後,用戶的使用效果沒辦法衡量。須要數據指標去衡量,好比功能使用率、性能指標等。數據庫
業務方的對業務的創意及需求須要反覆不斷的調優、開發,相同的組件開發了無數個,極可能明天又得改回去,這就形成了大量的資源浪費。若是沒有一個量化體系的話,運營只能經過上次成功的經驗來感受。因此須要經過對用戶數據的監控,從而獲得一個調優策略和量化指標。小程序
以後,咱們須要知道對於界面設計風格及投放的廣告資源,哪些手段會更有價值,去作一我的羣的細分,提升用戶體驗。微信小程序
2.前端監控須要監控什麼?
前端監控採集的內容主要包括行爲分析、異常監控、性能監控等。跨域
其行爲分析主要有:頁面的進入、離開、點擊、滾屏、自定義事件promise
簡單作法是在項目的編譯過程當中,將項目ID、頁面ID等掛載在標籤上,當進入頁面時,咱們就能夠根據這些ID去定位惟一一個頁面,這樣就能夠知道用戶的頁面進入、離開及按鈕的點擊等事件服務器
在這張圖裏能夠看到上報的數據,好比座標、分辨率等,從而能夠分析用戶點擊的熱力圖、平臺的總體兼容性、當前網絡狀況等 另外,還須要有對用戶頁面的瀏覽流程的一個上報,能夠將ID拼接在超連接裏,這樣當用戶點擊頁面跳轉以後,就會被代入下一個頁面,而後在下個頁面中加載SDK後就會將該連接的值進行上報不過用戶可能並非完整地去走過了一個頁面點擊流程,而是從中間的頁面進入好比點擊了超連接,就須要讓收集到的數據更有參考價值,以更準確地反映用戶真實狀況。 在路徑分析裏,去查看用戶的來源和去向 微信
另外能夠記錄用戶的停留時長,由於有些用戶可能一秒就關閉了窗口,而有些用戶因沒有關閉窗口就致使停留的時間很是長 最後基於各個頁面的分析數據,針對性地優化頁面佈局,增長用戶吸引力,也能夠根據用戶的行爲,深刻分析用戶對內容的注意力在哪塊3.前端監控設計策略
3.1 面向組件設計監控策略
咱們將對網頁的埋點分爲以下幾個級別,從而更好地爲後面的分析提供服務網絡
對不一樣的組件定義一些分析指標如轉化率、渲染速度等,從而把一些效果比較好的組件的優先級不斷提高 以後咱們就能夠對不一樣的組件進行一個綜合的對比爲了更方便分析數據。當內網訪問時,CDN判斷爲白名單用戶,就會爲頁面注入數據化分析能力,從而更方便地實時查看數據而無需再打開額外的數據分析平臺
3.2 面向業務設計監控策略
對於不一樣風格的組件,須要進行一個精準的人羣的劃分
除了須要分析頁面跟用戶行爲的關係以外,咱們還須要依賴其餘平臺的信息,就好比在商城平臺,疫情的爆發致使口罩的需求相應增長,微博抖音上某個商品的熱度增長,從而爲商品去打一個趨勢分並分析用戶的人羣畫像 當發現監控數據在某個時間段發生了波動,從而幫助咱們更好地去定位緣由。好比是商品大促?媒體宣傳?整個下來須要有一個數據採集、數據存儲、數據清洗、數據異常、數據展現的過程。
其中採集方式包括無埋點採集和有埋點採集。 無埋點採集主要是經過在框架層預設SDK,預設通用的事件。 有埋點採集對用戶的瀏覽日誌、瀏覽內容、觸發時機等一些自定義事件的一種採集方式
有時會根據業務去增長一些自定義採集 還須要對多端進行一個統一的採集,只有經過規範化的採集方式,才能更有效地整合數據,並在服務端才能夠很容易地去查詢和排查。二 自建前端監控體系
做爲開發運營者來講,自建前端監控體系,須要清楚地去分析及追蹤,當線上的前端與客戶端發生問題時,如何快速定位到這些問題並解決
1 以宋小菜APP爲例,針對APP自建前端監控體系
其目前的系統架構以下
首先須要明確要採集哪些錯誤日誌數據,而後去相應的設計SDK
主要SDK設計以下RN SDK
微信小程序 SDK 對Page和Component兩個方法進行全局代理,這樣就不必在每次初始化小程序頁面時都要埋點在收集到的錯誤log裏使用kafka進行轉發
在日誌處理時,能夠採用一些策略
- 在向ES寫入JSON時,因爲數據量大,能夠按時或按天創建索引,從而不會查詢的時候特別慢
- 要創建一個統一的索引模板,對於索引的保存的數據類型要統一,不然會形成數據保存失敗
- 因爲上報的類型涉及到了多端,並且又包括自定義的上報內容,因此設計的上報的規範也不能太死。哪些字段變化哪些字段不變須要根據系統衡量
- 有一些字段是某些場景下是沒有必要創建索引的,不然會形成字段爆炸,那麼就能夠以String類型存儲下來
在報警監控系統的設計上,咱們能夠在監控後臺上建立報警任務,而後報警任務經過kafka推送到任務管理中,任務管理器根據不一樣的任務分發到任務執行器中
在收集到的錯誤信息上,都通過TraceKit作一個標準化,以後根據錯誤類型去作一個歸類,以下面這些特徵。根據這些特徵,來判斷信息是否爲重複的問題
至於在監控系統中選擇kafka而不是RPC等通訊的緣由以下: 最後,咱們能夠手動建立一些報警任務,好比針對某一個錯誤,規定是否當某一個規則知足時才上報以及監控的頻率等 針對數據流這裏不做過多介紹,能夠參考該分享者發的連接 60 天急速自研-搭建前端埋點監控系統大浪子2 以貝貝自研SDK爲例,對數據進行蒐集與清洗
在監控平臺上,貝貝選擇的是自研SDK,緣由是端平臺多、項目多,第三方須要去考慮成本,另外在擴展性、支持的平臺方面等,在目前的監控方案如Sentry、FundeBug、Bugly,也存在受限。
其總體流程爲經過SDK進行上報給ES,在調度中心進行任務清洗,再將信息存儲在MySQL中。最後經過Node.js爲前端可視化提供接口數據蒐集與上報
在前端,能夠經過上報上來的錯誤堆棧去分析應用出現的錯誤緣由,方便排查問題
上報方式SDK如何設計?
對於上報方式,能夠分爲自動上報(左)和手動上報(右)
在錯誤捕獲機制上,能夠分爲以下幾種:- window.onerror:運⾏時錯誤捕獲
- window.addEventListener(‘unhandledrejection’):promise 沒有 catch 錯誤
- try/catch 處理跨域腳本錯誤
- 其餘技術棧中(Vue、React)的錯誤捕獲
例如在Vue中,咱們能夠劫持它的errorHandler,而後在發生錯誤的時候上報,以後再去執行剩下的操做
在React中,能夠經過監聽componentDidCatch,將錯誤捕獲上報SDK又如何去作信息收集?
針對用戶行爲,經過全局監聽事件,從而獲取dom名稱、行爲棧等,當頁面發生錯誤時,將行爲和錯誤一塊兒上報 針對發送行爲,經過監聽XMLHttpRequest對象的回調函數 針對頁面跳轉,如前進、後退,經過監聽window.onpopstate方法 針對控制檯打印,能夠重寫其info、warn、error方法SDK如何進行數據上報?
使用經過GET方法發送一個1*1的GIF圖片及錯誤信息進行上報
這裏爲何要用1 * 1的GIF圖片?數據清洗與壓縮:
SDK獲取到的數據量大、沒有分類聚合、也沒有過濾,因此須要去進行一個數據清洗
首先在存儲方案上,選擇MySQL做爲永久存儲,選擇ES做爲臨時存儲
咱們須要通過從ES保存的數據中獲取數據->數據預處理->數據聚合這幾個階段,針對一樣的錯誤,只處理前面的部分對於收集到的數據設置閾值,即規定:
每分鐘數據獲取上限 10000 條,超過就採樣⼊庫。同類型錯誤數量⼤於 200 條,只統計數量
同時,因爲ES返回的是String流格式,須要使用JSON.parse()解析出來。 最後將下面的數據去作修正如去掉轉義符,忽略非法數據等。最終存到MySQL中。
針對一些相同類型的錯誤,須要進行數據聚合以起到壓縮目的在聚合的維度上,能夠分爲業務名、數據類型、錯誤信息 按照這樣的3個維度,作成MD5以用於判斷後面發生的錯誤是否爲相同的錯誤
對於相同的錯誤,統計量就少了不少,同時能夠記錄錯誤的次數 最後,針對監控系統中的數據清洗任務,咱們也能夠單獨拿出來作一個監控數據告警
當監控條件知足時,監控平臺會將錯誤發送給相應的開發者
至此就完成了Web端的監控。其餘平臺則只需以統一的格式上傳,後面的分析、清洗等均可以拿來複用。好比對於Android來講,當錯誤發生時,先存儲到本地的數據庫,而後進行嘗試地上報。若是上報成功,就將本地數據刪除,不然待下次APP啓動的時候再上報
3 基於錯誤日誌進行進一步的優化
在系統中,須要對數據日誌清洗、輔助分析能力、用戶界面展現、錯誤告警追蹤能力進行進一步優化
在錯誤聚合中可分爲通用優化和專用優化
舉個例子,下面是android端收集到的其錯誤名稱、錯誤描述、錯誤堆棧若是本是同一個錯誤,卻由於一些緣由如發生錯誤的視圖信息(紅色部分)致使描述不一樣,就能夠只把相同的部分,錯誤名和錯誤堆棧作一個散列
另外,可能由於系統的不一樣,錯誤堆棧可能調用鏈路同樣,但發生的位置有些差異這時能夠經過正則去掉系統類對應的行號去掉,再去散列
還可能因APP版本等問題,致使堆棧鏈路也不一樣但實質上也爲同一個錯誤,則只需抽取業務類和部分系統類堆棧,再去散列,而不是所有錯誤鏈路 對於OOM,由於致使的緣由五花八門,堆棧意義較小,更多地是去看設備信息、頁面信息等其餘維度去查看好比在前端上,能夠分析前端的行爲鏈路
在客戶端上,用戶產生的行爲日誌包括網絡日誌,經過鏈路ID進行關聯起來監控系統最終還要造成一個錯誤閉環,當發生錯誤時,及時交付給相應開發人員,版本成功修復之後再對線上監控進行一個更新
好比看版本變動後是否問題改善,或是因版本的問題而產生的異常 告警要監控時效性和有效性在監控的篩選時間中,還要注意客戶端是先將錯誤保存到本地,以後會嘗試性地去上報錯誤。端側會累積錯誤並存在延遲,因此服務器接受到的錯誤極可能並非最新的錯誤。
因此對於數據的篩選與告警閾值的設定,就能夠有下面這兩種策略。
若是按服務端時間來進行篩選,就能夠定義一個小時內發生的錯誤爲最近的錯誤。若是按客戶端時間,則看在這一個小時內,哪些錯誤在一個小時內,其記錄的錯誤裏間隔一分鐘的時間的錯誤數量超過了閾值。
4 如何基於堆棧映射去定位問題?
前端問題的定位難在什麼地⽅?
前端的日誌不像服務端,它是發生在端側的,因此只能依賴於上報,但上報的話又不可能獲取到全部的信息,可能會缺失上下文,另外前端代碼會進行混淆,堆棧沒法直接使用。
異常定位實踐:能夠在服務端將堆棧作個SourceMap映射到源碼上
但會有一些問題,好比可能由於依賴的包的版本變化,致使線上映射後和實際生產環境的代碼不對應。SourceMap映射也相對較慢,等映射完再去排查可能浪費了不少時間並且映射時會佔用很大內存
給出的解決方案是異步生成SourceMap。首先鎖定依賴,避免後面因版本問題致使堆棧對不上,以後將SourceMap映射和正常的版本構建分離開,這樣就不會因SourceMap的佔用內存過大致使影響正常版本的上線
前端也不能全堆棧上報,不然會帶來一些問題 爲了減小堆棧上報,須要判斷重複堆棧。那麼怎麼判斷重複堆棧? 客戶端拿到這個堆棧ID後,最簡單的方式是服務端提供接口進行查詢。但當堆棧量級巨大時,爲了提升查詢性能。能夠先將哈希拼接到url上去CDN看是否有資源,若是沒有上報過確定返回404,而後將堆棧和哈希上報到服務端中,服務端再向CDN發一個空文件。後面再判斷時發現已經有過了就再也不上報了。 前端監控自己還有好多路要走,好比對於一些不是很嚴重的錯誤就儘可能少報,不要不管什麼信息都上報等等三 監控系統在實際應用中還存在的問題
1.有些異常是因爲手機廠商、第三方注入等致使的,並非實際業務引發的
2.對於客戶端,會由於版本的迭代不一樣,客戶端版本不統一,因此監控日誌就須要更多維度 3.另外對於多個應用,更須要去篩選過濾。同一個應用可能以前已經解決了,但客戶端未更新版本,則無需關注 釘釘經過日誌聚合、日誌過濾、日誌分組、日誌報警、計算規則這一系列流程對日誌流處理,經過白名單、黑名單肯定報上來的日誌是有效的日誌 另外採用了日誌雙寫同時進行存儲和運算,使得實時能力增強 這是釘釘的監控架構,能夠參考 談阿里核心業務監控平臺 SunFire 的技術架構四 感觸
從會議中瞭解到了前端搞監控的巨大意義和相關技術點,使用監控系統從而更好地提高用戶體驗和產品開發以及問題排查,這些都是本身以前從未接觸過的。特別感謝前端早早聊大會的分享,收穫頗多!
五 關於前端早早聊大會
關於前端早早聊大會:前端早早聊大會目標成爲用得上、聽得懂、抄得走的技術大會,計劃 2020年辦>= 15期,由前端早早聊與掘金聯合舉辦,前端早早聊大會行程動態、錄播視頻/PPT/講稿資料下載請關注 「前端早早聊」 公衆號跟進。