這篇文章也發在個人博客,歡迎圍觀😄javascript
前端監控是相對於後端監控而言的,以往的後端監控只能記錄接口被請求以後所發生的錯誤,可是如今隨着用戶複雜度不斷提升,不少錯誤是在後端接口被請求之前就發生的JS錯誤。對於這種錯誤,傳統的後端錯誤監控是無能爲力的,所以前端監控應運而生。前端
最近想在公司的項目上部署前端監控,以主動捕捉用戶端的錯誤(知足咱們本身的控制慾😄),再也不等待用戶的反饋(事實上用戶的反饋少之又少😓)。原本考慮本身寫一個,奈何水平有限,加之看到已經有很多成熟的方案,因此...大家懂得!目前較爲成熟的前端監控方案,具體參考知乎帖子 如何作前端異常監控 ,大體上可供選擇的方案以下:vue
由於是想部署到公司本身的服務器上,上述貌似只有Sentry和BetterJS有提供自行部署的方案。而後考慮到目前前端項目都是壓縮打包後再發布的,可以結合sourcemaps對錯誤進行定位是很是有必要的,所以從二者中選擇了Sentry。(上述方案中,Fundebug也是支持sourcemaps的)java
做爲試用,我選擇使用Sentry提供的服務,註冊帳號以後,選擇使用免費版的服務,就能夠開始在前端對咱們的項目加入前端錯誤監控了。webpack
首先,固然是要看Sentry提供的docs了,建立項目的步驟能夠說是介紹得很是清楚了。git
OK,建立一個新項目以後,就應該到個人前端項目中引入監控的模塊了。此處,由於個人項目是使用Vue的SPA項目,因此使用的是Sentry官方推薦的Raven.js。下載該模塊以後,按照官方指引在項目中引入文件,其中key和project在你註冊帳號以後官方都會自動幫你生成的,很是貼心。github
// main.js
import Raven from 'raven-js'
import RavenVue from 'raven-js/plugins/vue'
Raven
.config('https://<key>@sentry.io/<project>')
.addPlugin(RavenVue, Vue)
.install()
複製代碼
這時候,你只要在你項目中的一個不起眼的角落埋下一個錯誤,而後去觸發一下,就能看到調用了raven.js發送錯誤,而且在你的sentry項目中也能看到相關報錯了。web
可是這樣的報錯信息其實意義不大,除了可以看到具體的error緣由外,錯誤位置根本無從定位。若是錯誤信息沒有具體到咱們足以立刻定位出錯誤位置,那麼咱們只能一遍遍地對代碼進行排查,耗時耗力。這時候就要使用sourcemaps對錯誤進行定位了,所幸Sentry對此的支持也是很是好的。npm
首先,咱們來看官方文檔對引入sourcemaps的說明。Sentry容許咱們經過三種方式使用sourcemaps,releases API, sentry-cli, sentry-webpack-plugin。考慮到項目構建過程當中就一併提交sourcemaps,我我的僅僅實踐了最後一種。json
// 來自官方的步驟
1. Start by creating a new authentication token under **[Account] > API**.
2. Ensure you have project:write selected under scopes.
3. Install @sentry/webpack-plugin using npm
4. Create .sentryclirc file with necessary config (see Sentry Webpack Plugin docs below)
5. Update your webpack.config.json
複製代碼
下面咱們來實踐一下:
前兩步,很是簡單,略過略過。
對於第三步, 我我的發現僅僅install @sentry/webpack-plugin彷佛仍是不夠的,還須要install @sentry/cli,不知道是我我的問題,敬請指出。
第四步,多是我對這種配置格式不太熟悉,折騰最久就是這一步了。給出官方配置說明,下面是個人基礎配置(其實就是將如defaults.url,auth.token等拆分,寫入配置文件便可),在項目根目錄下:
// .sentryclirc
[defaults]
url = https://sentry.io/
<!-- 此處能夠從你的sentry.io的全路徑看出,如:https://sentry.io/此處是你的org/此處是你的project/ -->
org =
project =
[auth]
token = 此處就是你第一步第二步建立的token
複製代碼
第五步,更新個人webpack配置,配置個人監控模塊
此處參考了一位兄弟的文章,他用了另一個Plugin實現,請圍觀。
此處聲明,這位大兄弟文中的方法都很好,可是對於須要截取7位數的參數做爲版本號的問題,我我的實踐是截取後Raven.js沒法傳遞正確版本號了,反而不截取可以傳遞正確版本號!經過查看Raven.js的post,發現release很是長,不止7位。
下面這個步驟的urlPrefix屬性特別關鍵,這個是給上傳的文件添加前綴的,由於sentry除了根據版本號,還要匹配特定版本號中的路徑。這個屬性的默認值是~/,而~是僅僅是去掉了網址前面的協議和域名,即拼接起來的map資源路徑是http://host/static/js/app.js.map。可是若是像個人站點,多了一級路徑,那麼就須要配置這個屬性了,不然上傳到Sentry的maps就沒法訪問到了。
// webpack.prod.conf.js
const SentryPlugin = require('@sentry/webpack-plugin');
plugins: [
new SentryPlugin({
include: './dist',
release: process.env.RELEASE_VERSION,
configFile: 'sentry.properties',
urlPrefix: '~/TechPage/', // 若是不須要也能夠不傳這個參
}),
]
複製代碼
就是下面這個步驟,不該該截取
// prod.env.js
let gitSha = require('child_process').execSync('git rev-parse HEAD').toString().trim()
// process.env.RELEASE_VERSION = gitSha.substr(2, 9) 不該截取
process.env.RELEASE_VERSION = gitSha
module.exports = {
RELEASE_VERSION: `"${gitSha}"`,
NODE_ENV: '"production"'
}
複製代碼
// main.js
import Raven from 'raven-js'
import RavenVue from 'raven-js/plugins/vue'
Raven
.config('https://<key>@sentry.io/<project>', {
release: process.env.RELEASE_VERSION,
debug: true
})
.addPlugin(RavenVue, Vue)
.install()
複製代碼
因爲sentry是經過release版本匹配一致的方式,使用特定版本的sourcemaps去定位錯誤的,所以咱們須要在項目構建的時候生成一個特定的版本號,將這個版本號賦值給Raven.js以及SentryPlugin,這樣就能造成對應關係。固然你也能夠經過另外的方式生成相應的release版本號,這都是能夠的,只要是可以惟一對應就能夠了。即便你沒有造成對應關係,但只要你發佈了source maps,Sentry默認是會根據js文件中的sourceMappingURL去找到map文件,而後定位錯誤的。
Raven.js的配置官方文檔也是有詳細說明的,詳情點擊。此處我僅僅配置了release以及debug,設置debug爲true的話,Raven.js會將一些debug信息輸出到控制檯。
至此,你觸發項目中的錯誤,就能得到下面的效果,錯誤信息也成功定位了,很是的清楚。
此處是參照上面提到那位兄弟的作法了,不過他提到了要在上傳sourcemaps到sentry以後刪除,不讓終端用戶接觸,這是對的 。可是我這邊刪除以後,用戶端發生錯誤以後,沒有辦法把定位後的錯誤信息返回了,返回的錯誤信息都是編譯打包以後的代碼的,可讀性通常。若是發現我哪裏配置錯誤,敬請指出。
通過踩坑,正是因爲沒有正確配置urlPrefix(@sentry/webpack-plugin中的屬性,webpack-sentry-plugin中是配置filenameTransform方法),因此當我不發佈source maps時,沒法定位錯誤。
const SentryPlugin = require('webpack-sentry-plugin');
plugins: [
new SentryPlugin(Object.assign({
release: process.env.RELEASE_VERSION,
deleteAfterCompile: true,
suppressErrors: true,
/** filenameTransform: function (filename) { var pub = config.build.assetsPublicPath if (/^\/\//.test(pub)) pub = 'http:' + pub var urlObj = require('url').parse(pub) return '~' + urlObj.pathname.replace(/\/+$/, '') + '/' + filename } */
filenameTransform: function (filename) {
return '~/TechPage/' + filename
},
}, require('../sentry.conf.js'))),
]
複製代碼
// sentry.conf.js(位於根目錄)
module.exports = {
// 此處能夠從你的sentry.io的全路徑看出,如:https://sentry.io/此處是你的org/此處是你的project
organisation: '',
project: '',
apiKey: ''
}
複製代碼
這種配置,我獲得的報錯信息是這樣的,以下圖:
通過配置,可以在不發佈source maps的狀況下,獲得完整的錯誤定位!
若是想將Sentry部署到本身的服務器,Sentry官方也有詳細的文檔,各位請移步。
各位看官若是發現文中個人錯處,請必定不要嫌麻煩,請開展花式吐槽!謝謝!
也歡迎上個人Demo網站點擊建立時間一欄觸發錯誤看看Sentry的效果,謝謝!
此處感謝 @時間是海 的提醒,參考了sentry社區裏的問題才注意到urlPrefix這個問題。附上社區的兩篇帖子: