如何使用 Sentry 捕獲前端異常
工作多年,發(fā)現(xiàn)大家總是會(huì)遇到這種特殊的場(chǎng)景:用戶反映某個(gè)功能異常。為了找出問(wèn)題所在,我們嘗試在本地重現(xiàn)異常,但結(jié)果是什么都沒(méi)有。另一方面,前端代碼的運(yùn)行環(huán)境,如PC瀏覽器、手機(jī)瀏覽器等,復(fù)雜且不可控。這意味著代碼中可能會(huì)出現(xiàn)各種不可預(yù)知的錯(cuò)誤。
在這種情況下,如果我們想要擁有一套完整的前端異常監(jiān)控系統(tǒng),首先,需要關(guān)心的問(wèn)題就是,如何及時(shí)捕捉異常,如何準(zhǔn)確定位異常和錯(cuò)誤的位置,采集到異常后如何及時(shí)通知相關(guān)人員?
選擇解決方案
我們先來(lái)看看常見的前端監(jiān)控方案。
方案一:自我研究。
具體工作主要是:自己重寫Window對(duì)象中的onerror和onunhandledrejection方法,收集錯(cuò)誤信息,通過(guò)服務(wù)端接口上傳,編寫服務(wù)端文件,使用Sourcemap文件恢復(fù)源碼排查問(wèn)題。
此外,還可以搭建一個(gè)查看異常信息的平臺(tái)。因此,自研方法存在明顯的缺陷,需要大量的精力。當(dāng)然,自研也有易于擴(kuò)展的優(yōu)勢(shì),比如在前端監(jiān)控中加入性能監(jiān)控功能,方便后續(xù)頁(yè)面的性能優(yōu)化。
方案二:借助成熟的第三方工具,例如 Sentry。
這種方法不需要大量的開發(fā),只要訪問(wèn)配置足夠。
對(duì)于這兩種解決方案,如果自己沒(méi)有那么多精力去研究,可以選擇使用第三方工具。
在成熟的第三方工具中,我推薦你使用 Sentry。因?yàn)?Sentry 是一個(gè)開源的 bug 跟蹤工具,可以幫助我們實(shí)時(shí)監(jiān)控和修復(fù)系統(tǒng) bug。
此外,Sentry 支持通過(guò) Sourcemap 文件恢復(fù) JS 錯(cuò)誤調(diào)用堆棧,也可以在收集到異常后通過(guò) Telegram 或郵件實(shí)時(shí)通知。
另一個(gè)重要的點(diǎn)是,Sentry 允許我們?cè)谧约旱姆?wù)器上構(gòu)建私有服務(wù),這意味著我們可以免費(fèi)使用 Sentry 的強(qiáng)大功能,避免源代碼泄露的風(fēng)險(xiǎn)。
下面這張圖可以直觀地展示哨兵采集異常信息的效果。
如何及時(shí)捕獲異常?
部署哨兵
第一步,無(wú)疑是部署 Sentry。 由于官方推薦使用 Docker 進(jìn)行部署,且操作相對(duì)簡(jiǎn)單,所以我將以 Docker 為例,向大家展示如何從零開始搭建 Sentry 服務(wù)。
首先,我們安裝 Docker 和 Docker-Compose。 安裝完成后,啟動(dòng)Docker,拉取sentry-onpremise倉(cāng)庫(kù)代碼,這是Sentry官方提供的安裝程序,然后啟動(dòng)里面的安裝腳本。
在此期間,它將指導(dǎo)您創(chuàng)建管理會(huì)員帳戶并最終啟動(dòng)哨兵服務(wù)。 相關(guān)命令可以參考這段代碼:
git clone https://github.com/getsentry/onpremise
cd onpremise
./install.sh
$ docker-compose up -d
如果啟動(dòng)過(guò)程沒(méi)問(wèn)題,在瀏覽器中輸入http://ip:9000進(jìn)入Sentry登錄頁(yè)面,然后使用剛剛創(chuàng)建的管理員用戶名和密碼登錄系統(tǒng)。
前端項(xiàng)目訪問(wèn)
經(jīng)過(guò)剛才的一些操作,我們的Sentry服務(wù)器就完成了,接下來(lái),我們可以在應(yīng)用中集成Sentry客戶端SDK,在前端代碼中實(shí)時(shí)報(bào)錯(cuò)。
Sentry 非常強(qiáng)大,支持各種前端框架,如 Vue、Angular、React 等。我們都知道 Vue 是一個(gè)流行的前端輕量級(jí)框架,具有輕量級(jí)、高性能和組件化的優(yōu)勢(shì)。那么我將以Vue項(xiàng)目為例進(jìn)行詳細(xì)介紹。
創(chuàng)建項(xiàng)目
首先,我們點(diǎn)擊Sentry頁(yè)面左側(cè)導(dǎo)航欄中的第一項(xiàng)Projects,然后,點(diǎn)擊頁(yè)面右上角的Create Project按鈕。
然后,在Browser下選擇Vue,再次點(diǎn)擊CreateProject就可以創(chuàng)建項(xiàng)目了。
接下來(lái),您將看到 Sentry 給出的 Vue 項(xiàng)目的配置指南,它將逐步指導(dǎo)您完成項(xiàng)目配置。
然后,我們繼續(xù)指南。
首先,通過(guò)npm在項(xiàng)目中安裝Sentry依賴的兩個(gè)npm包,分別是@sentry/browser和@sentry/integrations,然后,在main.js中導(dǎo)入。
然后,使用Sentry.init初始化和配置Sentry。配置的時(shí)候,教程里已經(jīng)提供了初始化代碼,我們直接復(fù)制粘貼到main.js中即可。
最后,我們點(diǎn)擊指南底部的確認(rèn)按鈕,然后,自動(dòng)跳轉(zhuǎn)到本項(xiàng)目的Issue錯(cuò)誤頁(yè)面。
這里需要特別注意的是DSN地址與項(xiàng)目一一對(duì)應(yīng),不能隨意更改。
import * as Sentry from '@sentry/browser'
import { Vue as VueIntegration } from '@sentry/integrations'
Sentry.init({
dsn: 'https://xxxxxxxxxxxxxxxxx@sentry.in.cn/2',
integrations: [new VueIntegration({
Vue,
attachProps: true
})]
})
核實(shí)
現(xiàn)在,在Issue錯(cuò)誤頁(yè)面上,我們看到,只有一個(gè)空白表單,并且沒(méi)有任務(wù)異常信息。 讓我們創(chuàng)建一個(gè) JS 錯(cuò)誤報(bào)告,看看 Sentry 的效果。
首先,我們?cè)贏pp.vue的created方法中添加一行代碼:this.test(),調(diào)用當(dāng)前組件中不存在的方法,強(qiáng)行產(chǎn)生JS錯(cuò)誤。 通過(guò) Chrome DevTools 中的 Network 可以看到,每次頁(yè)面刷新時(shí),都會(huì)發(fā)送一個(gè) Sentry 相關(guān)的 Post 請(qǐng)求,也就是 Sentry 收集異常信息。 這時(shí)候進(jìn)入Issue報(bào)錯(cuò)頁(yè)面,我們發(fā)現(xiàn)Sentry已經(jīng)顯示了捕獲到的異常:
我們知道,Sentry 將每個(gè)異常報(bào)告都視為一個(gè) Event,每個(gè) Event 都有一個(gè) Fingerprint。 指紋默認(rèn)由 Sentry 的分組算法生成。 相同指紋的事件將自動(dòng)合并為一個(gè)問(wèn)題。 具體生成邏輯可以查看官方文檔:https://docs.sentry.io/product/data-management-settings/event-grouping/
通過(guò)問(wèn)題列表,我們可以獲得以下信息:異常類型、異常名稱、觸發(fā)位置、最近觸發(fā)時(shí)間、首次觸發(fā)時(shí)間等。
點(diǎn)擊進(jìn)入問(wèn)題詳情頁(yè)面,在頁(yè)面中間區(qū)域可以看到最新Event的具體信息,如用戶IP地址、瀏覽器信息、系統(tǒng)信息、異常調(diào)用棧信息等。
如何準(zhǔn)確定位異常報(bào)錯(cuò)的位置?
現(xiàn)在,我們看到 Sentry 已經(jīng)捕獲了異常調(diào)用堆棧信息。但是,因?yàn)榫W(wǎng)上的代碼都是經(jīng)過(guò)壓縮和混淆的,要知道是哪一行代碼報(bào)錯(cuò),只能全局搜索關(guān)鍵字,然后根據(jù)壓縮代碼的上下文定位。
那么如何查明錯(cuò)誤消息呢?
首先,我們?cè)赟entry后臺(tái)配置AuthToken,這是配置上傳Sourcemap的必要參數(shù)。
那么如何創(chuàng)建這個(gè)Token呢?
我們點(diǎn)擊頁(yè)面左上角的用戶名,在下拉菜單中找到User Settings,點(diǎn)擊進(jìn)入用戶設(shè)置界面,然后,點(diǎn)擊Auth Tokens菜單選項(xiàng)新建一個(gè)Token。
接下來(lái),我們?cè)跇?gòu)建編譯代碼的時(shí)候開啟Sourcemap配置,然后,在根目錄下新建一個(gè).sentryclirc文件。
最后,在項(xiàng)目中下載安裝Webpack插件@sentry/webpack-plugin,在打包配置文件中添加上傳Sourcemap到Sentry的配置。
具體配置請(qǐng)參考這段代碼:
[auth]
token=exxxxxxxxxxxx
[defaults]
project=xiaoan-web
org=sentry
url=https://sentry.xxxxx.com/
view raw
這里的 Release 屬性對(duì)應(yīng)的是代碼版本。 Sentry在采集異常信息時(shí),會(huì)同步采集用戶的代碼版本信息。 通過(guò)這些信息,我們可以知道是哪個(gè)版本引起了新的問(wèn)題。
需要注意的是,UrlPrefix 屬性值并不是固定的,而是與項(xiàng)目靜態(tài)資源訪問(wèn)路徑有關(guān)。
const SentryWebpackPlugin = require('@sentry/webpack-plugin')
const commitHash = require('child_process').execSync('git rev-parse HEAD').toString();
new SentryWebpackPlugin({
include: path.resolve(__dirname, '../dist/static/js/'),
ignoreFile: '.sentrycliignore',
ignore: ['node_modules', 'webpack.config.js'],
release: commitHash,
urlPrefix: '~/static/js' // https://ip.com/static/js/app.js
})
配置完成后,Sentry可以根據(jù)上傳的Sourcemap恢復(fù)代碼位置:
異常采集后如何及時(shí)通知相關(guān)人員?
當(dāng) Sentry 捕捉到異常時(shí),我們希望它能實(shí)時(shí)通知開發(fā)者,針對(duì)這種情況,Sentry 提供了郵件通知功能,只需在 Sentry 的配置文件中添加相關(guān)配置即可。
由于檢查郵件可能不夠及時(shí),如果你的團(tuán)隊(duì)使用 Telegram 進(jìn)行協(xié)同工作,你可以嘗試使用第三方 Telegram 插件,你可以在網(wǎng)上搜索一下如何使用。
結(jié)論
以上就是今天的全部?jī)?nèi)容,希望你會(huì)喜歡,如果你覺得有用的話,請(qǐng)記得點(diǎn)贊我,關(guān)注我,并將它分享給你的朋友,也許能夠幫助到他。
最后,感謝您的閱讀,祝編程愉快!