JSTracker:前端异常数据采集
JSTracker - 淘寶前端監控平臺
基本上服務器端的代碼都是處于 7x24 小時的實時監控狀態的,一旦有任何異常對應的開發同學就馬上收到報警,并且第一時間處理。 但是對于前端來說,往往是實際用戶那里的腳本報錯后才知道頁面出現異常,這時候已經是故障了。
為了讓前端也能和后端一樣,需要將線上的 JavaScript 代碼監控起來,當用戶端瀏覽器出現異前端第一時間被通知到。于是便有了淘寶前端的監控平臺:JSTracker。
采集哪些數據
在解決怎么采集之前,還需要解決采集哪些數據,哪些數據是有用的?
主要原則就是避開用戶敏感字段,采集瀏覽器版本、操作系統版本、報錯的 msg 信息等。
JavaScript 異常的時候捕獲異常
主動捕獲異常方案主要是 onError 和 addEventListener,
onError 在 IE6 開始就支持了,所以 JSTracker 的主動采集是使用的 onError。
onError 可以采集到 file、line、col 等信息,但是實際情況中卻大部分收集到的是 script error。
原因是瀏覽器的同源性策略(CORS),在高級瀏覽器中如果瀏覽器捕獲到了錯誤信息,如果 JS 文件所在的域名(如:g.alicdn.com)和當前的頁面地址(如:www.taobao.com)是跨域的,那么瀏覽器會把?onError 中的 msg 替換為 script error,其余字段也會做替換。
webkit 的源代碼:
Script error 這個問題也是目前大家最詬病的一個問題:當報警發生之后,我們只知道有問題,但是很難知道哪里出了問題。
其實是有解決方案的:
-
首先 JavaScript 請求的 http 返回頭上需要加上一個 Access-Control-Allow-Origin 頭。
-
在引入 JavaScript 文件的時候需要在 script 標簽上添加 crossorigin 屬性,在加這個屬性前請一定確保上一條已經完成,否則 JavaScript 文件不會執行!!!。
| ? | <script src="http://somremotesite.example/script.js" crossorigin></script> |
這個解決方式看起來完美,但是要做的改造實在是太多了,目前還是主動上報為主。
主動上報異常
onError 的方案會采集到全面的瀏覽器報錯,但是太全了,出了剛才的 script error 問題,還會采集到。
- ISP 在頁面中注入的腳本報錯(我們的前端質量很高的,但是被這些牛氓們一弄,啥質量都沒了)。
- 插件問題(亂七八糟的插件也是一樣的令人討厭,注入奇怪的東西在頁面中,引起報錯)。
為了讓采集到的錯誤更有價值,需要暴露接口給讓前端門自己在代碼中上報異常(作為一名合格的代碼工程師,一定要有拋異常的習慣呢)。
現在我們提供了自定義上報的接口,沒錯就是這么簡單,你不用擔心 JSTracker 腳本有沒有加載,只要在你的代碼中直接用就行了。
| ? | window.JSTracker2 = window.JSTracker2 || []; try{//your code }catch(e){JSTracker2.push({msg: "xx_api_failed"}); } |
自己上報的錯誤對于定位也是很容易的:
一些細節問題
在代碼中使用 try catch 是否對性能有影響
try catch 對性能的影響微乎其微,但是一些用法會讓性能受很大的影響, 參考這個實驗:http://taobaofed.org/blog/2015/10/28/try-catch-runing-problem/
總結下來就是:在 try 語句塊中不要定義太多的變量,最好是只寫一個函數調用,避免 try 運行中變量拷貝造成的性能損耗。類似的不只是 try,定義 function 也是一樣的。
采集到的數據如何發出去
JSTracker 的數據發送了非常大,這塊都交給后端幫我們處理,采集部分只需要關注準確無誤的把數據發送出去。
最初的簡單的發送方案,直接用 GET 請求,將參數拼接在 URL 后面:
| ? | var url = 'xxx'; new Image().src = url; |
后來發現這樣發送有一定概率丟失數據,當瀏覽器回收內存的時候這個請求是發不出去的,所以要將這個變量 hold住:
| ? | var win = window; var n = 'jsFeImage_' + _make_rnd(),img = win[n] = new Image(); img.onload = img.onerror = function () {win[n] = null; }; img.src = src; |
隨機數造成的數據丟失
我們為了防止緩存,經常會用毫秒的時間作為隨機數(如:+new Date()),但是在極端情況下可能1ms就會發出兩條 log,這樣第二條 log 就會丟失。
| ? | var _make_rnd = function(){return (+new Date()) + '.r' + Math.floor(Math.random() * 1000);}; |
360瀏覽器識別
為了能更好的統計這個瀏覽器,需要識別360SE、360EE。眾所周知 3Q 大戰之后360的 UA 就和 Chrome 的一樣,所以我們要用一些特別的方法識別它們。目前為止能夠識別的方案,這個方案會隨時更新,適應360的變化。
| ? | var is360 = function(){try {if(/UBrowser/i.test(navigator.userAgent)){return '';}if (typeof window.scrollMaxX !== 'undefined') {return '';}var _track = 'track' in document.createElement('track');var webstoreKeysLength = window.chrome && window.chrome.webstore ? Object.keys(window.chrome.webstore).length : 0;if (window.clientInformation && window.clientInformation.languages && window.clientInformation.languages.length > 2) {return '';}if (_track) {return webstoreKeysLength > 1 ? ' QIHU 360 EE' : ' QIHU 360 SE';}return '';}catch(e){return '';} }(); |
總結
以上是生活随笔為你收集整理的JSTracker:前端异常数据采集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Sentry异常监控方案部署-前端攻略
- 下一篇: MQ中间件