摘要:說(shuō)起埋點(diǎn)又到了談起前端項(xiàng)目中數(shù)據(jù)收集與監(jiān)控,那么今天來(lái)簡(jiǎn)單的聊下前端報(bào)錯(cuò)監(jiān)控的埋點(diǎn)。錯(cuò)誤監(jiān)控的錯(cuò)誤監(jiān)控主要是為了發(fā)現(xiàn)服務(wù)接口返回值的問(wèn)題。如果為,則偵聽(tīng)器只在目標(biāo)或冒泡階段處理事件。
說(shuō)起埋點(diǎn)又到了談起前端項(xiàng)目中數(shù)據(jù)收集與監(jiān)控,那么今天來(lái)簡(jiǎn)單的聊下前端報(bào)錯(cuò)監(jiān)控的埋點(diǎn)。
首先先安利下自己做的報(bào)錯(cuò)監(jiān)控的項(xiàng)目 FE-Monitor 歡迎 issue 和 star 。
首先我們可以看下前端做報(bào)錯(cuò)監(jiān)控的意義在哪里:
幫助灰度測(cè)試發(fā)現(xiàn)問(wèn)題
收集線上錯(cuò)誤日志
幫助優(yōu)化產(chǎn)品穩(wěn)定性
收集錯(cuò)誤數(shù)據(jù)用于分析
監(jiān)控第三方資源/CDN 穩(wěn)定性
總體來(lái)說(shuō)前端監(jiān)控的主要目的都是為了獲取用戶(hù)行為以及跟蹤產(chǎn)品在用戶(hù)端的使用情況,并以監(jiān)控?cái)?shù)據(jù)為基礎(chǔ),指明產(chǎn)品優(yōu)化方向。
常見(jiàn)監(jiān)控方式try { test code // throw error } catch(e){ console.log(e); }
上面的代碼在項(xiàng)目中很常見(jiàn),一般用來(lái)捕獲某一段可能代碼拋出的錯(cuò)誤信息。并且在try catch 中的錯(cuò)誤并不會(huì)阻塞整個(gè)頁(yè)面,即使發(fā)生錯(cuò)誤,頁(yè)面也可以繼續(xù)執(zhí)行。
當(dāng)然,我們不太可能對(duì)這個(gè)項(xiàng)目中的每一段代碼都添加 try catch,這樣不僅不利于線上定位問(wèn)題產(chǎn)生的原因,也會(huì)讓代碼難以維護(hù),目前主流的就是在項(xiàng)目中獨(dú)立引入一個(gè)報(bào)錯(cuò)監(jiān)控的 JS 來(lái)多帶帶的完成對(duì)整個(gè)項(xiàng)目的監(jiān)控。
比如 FE-Monitor 就提供開(kāi)源的項(xiàng)目報(bào)錯(cuò)監(jiān)控的能力,只需要將 SDK 引入自己的項(xiàng)目中,即可監(jiān)控整個(gè)項(xiàng)目的js執(zhí)行報(bào)錯(cuò),資源加載異常,ajax錯(cuò)誤等信息了。
ajax 錯(cuò)誤監(jiān)控ajax 的錯(cuò)誤監(jiān)控主要是為了發(fā)現(xiàn)服務(wù)接口返回值的問(wèn)題。
看了一些產(chǎn)品的實(shí)現(xiàn)都是對(duì) window 下的 XMLHttpRequest 重寫(xiě),但是這樣直接重寫(xiě)不僅會(huì)造成調(diào)用鏈的修改也會(huì)讓宿主頁(yè)面上的多個(gè) ajax 庫(kù)產(chǎn)生沖突,如使用了 jquery 的話(huà) jquery 中是直接使用 XMLHttpRequest 對(duì)象的。如果修改了全局的對(duì)象中的屬性可能會(huì)造成以外的影響。
用了一種特殊的方式去實(shí)現(xiàn)對(duì) XMLHttpRequest 對(duì)象的監(jiān)聽(tīng)。
_initListenAjax: function () { let self = this; function ajaxEventTrigger(event) { var ajaxEvent = new CustomEvent(event, { detail: this }); window.dispatchEvent(ajaxEvent); } var oldXHR = window.XMLHttpRequest; function newXHR() { var realXHR = new oldXHR(); realXHR.addEventListener("load", function ($event) { ajaxEventTrigger.call(this, "ajaxLoad"); }, false); realXHR.addEventListener("timeout", function () { ajaxEventTrigger.call(this, "ajaxTimeout"); }, false); realXHR.addEventListener("readystatechange", function() { ajaxEventTrigger.call(this, "ajaxReadyStateChange"); }, false); return realXHR; } window.XMLHttpRequest = newXHR; self._startLintenAjax(); }
這樣做不僅可以一經(jīng)調(diào)用就監(jiān)控到頁(yè)面的錯(cuò)誤,不會(huì)出現(xiàn)重寫(xiě) window.onerror 的時(shí)候第一次錯(cuò)誤監(jiān)控不到的情況還需要重寫(xiě) console.error 函數(shù)才可以監(jiān)聽(tīng)到。
error錯(cuò)誤監(jiān)控錯(cuò)誤監(jiān)控中對(duì) error 事件的監(jiān)控是最重要的,監(jiān)聽(tīng) error 的事件主要是為了發(fā)現(xiàn) js 執(zhí)行中拋錯(cuò)。
window.addEventListener("error", function(err) { getError(err, self._config); }, true);
監(jiān)控 error 報(bào)錯(cuò)的情況中,最 error 的處理中要判斷是否是我們?cè)O(shè)置的埋點(diǎn)接口的 URL 所拋錯(cuò)的。主要是為了避免在埋點(diǎn)服務(wù)宕機(jī)的情況下出現(xiàn)重復(fù)請(qǐng)求上報(bào),造成頁(yè)面卡死的情況。
監(jiān)控資源加載異常頁(yè)面上有很多的外部的資源,一般來(lái)說(shuō)對(duì)資源的加載的監(jiān)控是在資源標(biāo)簽添加 onerror 的方法來(lái)監(jiān)聽(tīng)加載錯(cuò)誤信息。
支持onload的標(biāo)簽:, ,