JSTracker 之前端異常資料採集

發表於2015-11-12

JSTracker 之前端異常資料採集

JSTracker – 淘寶前端監控平臺

基本上伺服器端的程式碼都是處於 7×24 小時的實時監控狀態的,一旦有任何異常對應的開發同學就馬上收到報警,並且第一時間處理。 但是對於前端來說,往往是實際使用者那裡的指令碼報錯後才知道頁面出現異常,這時候已經是故障了。

為了讓前端也能和後端一樣,需要將線上的 JavaScript 程式碼監控起來,當使用者端瀏覽器出現異前端第一時間被通知到。於是便有了淘寶前端的監控平臺:JSTracker。

採集哪些資料

在解決怎麼採集之前,還需要解決採集哪些資料,哪些資料是有用的?

主要原則就是避開使用者敏感欄位,採集瀏覽器版本、作業系統版本、報錯的 msg 資訊等。

JavaScript 異常的時候捕獲異常

主動捕獲異常方案主要是 onError 和 addEventListener,
onError 在 IE6 開始就支援了,所以 JSTracker 的主動採集是使用的 onError。

onError 可以採集到 file、line、col 等資訊,但是實際情況中卻大部分收集到的是 script error。
收集到的 script error

原因是瀏覽器的同源性策略(CORS),在高階瀏覽器中如果瀏覽器捕獲到了錯誤資訊,如果 JS 檔案所在的域名(如:g.alicdn.com)和當前的頁面地址(如:www.taobao.com)是跨域的,那麼瀏覽器會把 onError 中的 msg 替換為 script error,其餘欄位也會做替換。

webkit 的原始碼:
webkit 的原始碼

Script error 這個問題也是目前大家最詬病的一個問題:當報警發生之後,我們只知道有問題,但是很難知道哪裡出了問題。

其實是有解決方案的:

  • 首先 JavaScript 請求的 http 返回頭上需要加上一個 Access-Control-Allow-Origin 頭。
    Access-Control-Allow-Origin 頭
  • 在引入 JavaScript 檔案的時候需要在 script 標籤上新增 crossorigin 屬性,在加這個屬性前請一定確保上一條已經完成,否則 JavaScript 檔案不會執行!!!。

這個解決方式看起來完美,但是要做的改造實在是太多了,目前還是主動上報為主。

主動上報異常

onError 的方案會採集到全面的瀏覽器報錯,但是太全了,出了剛才的 script error 問題,還會採集到。

  • ISP 在頁面中注入的指令碼報錯(我們的前端質量很高的,但是被這些牛氓們一弄,啥質量都沒了)。
  • 外掛問題(亂七八糟的外掛也是一樣的令人討厭,注入奇怪的東西在頁面中,引起報錯)。

為了讓採集到的錯誤更有價值,需要暴露介面給讓前端門自己在程式碼中上報異常(作為一名合格的程式碼工程師,一定要有拋異常的習慣呢)。

現在我們提供了自定義上報的介面,沒錯就是這麼簡單,你不用擔心 JSTracker 指令碼有沒有載入,只要在你的程式碼中直接用就行了。

自己上報的錯誤對於定位也是很容易的:

自己上報的錯誤

一些細節問題

在程式碼中使用 try catch 是否對效能有影響

try catch 對效能的影響微乎其微,但是一些用法會讓效能受很大的影響, 參考這個實驗:http://taobaofed.org/blog/2015/10/28/try-catch-runing-problem/

總結下來就是:在 try 語句塊中不要定義太多的變數,最好是隻寫一個函式呼叫,避免 try 執行中變數拷貝造成的效能損耗。類似的不只是 try,定義 function 也是一樣的。

採集到的資料如何發出去

JSTracker 的資料傳送了非常大,這塊都交給後端幫我們處理,採集部分只需要關注準確無誤的把資料傳送出去。

最初的簡單的傳送方案,直接用 GET 請求,將引數拼接在 URL 後面:

後來發現這樣傳送有一定概率丟失資料,當瀏覽器回收記憶體的時候這個請求是發不出去的,所以要將這個變數 hold住:

隨機數造成的資料丟失

我們為了防止快取,經常會用毫秒的時間作為隨機數(如:+new Date()),但是在極端情況下可能1ms就會發出兩條 log,這樣第二條 log 就會丟失。

360瀏覽器識別

為了能更好的統計這個瀏覽器,需要識別360SE、360EE。眾所周知 3Q 大戰之後360的 UA 就和 Chrome 的一樣,所以我們要用一些特別的方法識別它們。目前為止能夠識別的方案,這個方案會隨時更新,適應360的變化。

相關文章