本文出自 Tencent CDC(前端異常監(jiān)控解決方案研究)
前端監(jiān)控包括行為監(jiān)控椿胯、異常監(jiān)控皮仁、性能監(jiān)控等述么,本文主要討論異常監(jiān)控蝌数。對(duì)于前端而言,和后端處于同一個(gè)監(jiān)控系統(tǒng)中度秘,前端有自己的監(jiān)控方案顶伞,后端也有自己等監(jiān)控方案,但兩者并不分離剑梳,因?yàn)橐粋€(gè)用戶在操作應(yīng)用過(guò)程中如果出現(xiàn)異常唆貌,有可能是前端引起,也有可能是后端引起垢乙,需要有一個(gè)機(jī)制锨咙,將前后端串聯(lián)起來(lái),使監(jiān)控本身統(tǒng)一于監(jiān)控系統(tǒng)追逮。因此酪刀,即使只討論前端異常監(jiān)控粹舵,其實(shí)也不能?chē)?yán)格區(qū)分前后端界限,而要根據(jù)實(shí)際系統(tǒng)的設(shè)計(jì)骂倘,在最終的報(bào)表中體現(xiàn)出監(jiān)控對(duì)開(kāi)發(fā)和業(yè)務(wù)的幫助眼滤。
一般而言,一個(gè)監(jiān)控系統(tǒng)历涝,大致可以分為四個(gè)階段:日志采集柠偶、日志存儲(chǔ)、統(tǒng)計(jì)與分析睬关、報(bào)告和警告诱担。
采集階段:收集異常日志,先在本地做一定的處理电爹,采取一定的方案上報(bào)到服務(wù)器蔫仙。
存儲(chǔ)階段:后端接收前端上報(bào)的異常日志,經(jīng)過(guò)一定處理丐箩,按照一定的存儲(chǔ)方案存儲(chǔ)摇邦。
分析階段:分為機(jī)器自動(dòng)分析和人工分析。機(jī)器自動(dòng)分析屎勘,通過(guò)預(yù)設(shè)的條件和算法施籍,對(duì)存儲(chǔ)的日志信息進(jìn)行統(tǒng)計(jì)和篩選,發(fā)現(xiàn)問(wèn)題概漱,觸發(fā)報(bào)警丑慎。人工分析,通過(guò)提供一個(gè)可視化的數(shù)據(jù)面板瓤摧,讓系統(tǒng)用戶可以看到具體的日志數(shù)據(jù)竿裂,根據(jù)信息,發(fā)現(xiàn)異常問(wèn)題根源照弥。
報(bào)警階段:分為告警和預(yù)警腻异。告警按照一定的級(jí)別自動(dòng)報(bào)警,通過(guò)設(shè)定的渠道这揣,按照一定的觸發(fā)規(guī)則進(jìn)行悔常。預(yù)警則在異常發(fā)生前,提前預(yù)判给赞,給出警告机打。
1 前端異常
前端異常是指在用戶使用Web應(yīng)用時(shí)無(wú)法快速得到符合預(yù)期結(jié)果的情況,不同的異常帶來(lái)的后果程度不同塞俱,輕則引起用戶使用不悅姐帚,重則導(dǎo)致產(chǎn)品無(wú)法使用吏垮,使用戶喪失對(duì)產(chǎn)品的認(rèn)可障涯。
1.1 前端異常分類(lèi)
根據(jù)異常代碼的后果的程度罐旗,對(duì)前端異常的表現(xiàn)分為如下幾類(lèi)
a. 出錯(cuò)
界面呈現(xiàn)的內(nèi)容與用戶預(yù)期的內(nèi)容不符,例如點(diǎn)擊進(jìn)入非目標(biāo)界面唯蝶,數(shù)據(jù)不準(zhǔn)確九秀,出現(xiàn)的錯(cuò)誤提示不可理解,界面錯(cuò)位粘我,提交后跳轉(zhuǎn)到錯(cuò)誤界面等情況鼓蜒。這類(lèi)異常出現(xiàn)時(shí),雖然產(chǎn)品本身功能還能正常使用征字,但用戶無(wú)法達(dá)成自己目標(biāo)都弹。
b. 呆滯
界面出現(xiàn)操作后沒(méi)有反應(yīng)的現(xiàn)象,例如點(diǎn)擊按鈕無(wú)法提交匙姜,提示成功后無(wú)法繼續(xù)操作畅厢。這類(lèi)異常出現(xiàn)時(shí),產(chǎn)品已經(jīng)存在界面級(jí)局部不可用現(xiàn)象氮昧。
c. 損壞
界面出現(xiàn)無(wú)法實(shí)現(xiàn)操作目的的現(xiàn)象框杜,例如點(diǎn)擊無(wú)法進(jìn)入目標(biāo)界面,點(diǎn)擊無(wú)法查看詳情內(nèi)容等袖肥。這類(lèi)異常出現(xiàn)時(shí)咪辱,應(yīng)用部分功能無(wú)法被正常使用。
d. 假死
界面出現(xiàn)卡頓椎组,無(wú)法對(duì)任何功能進(jìn)行使用的現(xiàn)象油狂。例如用戶無(wú)法登陸導(dǎo)致無(wú)法使用應(yīng)用內(nèi)功能,由于某個(gè)遮罩層阻擋且不可關(guān)閉導(dǎo)致無(wú)法進(jìn)行任何后續(xù)操作寸癌。這類(lèi)異常出現(xiàn)時(shí)选调,用戶很可能殺死應(yīng)用。
e. 崩潰
應(yīng)用出現(xiàn)經(jīng)常性自動(dòng)退出或無(wú)法操作的現(xiàn)象灵份。例如間歇性crash仁堪,網(wǎng)頁(yè)無(wú)法正常加載或加載后無(wú)法進(jìn)行任何操作。這類(lèi)異常持續(xù)出現(xiàn)填渠,將直接導(dǎo)致用戶流失弦聂,影響產(chǎn)品生命力。
1.2 異常錯(cuò)誤原因分類(lèi)
前端產(chǎn)生異常的原因主要分5類(lèi):
原因 | 案例 | 頻率 |
---|---|---|
邏輯錯(cuò)誤 | 1) 業(yè)務(wù)邏輯判斷條件錯(cuò)誤 2) 事件綁定順序錯(cuò)誤3) 調(diào)用棧時(shí)序錯(cuò)誤4) 錯(cuò)誤的操作js對(duì)象 | 經(jīng)常 |
數(shù)據(jù)類(lèi)型錯(cuò)誤 | 1) 將null視作對(duì)象讀取property 2) 將undefined視作數(shù)組進(jìn)行遍歷 3) 將字符串形式的數(shù)字直接用于加運(yùn)算 4) 函數(shù)參數(shù)未傳 | 經(jīng)常 |
語(yǔ)法句法錯(cuò)誤 | 較少 | |
網(wǎng)絡(luò)錯(cuò)誤 | 1) 慢 2) 服務(wù)端未返回?cái)?shù)據(jù)但仍200氛什,前端按正常進(jìn)行數(shù)據(jù)遍歷 3) 提交數(shù)據(jù)時(shí)網(wǎng)絡(luò)中斷 4) 服務(wù)端500錯(cuò)誤時(shí)前端未做任何錯(cuò)誤處理 | 偶爾 |
系統(tǒng)錯(cuò)誤 | 1) 內(nèi)存不夠用 2) 磁盤(pán)塞滿3) 殼不支持API4) 不兼容 | 較少 |
2 異常采集
2.1 采集內(nèi)容
當(dāng)異常出現(xiàn)的時(shí)候莺葫,我們需要知道異常的具體信息,根據(jù)異常的具體信息來(lái)決定采用什么樣的解決方案枪眉。在采集異常信息時(shí)捺檬,可以遵循4W原則:
WHO did WHAT and get WHICH exception in WHICH environment?
a. 用戶信息
出現(xiàn)異常時(shí)該用戶的信息,例如該用戶在當(dāng)前時(shí)刻的狀態(tài)贸铜、權(quán)限等堡纬,以及需要區(qū)分用戶可多終端登錄時(shí)聂受,異常對(duì)應(yīng)的是哪一個(gè)終端。
b. 行為信息
用戶進(jìn)行什么操作時(shí)產(chǎn)生了異常:所在的界面路徑烤镐;執(zhí)行了什么操作蛋济;操作時(shí)使用了哪些數(shù)據(jù);當(dāng)時(shí)的API吐了什么數(shù)據(jù)給客戶端炮叶;如果是提交操作碗旅,提交了什么數(shù)據(jù);上一個(gè)路徑镜悉;上一個(gè)行為日志記錄ID等祟辟。
c. 異常信息
產(chǎn)生異常的代碼信息:用戶操作的DOM元素節(jié)點(diǎn);異常級(jí)別侣肄;異常類(lèi)型川尖;異常描述;代碼stack信息等茫孔。
d. 環(huán)境信息
網(wǎng)絡(luò)環(huán)境叮喳;設(shè)備型號(hào)和標(biāo)識(shí)碼;操作系統(tǒng)版本缰贝;客戶端版本馍悟;API接口版本等。
字段 | 類(lèi)型 | 解釋 |
---|---|---|
requestId | String | 一個(gè)界面產(chǎn)生一個(gè)requestId |
traceId | String | 一個(gè)階段產(chǎn)生一個(gè)traceId剩晴,用于追蹤和一個(gè)異常相關(guān)的所有日志記錄 |
hash | String | 這條log的唯一標(biāo)識(shí)碼锣咒,相當(dāng)于logId,但它是根據(jù)當(dāng)前日志記錄的具體內(nèi)容而生成的 |
time | Number | 當(dāng)前日志產(chǎn)生的時(shí)間(保存時(shí)刻) |
userId | String | |
userStatus | Number | 當(dāng)時(shí)赞弥,用戶狀態(tài)信息(是否可用/禁用) |
userRoles | Array | 當(dāng)時(shí)毅整,前用戶的角色列表 |
userGroups | Array | 當(dāng)時(shí),用戶當(dāng)前所在組绽左,組別權(quán)限可能影響結(jié)果 |
userLicenses | Array | 當(dāng)時(shí)悼嫉,許可證,可能過(guò)期 |
path | String | 所在路徑拼窥,URL |
action | String | 進(jìn)行了什么操作 |
referer | String | 上一個(gè)路徑戏蔑,來(lái)源URL |
prevAction | String | 上一個(gè)操作 |
data | Object | 當(dāng)前界面的state、data |
dataSources | Array<Object> | 上游api給了什么數(shù)據(jù) |
dataSend | Object | 提交了什么數(shù)據(jù) |
targetElement | HTMLElement | 用戶操作的DOM元素 |
targetDOMPath | Array<HTMLElement> | 該DOM元素的節(jié)點(diǎn)路徑 |
targetCSS | Object | 該元素的自定義樣式表 |
targetAttrs | Object | 該元素當(dāng)前的屬性及值 |
errorType | String | 錯(cuò)誤類(lèi)型 |
errorLevel | String | 異常級(jí)別 |
errorStack | String | 錯(cuò)誤stack信息 |
errorFilename | String | 出錯(cuò)文件 |
errorLineNo | Number | 出錯(cuò)行 |
errorColNo | Number | 出錯(cuò)列位置 |
errorMessage | String | 錯(cuò)誤描述(開(kāi)發(fā)者定義) |
errorTimeStamp | Number | 時(shí)間戳 |
eventType | String | 事件類(lèi)型 |
pageX | Number | 事件x軸坐標(biāo) |
pageY | Number | 事件y軸坐標(biāo) |
screenX | Number | 事件x軸坐標(biāo) |
screenY | Number | 事件y軸坐標(biāo) |
pageW | Number | 頁(yè)面寬度 |
pageH | Number | 頁(yè)面高度 |
screenW | Number | 屏幕寬度 |
screenH | Number | 屏幕高度 |
eventKey | String | 觸發(fā)事件的鍵 |
network | String | 網(wǎng)絡(luò)環(huán)境描述 |
userAgent | String | 客戶端描述 |
device | String | 設(shè)備描述 |
system | String | 操作系統(tǒng)描述 |
appVersion | String | 應(yīng)用版本 |
apiVersion | String | 接口版本 |
這是一份非常龐大的日志字段表鲁纠,它幾乎囊括了一個(gè)異常發(fā)生時(shí)总棵,能夠?qū)Ξ惓V茉猸h(huán)境進(jìn)行詳細(xì)描述的所有信息。不同情況下改含,這些字段并不一定都會(huì)收集情龄,由于我們會(huì)采用文檔數(shù)據(jù)庫(kù)存儲(chǔ)日志,因此,并不影響它的實(shí)際存儲(chǔ)結(jié)果骤视。
2.2 異常捕獲
前端捕獲異常分為全局捕獲和單點(diǎn)捕獲鞍爱。全局捕獲代碼集中,易于管理尚胞;單點(diǎn)捕獲作為補(bǔ)充,對(duì)某些特殊情況進(jìn)行捕獲帜慢,但分散笼裳,不利于管理。
a粱玲、全局捕獲
通過(guò)全局的接口躬柬,將捕獲代碼集中寫(xiě)在一個(gè)地方,可以利用的接口有:
- window.addEventListener(‘error’) / window.addEventListener(“unhandledrejection”) / document.addEventListener(‘click’) 等
- 框架級(jí)別的全局監(jiān)聽(tīng)抽减,例如aixos中使用interceptor進(jìn)行攔截允青,vue、react都有自己的錯(cuò)誤采集接口
- 通過(guò)對(duì)全局函數(shù)進(jìn)行封裝包裹卵沉,實(shí)現(xiàn)在在調(diào)用該函數(shù)時(shí)自動(dòng)捕獲異常
- 對(duì)實(shí)例方法重寫(xiě)(Patch)颠锉,在原有功能基礎(chǔ)上包裹一層,例如對(duì)console.error進(jìn)行重寫(xiě)史汗,在使用方法不變的情況下也可以異常捕獲
b琼掠、單點(diǎn)捕獲
在業(yè)務(wù)代碼中對(duì)單個(gè)代碼塊進(jìn)行包裹,或在邏輯流程中打點(diǎn)停撞,實(shí)現(xiàn)有針對(duì)性的異常捕獲:
- try…catch
- 專(zhuān)門(mén)寫(xiě)一個(gè)函數(shù)來(lái)收集異常信息瓷蛙,在異常發(fā)生時(shí),調(diào)用該函數(shù)
- 專(zhuān)門(mén)寫(xiě)一個(gè)函數(shù)來(lái)包裹其他函數(shù)戈毒,得到一個(gè)新函數(shù)艰猬,該新函數(shù)運(yùn)行結(jié)果和原函數(shù)一模一樣,只是在發(fā)生異常時(shí)可以捕獲異常
2.3 跨域腳本異常
由于瀏覽器安全策略限制埋市,跨域腳本報(bào)錯(cuò)時(shí)冠桃,無(wú)法直接獲取錯(cuò)誤的詳細(xì)信息,只能得到一個(gè)Script Error道宅。例如腊满,我們會(huì)引入第三方依賴(lài),或者將自己的腳本放在CDN時(shí)培己。
解決Script Error的方法:
方案一:
- 將js內(nèi)聯(lián)到HTML中
- 將js文件與HTML放在同域下
方案二:
- 為頁(yè)面上script標(biāo)簽添加crossorigin屬性
- 被引入腳本所在服務(wù)端響應(yīng)頭中碳蛋,增加 Access-Control-Allow-Origin 來(lái)支持跨域資源共享
2.4 異常錄制
對(duì)于一個(gè)異常,僅僅擁有該異常的信息還不足以完全抓住問(wèn)題的本質(zhì)省咨,因?yàn)楫惓0l(fā)生的位置肃弟,并不一定是異常根源所在的位置。我們需要對(duì)異常現(xiàn)場(chǎng)進(jìn)行還原笤受,才能復(fù)原問(wèn)題全貌穷缤,甚至避免類(lèi)似問(wèn)題在其他界面中發(fā)生。這里需要引進(jìn)一個(gè)概念箩兽,就是“異常錄制”津肛。錄制通過(guò)“時(shí)間”“空間”兩個(gè)維度記錄異常發(fā)生前到發(fā)生的整個(gè)過(guò)程,對(duì)于找到異常根源更有幫助汗贫。
上圖表示身坐,當(dāng)異常發(fā)生時(shí),異常的根源可能離我們很遠(yuǎn)落包,我們需要回到異常發(fā)生的現(xiàn)場(chǎng)部蛇,找到異常根源。就像現(xiàn)實(shí)生活中破案一樣咐蝇,如果有監(jiān)控?cái)z影機(jī)對(duì)案發(fā)過(guò)程的錄影涯鲁,對(duì)破案來(lái)說(shuō)更加容易。如果僅僅關(guān)注異常本身有序,要找到異常的根源抹腿,需要憑借運(yùn)氣,但有了異常錄制的幫助旭寿,找到根源就更加容易幢踏。
所謂的“異常錄制”,實(shí)際上就是通過(guò)技術(shù)手段许师,收集用戶的操作過(guò)程房蝉,對(duì)用戶的每一個(gè)操作都進(jìn)行記錄,在發(fā)生異常時(shí)微渠,把一定時(shí)間區(qū)間內(nèi)的記錄重新運(yùn)行搭幻,形成影像進(jìn)行播放,讓調(diào)試者無(wú)需向用戶詢問(wèn)逞盆,就能看到用戶當(dāng)時(shí)的操作過(guò)程檀蹋。
上圖是來(lái)自阿里的一套異常錄制還原方案示意圖,用戶在界面上的操作產(chǎn)生的events和mutation被產(chǎn)品收集起來(lái)云芦,上傳到服務(wù)器俯逾,經(jīng)過(guò)隊(duì)列處理按順序存放到數(shù)據(jù)庫(kù)中。當(dāng)需要進(jìn)行異常重現(xiàn)的時(shí)候舅逸,將這些記錄從數(shù)據(jù)庫(kù)中取出桌肴,采用一定的技術(shù)方案,順序播放這些記錄琉历,即可實(shí)現(xiàn)異常還原坠七。
2.5 異常級(jí)別
一般而言水醋,我們會(huì)將收集信息的級(jí)別分為info,warn彪置,error等拄踪,并在此基礎(chǔ)上進(jìn)行擴(kuò)展。
當(dāng)我們監(jiān)控到異常發(fā)生時(shí)拳魁,可以將該異常劃分到“重要——緊急”模型中分為A惶桐、B、C潘懊、D四個(gè)等級(jí)姚糊。有些異常,雖然發(fā)生了卦尊,但是并不影響用戶的正常使用叛拷,用戶其實(shí)并沒(méi)有感知到舌厨,雖然理論上應(yīng)該修復(fù)岂却,但是實(shí)際上相對(duì)于其他異常而言,可以放在后面進(jìn)行處理裙椭。
下文會(huì)討論告警策略躏哩,一般而言,越靠近右上角的異常會(huì)越快通知揉燃,保證相關(guān)人員能最快接收到信息扫尺,并進(jìn)行處理。A級(jí)異常需要快速響應(yīng)炊汤,甚至需要相關(guān)負(fù)責(zé)人知悉正驻。
在收集異常階段,可根據(jù)第一節(jié)劃分的異常后果來(lái)判斷異常的嚴(yán)重程度抢腐,在發(fā)生異常時(shí)選擇對(duì)應(yīng)的上報(bào)方案進(jìn)行上報(bào)姑曙。
3 整理與上報(bào)方案
前文已經(jīng)提到,除了異常報(bào)錯(cuò)信息本身迈倍,我們還需要記錄用戶操作日志伤靠,以實(shí)現(xiàn)場(chǎng)景復(fù)原。這就涉及到上報(bào)的量和頻率問(wèn)題啼染。如果任何日志都立即上報(bào)宴合,這無(wú)異于自造的DDOS攻擊。因此迹鹅,我們需要合理的上報(bào)方案卦洽。下文會(huì)介紹4種上報(bào)方案,但實(shí)際我們不會(huì)僅限于其中一種斜棚,而是經(jīng)常同時(shí)使用逐样,對(duì)不同級(jí)別的日志選擇不同的上報(bào)方案。
3.1 前端存儲(chǔ)日志
我們前面提到,我們并不單單采集異常本身日志脂新,而且還會(huì)采集與異常相關(guān)的用戶行為日志挪捕。單純一條異常日志并不能幫助我們快速定位問(wèn)題根源,找到解決方案争便。但如果要收集用戶的行為日志级零,又要采取一定的技巧,而不能用戶每一個(gè)操作后滞乙,就立即將該行為日志傳到服務(wù)器奏纪,對(duì)于具有大量用戶同時(shí)在線的應(yīng)用,如果用戶一操作就立即上傳日志斩启,無(wú)異于對(duì)日志服務(wù)器進(jìn)行DDOS攻擊序调。因此,我們先將這些日志存儲(chǔ)在用戶客戶端本地兔簇,達(dá)到一定條件之后发绢,再同時(shí)打包上傳一組日志。
那么垄琐,如何進(jìn)行前端日志存儲(chǔ)呢边酒?我們不可能直接將這些日志用一個(gè)變量保存起來(lái),這樣會(huì)擠爆內(nèi)存狸窘,而且一旦用戶進(jìn)行刷新操作墩朦,這些日志就丟失了,因此翻擒,我們自然而然想到前端數(shù)據(jù)持久化方案氓涣。
目前,可用的持久化方案可選項(xiàng)也比較多了陋气,主要有:Cookie劳吠、localStorage、sessionStorage恩伺、IndexedDB赴背、webSQL 、FileSystem 等等晶渠。那么該如何選擇呢凰荚?我們通過(guò)一個(gè)表來(lái)進(jìn)行對(duì)比:
存儲(chǔ)方式 | cookie | localStorage | sessionStorage | IndexedDB | webSQL | FileSystem |
---|---|---|---|---|---|---|
類(lèi)型 | key-value | key-value | NoSQL | SQL | ||
數(shù)據(jù)格式 | string | string | string | object | ||
容量 | 4k | 5M | 5M | 500M | 60M | |
進(jìn)程 | 同步 | 同步 | 同步 | 異步 | 異步 | |
檢索 | key | key | key, index | field | ||
性能 | 讀快寫(xiě)慢 | 讀慢寫(xiě)快 |
綜合之后,IndexedDB是最好的選擇褒脯,它具有容量大便瑟、異步的優(yōu)勢(shì),異步的特性保證它不會(huì)對(duì)界面的渲染產(chǎn)生阻塞番川。而且IndexedDB是分庫(kù)的到涂,每個(gè)庫(kù)又分store凰锡,還能按照索引進(jìn)行查詢黄伊,具有完整的數(shù)據(jù)庫(kù)管理思維,比localStorage更適合做結(jié)構(gòu)化數(shù)據(jù)管理。但是它有一個(gè)缺點(diǎn)抄谐,就是api非常復(fù)雜窃爷,不像localStorage那么簡(jiǎn)單直接皂冰。針對(duì)這一點(diǎn)贿讹,我們可以使用hello-indexeddb這個(gè)工具,它用Promise對(duì)復(fù)雜api進(jìn)行來(lái)封裝伐谈,簡(jiǎn)化操作烂完,使IndexedDB的使用也能做到localStorage一樣便捷。另外诵棵,IndexedDB是被廣泛支持的HTML5標(biāo)準(zhǔn)抠蚣,兼容大部分瀏覽器,因此不用擔(dān)心它的發(fā)展前景履澳。
接下來(lái)嘶窄,我們究竟應(yīng)該怎么合理使用IndexedDB,保證我們前端存儲(chǔ)的合理性呢奇昙?
上圖展示了前端存儲(chǔ)日志的流程和數(shù)據(jù)庫(kù)布局护侮。當(dāng)一個(gè)事件敌完、變動(dòng)储耐、異常被捕獲之后,形成一條初始日志滨溉,被立即放入暫存區(qū)(indexedDB的一個(gè)store)什湘,之后主程序就結(jié)束了收集過(guò)程,后續(xù)的事只在webworker中發(fā)生晦攒。在一個(gè)webworker中闽撤,一個(gè)循環(huán)任務(wù)不斷從暫存區(qū)中取出日志,對(duì)日志進(jìn)行分類(lèi)脯颜,將分類(lèi)結(jié)果存儲(chǔ)到索引區(qū)中哟旗,并對(duì)日志記錄的信息進(jìn)行豐富,將最終將會(huì)上報(bào)到服務(wù)端的日志記錄轉(zhuǎn)存到歸檔區(qū)栋操。而當(dāng)一條日志在歸檔區(qū)中存在的時(shí)間超過(guò)一定天數(shù)之后闸餐,它就已經(jīng)沒(méi)有價(jià)值了,但是為了防止特殊情況矾芙,它被轉(zhuǎn)存到回收區(qū)舍沙,再經(jīng)歷一段時(shí)間后,就會(huì)被從回收區(qū)中清除剔宪。
3.2 前端整理日志
上文講到拂铡,在一個(gè)webworker中對(duì)日志進(jìn)行整理后存到索引區(qū)和歸檔區(qū)壹无,那么這個(gè)整理過(guò)程是怎樣的呢?
由于我們下文要講的上報(bào)感帅,是按照索引進(jìn)行的斗锭,因此,我們?cè)谇岸说娜罩菊砉ぷ魇颍饕褪歉鶕?jù)日志特征拒迅,整理出不同的索引。我們?cè)谑占罩緯r(shí)她倘,會(huì)給每一條日志打上一個(gè)type璧微,以此進(jìn)行分類(lèi),并創(chuàng)建索引硬梁,同時(shí)通過(guò)object-hashcode計(jì)算每個(gè)log對(duì)象的hash值前硫,作為這個(gè)log的唯一標(biāo)志。
- 將所有日志記錄按時(shí)序存放在歸檔區(qū)荧止,并將新入庫(kù)的日志加入索引
- BatchIndexes:批量上報(bào)索引(包含性能等其他日志)屹电,可一次批量上報(bào)100條
- MomentIndexes:即時(shí)上報(bào)索引,一次全部上報(bào)
- FeedbackIndexes:用戶反饋索引跃巡,一次上報(bào)一條
- BlockIndexes:區(qū)塊上報(bào)索引危号,按異常/錯(cuò)誤(traceId,requestId)分塊素邪,一次上報(bào)一塊
- 上報(bào)完成后外莲,被上報(bào)過(guò)的日志對(duì)應(yīng)的索引刪除
- 3天以上日志進(jìn)入回收區(qū)
- 7天以上的日志從回收區(qū)清除
rquestId:同時(shí)追蹤前后端日志。由于后端也會(huì)記錄自己的日志兔朦,因此偷线,在前端請(qǐng)求api的時(shí)候,默認(rèn)帶上requestId沽甥,后端記錄的日志就可以和前端日志對(duì)應(yīng)起來(lái)声邦。
traceId:追蹤一個(gè)異常發(fā)生前后的相關(guān)日志。當(dāng)應(yīng)用啟動(dòng)時(shí)摆舟,創(chuàng)建一個(gè)traceId亥曹,直到一個(gè)異常發(fā)生時(shí),刷新traceId恨诱。把一個(gè)traceId相關(guān)的requestId收集起來(lái)媳瞪,把這些requestId相關(guān)的日志組合起來(lái),就是最終這個(gè)異常相關(guān)的所有日志胡野,用來(lái)對(duì)異常進(jìn)行復(fù)盤(pán)材失。
上圖舉例展示了如何利用traceId和requestId找出和一個(gè)異常相關(guān)的所有日志。在上圖中硫豆,hash4是一條異常日志龙巨,我們找到hash4對(duì)應(yīng)的traceId為traceId2笼呆,在日志列表中,有兩條記錄具有該traceId旨别,但是hash3這條記錄并不是一個(gè)動(dòng)作的開(kāi)始诗赌,因?yàn)閔ash3對(duì)應(yīng)的requestId為reqId2,而reqId2開(kāi)始于hash2秸弛,因此铭若,我們實(shí)際上要把hash2也加入到該異常發(fā)生的整個(gè)復(fù)盤(pán)備選記錄中〉堇溃總結(jié)起來(lái)就是叼屠,我們要找出同一個(gè)traceId對(duì)應(yīng)的所有requestId對(duì)應(yīng)的日志記錄,雖然有點(diǎn)繞绞铃,但稍理解就可以明白其中的道理镜雨。
我們把這些和一個(gè)異常相關(guān)的所有日志集合起來(lái),稱(chēng)為一個(gè)block儿捧,再利用日志的hash集合荚坞,得出這個(gè)block的hash,并在索引區(qū)中建立索引菲盾,等待上報(bào)颓影。
3.3 上報(bào)日志
上報(bào)日志也在webworker中進(jìn)行,為了和整理區(qū)分懒鉴,可以分兩個(gè)worker诡挂。上報(bào)的流程大致為:在每一個(gè)循環(huán)中,從索引區(qū)取出對(duì)應(yīng)條數(shù)的索引疗我,通過(guò)索引中的hash咆畏,到歸檔區(qū)取出完整的日志記錄南捂,再上傳到服務(wù)器吴裤。
按照上報(bào)的頻率(重要緊急度)可將上報(bào)分為四種:
a. 即時(shí)上報(bào)
收集到日志后,立即觸發(fā)上報(bào)函數(shù)溺健。僅用于A類(lèi)異常麦牺。而且由于受到網(wǎng)絡(luò)不確定因素影響,A類(lèi)日志上報(bào)需要有一個(gè)確認(rèn)機(jī)制鞭缭,只有確認(rèn)服務(wù)端已經(jīng)成功接收到該上報(bào)信息之后剖膳,才算完成。否則需要有一個(gè)循環(huán)機(jī)制岭辣,確保上報(bào)成功吱晒。
b. 批量上報(bào)
將收集到的日志存儲(chǔ)在本地,當(dāng)收集到一定數(shù)量之后再打包一次性上報(bào)沦童,或者按照一定的頻率(時(shí)間間隔)打包上傳仑濒。這相當(dāng)于把多次合并為一次上報(bào)叹话,以降低對(duì)服務(wù)器的壓力。
c. 區(qū)塊上報(bào)
將一次異常的場(chǎng)景打包為一個(gè)區(qū)塊后進(jìn)行上報(bào)墩瞳。它和批量上報(bào)不同驼壶,批量上報(bào)保證了日志的完整性,全面性喉酌,但會(huì)有無(wú)用信息热凹。而區(qū)塊上報(bào)則是針對(duì)異常本身的,確保單個(gè)異常相關(guān)的日志被全部上報(bào)泪电。
d. 用戶主動(dòng)提交
在界面上提供一個(gè)按鈕般妙,用戶主動(dòng)反饋bug。這有利于加強(qiáng)與用戶的互動(dòng)相速。
或者當(dāng)異常發(fā)生時(shí)股冗,雖然對(duì)用戶沒(méi)有任何影響,但是應(yīng)用監(jiān)控到了和蚪,彈出一個(gè)提示框止状,讓用戶選擇是否愿意上傳日志。這種方案適合涉及用戶隱私數(shù)據(jù)時(shí)攒霹。
即時(shí)上報(bào) | 批量上報(bào) | 區(qū)塊上報(bào) | 用戶反饋 | |
---|---|---|---|---|
時(shí)效 | 立即 | 定時(shí) | 稍延時(shí) | 延時(shí) |
條數(shù) | 一次全部上報(bào) | 一次100條 | 單次上報(bào)相關(guān)條目 | 一次1條 |
容量 | 小 | 中 | – | – |
緊急 | 緊急重要 | 不緊急 | 不緊急但重要 | 不緊急 |
即時(shí)上報(bào)雖然叫即時(shí)怯疤,但是其實(shí)也是通過(guò)類(lèi)似隊(duì)列的循環(huán)任務(wù)去完成的,它主要是盡快把一些重要的異常提交給監(jiān)控系統(tǒng)催束,好讓運(yùn)維人員發(fā)現(xiàn)問(wèn)題集峦,因此,它對(duì)應(yīng)的緊急程度比較高抠刺。
批量上報(bào)和區(qū)塊上報(bào)的區(qū)別:批量上報(bào)是一次上報(bào)一定條數(shù)塔淤,比如每2分鐘上報(bào)1000條,直到上報(bào)完成速妖。而區(qū)塊上報(bào)是在異常發(fā)生之后高蜂,馬上收集和異常相關(guān)的所有日志,查詢出哪些日志已經(jīng)由批量上報(bào)上報(bào)過(guò)了罕容,剔除掉备恤,把其他相關(guān)日志上傳,和異常相關(guān)的這些日志相對(duì)而言更重要一些锦秒,它們可以幫助盡快復(fù)原異陈恫矗現(xiàn)場(chǎng),找出發(fā)生異常的根源旅择。
用戶提交的反饋信息惭笑,則可以慢悠悠上報(bào)上去。
為了確保上報(bào)是成功的,在上報(bào)時(shí)需要有一個(gè)確認(rèn)機(jī)制沉噩,由于在服務(wù)端接收到上報(bào)日志之后铺敌,并不會(huì)立即存入數(shù)據(jù)庫(kù),而是放到一個(gè)隊(duì)列中屁擅,因此偿凭,前后端在確保日志確實(shí)已經(jīng)記錄進(jìn)數(shù)據(jù)庫(kù)這一點(diǎn)上需要再做一些處理。
上圖展示了上報(bào)的一個(gè)大致流程派歌,在上報(bào)時(shí)弯囊,先通過(guò)hash查詢,讓客戶端知道準(zhǔn)備要上報(bào)的日志集合中胶果,是否存在已經(jīng)被服務(wù)端保存好的日志匾嘱,如果已經(jīng)存在,就將這些日志去除早抠,避免重復(fù)上報(bào)霎烙,浪費(fèi)流量。
3.4 壓縮上報(bào)數(shù)據(jù)
一次性上傳批量數(shù)據(jù)時(shí)蕊连,必然遇到數(shù)據(jù)量大悬垃,浪費(fèi)流量,或者傳輸慢等情況甘苍,網(wǎng)絡(luò)不好的狀態(tài)下尝蠕,可能導(dǎo)致上報(bào)失敗。因此载庭,在上報(bào)之前進(jìn)行數(shù)據(jù)壓縮也是一種方案看彼。
對(duì)于合并上報(bào)這種情況,一次的數(shù)據(jù)量可能要十幾k囚聚,對(duì)于日 pv 大的站點(diǎn)來(lái)說(shuō)靖榕,產(chǎn)生的流量還是很可觀的。所以有必要對(duì)數(shù)據(jù)進(jìn)行壓縮上報(bào)顽铸。lz-string是一個(gè)非常優(yōu)秀的字符串壓縮類(lèi)庫(kù)茁计,兼容性好,代碼量少跋破,壓縮比高簸淀,壓縮時(shí)間短,壓縮率達(dá)到驚人的60%毒返。但它基于LZ78壓縮,如果后端不支持解壓舷手,可選擇gzip壓縮拧簸,一般而言后端會(huì)默認(rèn)預(yù)裝gzip,因此男窟,選擇gzip壓縮數(shù)據(jù)也可以盆赤,工具包pako中自帶了gzip壓縮贾富,可以嘗試使用。
4 日志接收與存儲(chǔ)
4.1 接入層與消息隊(duì)列
一般通過(guò)提供獨(dú)立的日志服務(wù)器接收客戶端日志牺六,接收過(guò)程中颤枪,要對(duì)客戶端日志內(nèi)容的合法性、安全性等進(jìn)行甄別淑际,防止被人攻擊畏纲。而且由于日志提交一般都比較頻繁,多客戶端同時(shí)并發(fā)的情況也常見(jiàn)春缕。通過(guò)消息隊(duì)列將日志信息逐一處理后寫(xiě)入到數(shù)據(jù)庫(kù)進(jìn)行保存也是比較常用的方案盗胀。
上圖為騰訊BetterJS的架構(gòu)圖,其中“接入層”和“推送中心”就是這里提到的接入層和消息隊(duì)列锄贼。BetterJS將整個(gè)前端監(jiān)控的各個(gè)模塊進(jìn)行拆分票灰,推送中心承擔(dān)了將日志推送到存儲(chǔ)中心進(jìn)行存儲(chǔ)和推送給其他系統(tǒng)(例如告警系統(tǒng))的角色,但我們可以把接收日志階段的隊(duì)列獨(dú)立出來(lái)看宅荤,在接入層和存儲(chǔ)層之間做一個(gè)過(guò)渡屑迂。
4.2 日志存儲(chǔ)系統(tǒng)
存儲(chǔ)日志是一個(gè)臟活累活,但是不得不做冯键。對(duì)于小應(yīng)用屈糊,單庫(kù)單表加優(yōu)化就可以應(yīng)付。一個(gè)成規(guī)模的應(yīng)用琼了,如果要提供更標(biāo)準(zhǔn)高效的日志監(jiān)控服務(wù)逻锐,常常需要在日志存儲(chǔ)架構(gòu)上下一些功夫。目前業(yè)界已經(jīng)有比較完備的日志存儲(chǔ)方案雕薪,主要有:Hbase系昧诱,Dremel系,Lucene系等所袁≌档担總體而言,日志存儲(chǔ)系統(tǒng)主要面對(duì)的問(wèn)題是數(shù)據(jù)量大燥爷,數(shù)據(jù)結(jié)構(gòu)不規(guī)律蜈亩,寫(xiě)入并發(fā)高,查詢需求大等前翎。一般一套日志存儲(chǔ)系統(tǒng)稚配,要解決上面這些問(wèn)題,就要解決寫(xiě)入的緩沖港华,存儲(chǔ)介質(zhì)按日志時(shí)間選擇道川,為方便快速讀取而設(shè)計(jì)合理的索引系統(tǒng)等等。
由于日志存儲(chǔ)系統(tǒng)方案比較成熟,這里就不再做更多討論冒萄。
4.3 搜索
日志的最終目的是要使用臊岸,由于一般日志的體量都非常大,因此尊流,要在龐大的數(shù)據(jù)中找到需要的日志記錄帅戒,需要依賴(lài)比較好的搜索引擎。Splunk是一套成熟的日志存儲(chǔ)系統(tǒng)崖技,但它是付費(fèi)使用的逻住。按照Splunk的框架,Elk是Splunk的開(kāi)源實(shí)現(xiàn)响疚,Elk是ElasticSearch鄙信、Logstash、Kibana的結(jié)合忿晕,ES基于Lucene的存儲(chǔ)装诡、索引的搜索引擎;logstash是提供輸入輸出及轉(zhuǎn)化處理插件的日志標(biāo)準(zhǔn)化管道践盼;Kibana提供可視化和查詢統(tǒng)計(jì)的用戶界面鸦采。
5 日志統(tǒng)計(jì)與分析
一個(gè)完善的日志統(tǒng)計(jì)分析工具需要提供各方面方便的面板,以可視化的方式給日志管理員和開(kāi)發(fā)者反饋信息咕幻。
5.1 用戶緯度
同一個(gè)用戶的不同請(qǐng)求實(shí)際上會(huì)形成不同的story線渔伯,因此,針對(duì)用戶的一系列操作設(shè)計(jì)唯一的request id是有必要的肄程。同一個(gè)用戶在不同終端進(jìn)行操作時(shí)锣吼,也能進(jìn)行區(qū)分。用戶在進(jìn)行某個(gè)操作時(shí)的狀態(tài)蓝厌、權(quán)限等信息玄叠,也需要在日志系統(tǒng)中予以反應(yīng)。
5.2 時(shí)間維度
一個(gè)異常是怎么發(fā)生的拓提,需要將異常操作的前后story線串聯(lián)起來(lái)觀察读恃。它不單單涉及一個(gè)用戶的一次操作,甚至不限于某一個(gè)頁(yè)面代态,而是一連串事件的最終結(jié)果寺惫。
5.3 性能維度
應(yīng)用運(yùn)行過(guò)程中的性能情況,例如蹦疑,界面加載時(shí)間西雀,api請(qǐng)求時(shí)長(zhǎng)統(tǒng)計(jì),單元計(jì)算的消耗必尼,用戶呆滯時(shí)間蒋搜。
5.4 運(yùn)行環(huán)境維度
應(yīng)用及服務(wù)所運(yùn)行的環(huán)境情況篡撵,例如應(yīng)用所在的網(wǎng)絡(luò)環(huán)境判莉,操作系統(tǒng)豆挽,設(shè)備硬件信息等,服務(wù)器cpu券盅、內(nèi)存狀況帮哈,網(wǎng)絡(luò)、寬帶使用情況等锰镀。
5.4 細(xì)粒度代碼追蹤
異常的代碼stack信息娘侍,定位到發(fā)生異常的代碼位置和異常堆棧。
5.6 場(chǎng)景回溯
通過(guò)將異常相關(guān)的用戶日志連接起來(lái)泳炉,以動(dòng)態(tài)的效果輸出發(fā)生異常的過(guò)程憾筏。
6 監(jiān)控與通知
對(duì)異常進(jìn)行統(tǒng)計(jì)和分析只是基礎(chǔ),而在發(fā)現(xiàn)異常時(shí)可以推送和告警花鹅,甚至做到自動(dòng)處理氧腰,才是一個(gè)異常監(jiān)控系統(tǒng)應(yīng)該具備的能力。
6.1 自定義觸發(fā)條件的告警
a. 監(jiān)控實(shí)現(xiàn)
當(dāng)日志信息進(jìn)入接入層時(shí)刨肃,就可以觸發(fā)監(jiān)控邏輯古拴。當(dāng)日志信息中存在較為高級(jí)別的異常時(shí),也可以立即出發(fā)告警真友。告警消息隊(duì)列和日志入庫(kù)隊(duì)列可以分開(kāi)來(lái)管理黄痪,實(shí)現(xiàn)并行。
對(duì)入庫(kù)日志信息進(jìn)行統(tǒng)計(jì)盔然,對(duì)異常信息進(jìn)行告警桅打。對(duì)監(jiān)控異常進(jìn)行響應(yīng)。所謂監(jiān)控異常愈案,是指:有規(guī)律的異常一般而言都比較讓人放心挺尾,比較麻煩的是突然之間的異常。例如在某一時(shí)段突然頻繁接收到D級(jí)異常刻帚,雖然D級(jí)異常是不緊急一般重要潦嘶,但是當(dāng)監(jiān)控本身發(fā)生異常時(shí),就要提高警惕崇众。
b. 自定義觸發(fā)條件
除了系統(tǒng)開(kāi)發(fā)時(shí)配置的默認(rèn)告警條件掂僵,還應(yīng)該提供給日志管理員可配置的自定義觸發(fā)條件。
- 日志內(nèi)含有什么內(nèi)容時(shí)
- 日志統(tǒng)計(jì)達(dá)到什么度顷歌、量時(shí)
- 向符合什么條件的用戶告警
6.2 推送渠道
可選擇的途徑有很多锰蓬,例如郵件、短信眯漩、微信芹扭、電話麻顶。
6.3 推送頻率
針對(duì)不同級(jí)別的告警,推送的頻率也可以進(jìn)行設(shè)定舱卡。低風(fēng)險(xiǎn)告警可以以報(bào)告的形式一天推送一次辅肾,高風(fēng)險(xiǎn)告警10分鐘循環(huán)推送,直到處理人手動(dòng)關(guān)閉告警開(kāi)關(guān)轮锥。
6.4 自動(dòng)報(bào)表
對(duì)于日志統(tǒng)計(jì)信息的推送矫钓,可以做到自動(dòng)生成日?qǐng)?bào)、周報(bào)舍杜、月報(bào)新娜、年報(bào)并郵件發(fā)送給相關(guān)群組。
6.5 自動(dòng)產(chǎn)生bug工單
當(dāng)異常發(fā)生時(shí)既绩,系統(tǒng)可以調(diào)用工單系統(tǒng)API實(shí)現(xiàn)自動(dòng)生成bug單概龄,工單關(guān)閉后反饋給監(jiān)控系統(tǒng),形成對(duì)異常處理的追蹤信息進(jìn)行記錄饲握,在報(bào)告中予以展示私杜。
7 修復(fù)異常
7.1 sourcemap
前端代碼大部分情況都是經(jīng)過(guò)壓縮后發(fā)布的,上報(bào)的stack信息需要還原為源碼信息互拾,才能快速定位源碼進(jìn)行修改歪今。
發(fā)布時(shí),只部署js腳本到服務(wù)器上颜矿,將sourcemap文件上傳到監(jiān)控系統(tǒng)寄猩,在監(jiān)控系統(tǒng)中展示stack信息時(shí),利用sourcemap文件對(duì)stack信息進(jìn)行解碼骑疆,得到源碼中的具體信息田篇。
但是這里有一個(gè)問(wèn)題,就是sourcemap必須和正式環(huán)境的版本對(duì)應(yīng)箍铭,還必須和git中的某個(gè)commit節(jié)點(diǎn)對(duì)應(yīng)泊柬,這樣才能保證在查異常的時(shí)候可以正確利用stack信息,找到出問(wèn)題所在版本的代碼诈火。這些可以通過(guò)建立CI任務(wù)兽赁,在集成化部署中增加一個(gè)部署流程,以實(shí)現(xiàn)這一環(huán)節(jié)冷守。
7.2 從告警到預(yù)警
預(yù)警的本質(zhì)是刀崖,預(yù)設(shè)可能出現(xiàn)異常的條件,當(dāng)觸發(fā)該條件時(shí)異常并沒(méi)有真實(shí)發(fā)生拍摇,因此亮钦,可以趕在異常發(fā)生之前對(duì)用戶行為進(jìn)行檢查,及時(shí)修復(fù)充活,避免異撤淅颍或異常擴(kuò)大蜡娶。
怎么做呢?其實(shí)就是一個(gè)統(tǒng)計(jì)聚類(lèi)的過(guò)程映穗。將歷史中發(fā)生異常的情況進(jìn)行統(tǒng)計(jì)窖张,從時(shí)間、地域男公、用戶等不同維度加以統(tǒng)計(jì)荤堪,找出規(guī)律合陵,并將這些規(guī)律通過(guò)算法自動(dòng)加入到預(yù)警條件中枢赔,當(dāng)下次觸發(fā)時(shí),及時(shí)預(yù)警拥知。
7.3 智能修復(fù)
自動(dòng)修復(fù)錯(cuò)誤踏拜。例如,前端要求接口返回?cái)?shù)值低剔,但接口返回了數(shù)值型的字符串速梗,那么可以有一種機(jī)制,監(jiān)控系統(tǒng)發(fā)送正確數(shù)據(jù)類(lèi)型模型給后端襟齿,后端在返回?cái)?shù)據(jù)時(shí)姻锁,根據(jù)該模型控制每個(gè)字段的類(lèi)型。
8 異常測(cè)試
8.1 主動(dòng)異常測(cè)試
撰寫(xiě)異常用例猜欺,在自動(dòng)化測(cè)試系統(tǒng)中位隶,加入異常測(cè)試用戶。在測(cè)試或運(yùn)行過(guò)程中开皿,每發(fā)現(xiàn)一個(gè)異常涧黄,就將它加入到原有的異常用例列表中。
8.2 隨機(jī)異常測(cè)試
模擬真實(shí)環(huán)境赋荆,在模擬器中模擬真實(shí)用戶的隨機(jī)操作笋妥,利用自動(dòng)化腳本產(chǎn)生隨機(jī)操作動(dòng)作代碼,并執(zhí)行窄潭。
定義異常春宣,例如彈出某個(gè)彈出框,包含特定內(nèi)容時(shí)嫉你,就是異常月帝。將這些測(cè)試結(jié)果記錄下來(lái),再聚類(lèi)統(tǒng)計(jì)分析均抽,對(duì)防御異常也很有幫助嫁赏。
9 部署
9.1 多客戶端
一個(gè)用戶在不同終端上登錄,或者一個(gè)用戶在登錄前和登錄后的狀態(tài)油挥。通過(guò)特定算法生成requestID潦蝇,通過(guò)該requestId可以確定某個(gè)用戶在獨(dú)立客戶端上的一系列操作款熬,根據(jù)日志時(shí)序,可以梳理出用戶產(chǎn)生異常的具體路徑攘乒。
9.2 集成便捷性
前端寫(xiě)成包贤牛,全局引用即可完成大部分日志記錄、存儲(chǔ)和上報(bào)则酝。在特殊邏輯里面殉簸,可以調(diào)用特定方法記錄日志。
后端與應(yīng)用本身的業(yè)務(wù)代碼解耦沽讹,可以做成獨(dú)立的服務(wù)般卑,通過(guò)接口和第三方應(yīng)用交互。利用集成部署爽雄,可以將系統(tǒng)隨時(shí)進(jìn)行擴(kuò)容蝠检、移植等操作。
9.3 管理系統(tǒng)的可擴(kuò)展
整套系統(tǒng)可擴(kuò)展挚瘟,不僅服務(wù)單應(yīng)用叹谁,可支持多個(gè)應(yīng)用同時(shí)運(yùn)行。同一個(gè)團(tuán)隊(duì)下的所有應(yīng)用都可以利用同一個(gè)平臺(tái)進(jìn)行管理乘盖。
9.4 日志系統(tǒng)權(quán)限
不同的人在訪問(wèn)日志系統(tǒng)時(shí)權(quán)限不同焰檩,一個(gè)訪問(wèn)者只能查看自己相關(guān)的應(yīng)用,有些統(tǒng)計(jì)數(shù)據(jù)如果比較敏感订框,可以單獨(dú)設(shè)置權(quán)限析苫,敏感數(shù)據(jù)可脫敏。
10 其他
10.1 性能監(jiān)控
異常監(jiān)控主要針對(duì)代碼級(jí)別的報(bào)錯(cuò)布蔗,但也應(yīng)該關(guān)注性能異常藤违。性能監(jiān)控主要包括:
- 運(yùn)行時(shí)性能:文件級(jí)、模塊級(jí)纵揍、函數(shù)級(jí)顿乒、算法級(jí)
- 網(wǎng)絡(luò)請(qǐng)求速率
- 系統(tǒng)性能
10.2 API Monitor
后端API對(duì)前端的影響也非常大,雖然前端代碼也控制邏輯泽谨,但是后端返回的數(shù)據(jù)是基礎(chǔ)璧榄,因此對(duì)API的監(jiān)控可以分為:
- 穩(wěn)定性監(jiān)控
- 數(shù)據(jù)格式和類(lèi)型
- 報(bào)錯(cuò)監(jiān)控
- 數(shù)據(jù)準(zhǔn)確性監(jiān)控
10.3 數(shù)據(jù)脫敏
敏感數(shù)據(jù)不被日志系統(tǒng)采集。由于日志系統(tǒng)的保存是比較開(kāi)放的吧雹,雖然里面的數(shù)據(jù)很重要骨杂,但是在存儲(chǔ)上大部分日志系統(tǒng)都不是保密級(jí),因此雄卷,如果應(yīng)用涉及了敏感數(shù)據(jù)搓蚪,最好做到:
- 獨(dú)立部署,不和其他應(yīng)用共享監(jiān)控系統(tǒng)
- 不采集具體數(shù)據(jù)丁鹉,只采集用戶操作數(shù)據(jù)妒潭,在重現(xiàn)時(shí)悴能,通過(guò)日志信息可以取出數(shù)據(jù)api結(jié)果來(lái)展示
- 日志加密,做到軟硬件層面的加密防護(hù)
- 必要時(shí)雳灾,可采集具體數(shù)據(jù)的ID用于調(diào)試漠酿,場(chǎng)景重現(xiàn)時(shí),用mock數(shù)據(jù)替代谎亩,mock數(shù)據(jù)可由后端采用假的數(shù)據(jù)源生成
- 對(duì)敏感數(shù)據(jù)進(jìn)行混淆
結(jié)語(yǔ)
本文主要是對(duì)前端異常監(jiān)控的整體框架進(jìn)行了研究炒嘲,沒(méi)有涉及到具體的技術(shù)實(shí)現(xiàn),涉及前端部分和后臺(tái)部分以及與整個(gè)問(wèn)題相關(guān)的一些知識(shí)點(diǎn)匈庭,主要關(guān)注前端部分夫凸,它和后端的監(jiān)控有重疊部分也有分支部分,需要在一個(gè)項(xiàng)目中不斷實(shí)踐嚎花,總結(jié)出項(xiàng)目本身的監(jiān)控需求和策略寸痢。