異常上報(bào)如何選擇通訊方式 動(dòng)態(tài)創(chuàng)建img標(biāo)簽: 其實(shí)上報(bào)就是要將捕獲的異常信息發(fā)送到后端。最常用的方式首推動(dòng)態(tài)創(chuàng)建標(biāo)簽方式。 因?yàn)檫@種方式無(wú)需加載任何通訊庫(kù),而且頁(yè)面是無(wú)需刷新的。 基本上目前包括百度統(tǒng)計(jì) Google統(tǒng)計(jì)都是基于這個(gè)原理做的埋點(diǎn)。 new Image().src ='http://localhost:7001/monitor/error'+ '?info =xxxxxx' 通過(guò)動(dòng)態(tài)創(chuàng)建一個(gè)img,瀏覽器就會(huì)向服務(wù)器發(fā)送get請(qǐng)求。 可以把你需要上報(bào)的錯(cuò)誤數(shù)據(jù)放在querystring字符串中,利用這種方式就可以將錯(cuò)誤上報(bào)到服務(wù)器了。 Ajax上報(bào): 實(shí)際上我們也可以用ajax的方式上報(bào)錯(cuò)誤,這和我們?cè)贅I(yè)務(wù)程序中并沒(méi)有什么區(qū)別。 上報(bào)哪些數(shù)據(jù): 上報(bào)哪些數(shù)據(jù): 我們先看一下error事件參數(shù): 其中核心的應(yīng)該是錯(cuò)誤棧,其實(shí)我們定位錯(cuò)誤最主要的就是錯(cuò)誤棧。 錯(cuò)誤堆棧中包含了絕大多數(shù)調(diào)試有關(guān)的信息。其中包括了異常位置(行號(hào),列號(hào)),異常信息 上報(bào)數(shù)據(jù)序列化: 由于通訊的時(shí)候只能以字符串方式傳輸,我們需要將對(duì)象進(jìn)行序列化處理。 大概分成以下三步: 1、將異常數(shù)據(jù)從屬性中解構(gòu)出來(lái),存入一個(gè)JSON對(duì)象 2、將JSON對(duì)象轉(zhuǎn)換為字符串 3、將字符串轉(zhuǎn)換為Base64 當(dāng)然在后端也要做對(duì)應(yīng)的反向操作 這個(gè)我們后面再說(shuō)。 異常上報(bào)的后端服務(wù)器 搭建eggis工程: 異常上報(bào)的數(shù)據(jù)一定是要有一個(gè)后端服務(wù)接收才可以。 我們就以比較流行的開(kāi)源框架eggjs為例來(lái)演示 # 全局安裝egg-cli npm i egg-init -g # 創(chuàng)建后端項(xiàng)目 egg-init backend --type=simple cd backend npm i # 啟動(dòng)項(xiàng)目 npm run dev 編寫(xiě)error上傳接口: 首先在app/router.js添加一個(gè)新的路由 創(chuàng)建一個(gè)新的: controller (app/controller/monitor) 看一下接收后的結(jié)果? 記入日志文件: 下一步就是講錯(cuò)誤記入日志。實(shí)現(xiàn)的方法可以自己用fs寫(xiě),也可以借助log4js這樣成熟的日志庫(kù)。 當(dāng)然在eggjs中是支持我們定制日志那么我么你就用這個(gè)功能定制一個(gè)前端錯(cuò)誤日志好了。 在/config/config.default.js中增加一個(gè)定制日志配置 在/app/controller/monitor.js中添加日志記錄: ![]() 最后實(shí)現(xiàn)的效果: ![]() ![]() Webpack插件實(shí)現(xiàn)SourceMap上傳 談到異常分析最重要的工作其實(shí)是將webpack混淆壓縮的代碼還原。 創(chuàng)建Webpack插件: /source-map/plugin(文件位置) ![]() 加載webpack插件: webpack.config.js(文件位置) ![]() 添加讀取sourcemap讀取邏輯: 在apply函數(shù)中增加讀取sourcemap文件的邏輯 /plugin/uploadSourceMapWebPlugin.js ![]() 實(shí)現(xiàn)http上傳功能: ![]() 服務(wù)器端添加上傳接口: /backend/app/router.js(文件位置) ![]() 添加sourcemap上傳接口: /backend/app/controller/monitor.js ![]() 最終效果: 執(zhí)行webpack打包時(shí)調(diào)用插件sourcemap被上傳至服務(wù)器。 ![]() ![]() 解析ErrorStack 考慮到這個(gè)功能需要較多邏輯,我們準(zhǔn)備把他開(kāi)發(fā)成一個(gè)獨(dú)立的函數(shù)并且用Jest來(lái)做單元測(cè)試: 先看一下我們的需求? ![]() 搭建Jest框架: ![]() 首先創(chuàng)建一個(gè)/utils/stackparser.js文件? ![]() 在同級(jí)目錄下創(chuàng)建測(cè)試文件stackparser.spec.js 以上需求我們用Jest表示就是 ![]() 整理如下: 下面我們運(yùn)行Jest npx jest stackparser --watch ![]() 顯示運(yùn)行失敗,原因很簡(jiǎn)單因?yàn)槲覀冞€沒(méi)有實(shí)現(xiàn)對(duì)吧。 ![]() 下面我們就實(shí)現(xiàn)一下這個(gè)方法 反序列Error對(duì)象: 首先創(chuàng)建一個(gè)新的Error對(duì)象 將錯(cuò)誤棧設(shè)置到Error中。 然后利用error-stack-parser這個(gè)npm庫(kù)來(lái)轉(zhuǎn)化為stackFrame ![]() 運(yùn)行效果如下? ![]() 解析ErrorStack: 下一步我們將錯(cuò)誤棧中的代碼位置轉(zhuǎn)換為源碼位置 ![]() 我們?cè)儆肑est測(cè)試一下? ![]() 這時(shí)我們?cè)倏匆幌陆Y(jié)果: ![]() 這樣一來(lái)測(cè)試就通過(guò)啦~ 將源碼位置記入日志: ![]() 記錄完成后,我們?cè)賮?lái)看一下運(yùn)行效果: ![]() 結(jié)束了這一步,我們的ErrorStack工作就完成了。 ![]() 需要運(yùn)用的兩種開(kāi)源框架 Fundebug: Fundebug專(zhuān)注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了10億+錯(cuò)誤事件,付費(fèi)客戶(hù)有陽(yáng)光保險(xiǎn)、荔枝FM、掌門(mén)1對(duì)1、核桃編程、微脈等眾多品牌企業(yè)。 Sentry: Sentry 是一個(gè)開(kāi)源的實(shí)時(shí)錯(cuò)誤追蹤系統(tǒng),可以幫助開(kāi)發(fā)者實(shí)時(shí)監(jiān)控并修復(fù)異常問(wèn)題。 它主要專(zhuān)注于持續(xù)集成、提高效率并且提升用戶(hù)體驗(yàn)。 Sentry 分為服務(wù)端和客戶(hù)端 SDK,前者可以直接使用它家提供的在線服務(wù),也可以本地自行搭建; 后者提供了對(duì)多種主流語(yǔ)言和框架的支持,包括 React、Angular、Node、Django、RoR、PHP、Laravel、Android、.NET、JAVA 等。 同時(shí)它可提供了和其他流行服務(wù)集成的方案,例如 GitHub、GitLab、bitbuck、heroku、slack、Trello 等。 目前公司的項(xiàng)目也都在逐步應(yīng)用上 Sentry 進(jìn)行錯(cuò)誤日志管理。 總結(jié): 截止到目前為止,我們把前端異常監(jiān)控的基本功能算是形成了一個(gè)MVP(最小化可行產(chǎn)品)。 后面需要升級(jí)的還有很多,對(duì)錯(cuò)誤日志的分析和可視化方面可以使用ELK。 發(fā)布和部署可以采用Docker。對(duì)eggjs的上傳和上報(bào)最好要增加權(quán)限控制功能。 關(guān)于這一期的VUE異常處理課程我們就講到這里啦。 |
|