应用实时监控 ARMS 上线用户行为回溯功能
隨著前端技術日新月異迅猛發展,為了實現更好的前端性能,最大程度提高用戶體驗,支持單頁應用的框架逐漸占領市場,如眾所周知的React,Vue等等。但是在單頁應用的趨勢下,快速定位并解決JS錯誤卻成為一大難題。在當下的互聯網行業,對前端性能要求越來越高,前端性能監控的產品層出不窮,javascript錯誤診斷更是其中舉足輕重的一個環節。幫助開發者排查線上bug,實現快速定位問題,高效解決問題,是我們努力的方向。
一、JS錯誤診斷
目前已經有了許多諸如Arms,Sentry等前端性能監控框架,都在一定程度上對JS錯誤診斷提供了相應的 支持,總體來說,大家的思路比較相似,可以總結為以下幾個步驟:
1. 統計JS錯誤
每當上線一個新的產品或新的業務功能,往往伴隨著一些不可避免的線上bug,這些bug發生的頻率有多高、發生在什么頁面、影響了多少用戶等等,對于判斷解決問題的優先級、幫助排查問題和優化性能來說是非常關鍵的。
圖1是Arms前端性能監控的JS錯誤診斷診斷頁面,可以清晰地看到錯誤發生的次數、影響用戶數以及錯誤分布情況等信息,開發者可以根據這些統計數據更好地決策問題的輕重緩急,使性能優化有條不紊進行。
?
圖1. JS錯誤總覽
2. 精準定位錯誤
前端報錯的原因有很多,網絡因素、瀏覽器兼容性、用戶操作邏輯、業務代碼本身的問題等等都可能導致故障發生,在JS錯誤統計中我們已經知道了錯誤發生的頁面,這在一定程度上縮小了排查范圍,但這樣還是不夠的,我們還想要知道更多錯誤詳情,比如:
1)現場信息
包括報錯的設備、操作系統、瀏覽器等等,這些信息無疑可以幫助開發者更好地復現問題,進而修復bug。
?
圖2. JS錯誤概要
2)代碼追蹤
利用error stack和source map來精準定位發生錯誤的代碼位置。
?
a. 上傳source map文件
b. 在代碼中定位錯誤
圖3. source map錯誤定位
3. 還原報錯現場
還原錯誤發生時用戶行為上下文是JS錯誤診斷的最后一步,也是最關鍵和最困難的一步。
假設以下場景:我們收到用戶反饋說點了某按鈕后沒有反應……
面對用戶反饋,我們不由得會想,沒反應是什么原因呢,是點擊事件的handler出錯了導致接口請求沒發出?還是接口掛了?或者是接口返回數據渲染失敗了?
類似以上的困惑應該很多開發者都會時常遇到,我們不可能去指揮用戶打開開發者工具再一步步debug給我們看,這就需要我們的前端監控平臺具備還原報錯現場的能力,幫助開發者了解錯誤發生時候的用戶行為上下文,進而可以預想一下剛才的場景——
根據用戶的uid等信息,我們可以回溯到該用戶報錯前后的一系列操作以及前端行為:
進入頁面->點擊按鈕->發出api請求成功-> js error……
于是我們可以知道報錯是發生在api請求成功后的數據處理環節,再依據步驟2中提供的錯誤詳情快速解決問題。
二、用戶行為回溯
已經有一些前端性能監控平臺接入了用戶行為監控,實現的方式也各有千秋,主要流程可以分為三個步驟:行為采集、行為上報、行為回溯。
1. 行為采集
1)哪些行為需要采集?
我們站在用戶的立場去考慮一個單頁應用的瀏覽周期內的可能流程:進入應用首頁——加載頁面內容——瀏覽頁面內容——用戶交互(鼠標交互/鍵盤交互等)——跳轉到新頁面……
要將用戶行為串聯成完整的行為鏈來為js error提供上下文,我們需要知道什么時間,什么位置,發生了什么事情。由此,以上用戶瀏覽過程中的所有的頁面行為(包括但不僅限于用戶交互)可以用以下幾類來大致概括:
Api請求,鼠標事件,鍵盤事件,路由跳轉,error 等。
2)如何采集?
在確定了哪些行為需要上報以后,我們再在來看如何完成行為打點。
在過往的時代,我們有傳統的手動埋點方法,它的缺點也是不言而喻的:手動埋點是容易混亂的,有時可能會出現錯埋、漏埋等情況,每每上線一個新功能,需要開發團隊和數據團隊進行埋點溝通,徒增了時間和人力成本;其次時常因為產品排期緊張,功能急于上線,就不得不先砍掉了埋點的需求,在后續的版本更新中再補上,這使得新上線的功能得不到驗證,而新上線的功能對業務和產品性能的影響都很關鍵。
現如今,一個好的前端監控產品需要實現“無埋點”監控,充當一雙眼睛,時時刻刻監控著產品的運作情況,全量采集頁面事件和用戶行為,為業務分析和錯誤診斷都提供充足的信息。
?
圖4. 用戶行為采集流程圖
以上流程圖為Arms做行為采集的大致步驟,首先需要在正常的html頁面中插入一小段js代碼,即引入我們具有行為日志采集功能的SDK,如下代碼所示,通過createElement(“script”)在Dom節點添加script的元素,并將SDK的js文件引入進來,用于收集用戶行為,并在適當的時候上報到后端,具體方法如下代碼所示,其中bl.js為SDK文件。
<script> !(function(c,b,d,a){c[a]||(c[a]={});c[a].config={pid:"xxxxxxx",appType:"web",imgUrl:"https://arms-retcode.aliyuncs.com/r.png?"}; with(b)with(body)with(insertBefore(createElement("script"),firstChild))setAttribute("crossorigin","",src=d) })(window,document,"https://retcode.alicdn.com/retcode/bl.js","__bl"); </script>3)SDK中行為采集的實現
- API行為采集
重寫原生XMLHttpRequest或fetch方法,采集必要的API信息(如url,狀態碼,狀態message等)。
- 控制臺行為采集
重寫console的常見控制臺輸出方法,比如: log,warning,error等。
注意,通過重寫 console 對象監控瀏覽器控制臺的打印信息,這樣會導致在控制臺下打印的日志無法正確看到原代碼文件中的位置,console的位置會定位到SDK的代碼中,可以通過配置瀏覽器 Blackboxing來解決。
?
圖5. console定位在SDK代碼中
- 用戶交互行為采集(鼠標鍵盤事件等):?
可以在頂層的document上全面監聽各類用戶交互事件,如click,keypress,mousemove,scroll等等。但是這種方法也有一個明顯的缺陷,假設用戶監聽了某個dom上的click事件,并且設置了event.stopPropagation(),這種情況的點擊事件是無法被document監聽到的,而往往這類行為對于錯誤診斷和業務分析都尤為重要。解決方法是在addEventListener中埋入鉤子。
- 路由跳轉行為采集
路由跳轉無疑會觸發瀏覽器歷史記錄的改變,每當處于激活狀態的歷史記錄條目發生變化時,window的popstate事件會觸發,但是調用history.pushState()或者history.replaceState()不會觸發popstate事件。因此路由跳轉的監控可以分為兩個方面,一方面在window. onpopstate中埋入鉤子,另一方面在history.pushState和history.replaceState中埋入鉤子。
- js error
全局監聽js error:
監聽全局未處理的rejection:
window.addEventListener('unhandledrejection', function(event){...})2. 行為上報
SDK采集到用戶行為后,以一定的格式進行信息拼接,然后偽裝成圖片發送給后端。為什么要使用圖片來發送日志信息而不是直接使用ajax呢?這是因為SDK的script文件和后端分析的代碼可能不在相同的域內,而將image對象的src屬性指向后端腳本并攜帶參數,可以輕松實現跨域請求。不同平臺對于前端監控行為的類別都比較類似,但上報的方式還是不盡相同的,服務于不同的業務需求。以下是兩種比較典型的行為上報形式:
1)持續全量上報
圖6是截取的New relic的行為日志上報信息,為什么稱之為持續全量上報呢?“持續”是指它的行為日志是定時上報的,每隔幾秒便會上報一次,上報請求非常密集。“全量”則是指它采集的行為類型覆蓋面很廣,可以從上報的Request Payload中看到,它采集的不僅限于我們上面提到的一些主要的頁面行為,它幾乎覆蓋了所有的頁面事件,包括鼠標移動等等。而這種上報方式也是利弊參半:
優點:它可以更真實地還原用戶在整個頁面周期內的行為,保真度很高,對于還原現場來說是有一定優勢的。
缺陷:首先是無差別的行為采集,這顯然增大了行為日志的數據體量,在上報中對流量的消耗很大,日志存儲成本也很高,而這巨大的損耗所帶來的信息價值呢?幾乎大部分都是鼠標移動或者滑輪滾動的大量重復信息,無論是對業務分析還是錯誤診斷都沒有太大貢獻,甚至增加了分析問題的復雜性。
其次是行為日志的頻繁上報,這對業務方來說可能也是不太友好的,性能監控請求發的比本身的業務請求都多。
圖6. 行為日志全量上報
2)場景觸發上報
場景觸發上報即是指,當符合一定條件或者場景時才上報行為日志,對于JS錯誤診斷中的用戶行為回溯場景而言,當然就是錯誤觸發上報,當頁面監聽到error時,便把當前采集到的行為列表伴隨error詳情一并上報,作為錯誤診斷的輔助信息。
行為日志伴隨錯誤一起上報的方式需要維護一個行為隊列,隊列應設有最大長度,當捕獲到js error的時候,將行為隊列作為js錯誤日志的一個補充信息一起上報,圖7所示為sentry錯誤日志上報的request payload,其用戶行為隊列包含在錯誤日志的“breadcrumbs”字段中。
這種用戶行為伴隨錯誤上報的方式就相對輕量很多,首先錯誤和行為一起上報減少了請求數量;其次對用戶行為選擇性采集,避免了大量冗余信息對流量和存儲的消耗,就js錯誤診斷而言會使得錯誤現場變得更清晰,對分析錯誤有利。
當然這種行為上報的方式也是有不可忽視的問題,即行為和js error的強耦合,使得用戶行為信息失去了業務分析的擴展性,僅適用于JS錯誤診斷。
圖7. 行為日志breadcrumbs上報
三、用戶行為回溯在js錯誤診斷中的應用
圖8展示了Arms前端性能監控的JS錯誤診斷中用戶行為回溯的情況,在錯誤詳情中復原出錯現場,輔助排查。下圖展示了用戶在進行了“接口請求-控制臺輸出-點擊按鈕-控制臺輸出”的一系列行為后發生了JS錯誤,即可從按鈕的點擊事件的處理函數中進行錯誤排查。
?
圖8. Arms前端性能監控的用戶行為回溯
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的应用实时监控 ARMS 上线用户行为回溯功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 刚刚,阿里巴巴小程序生态联盟重磅启动
- 下一篇: 使用阿里云极速型NAS构建高可用的Git