十分鐘快速構(gòu)建錯(cuò)誤監(jiān)控系統(tǒng)
前言
作為程序員,每次開(kāi)發(fā)完自測(cè)充分的時(shí)候,但還是會(huì)有線上異常情況。如何快速發(fā)現(xiàn) 或者提前監(jiān)控到這些異常的出現(xiàn)呢,是不是需要一個(gè)錯(cuò)誤監(jiān)控系統(tǒng)?
調(diào)研
一個(gè)錯(cuò)誤監(jiān)控系統(tǒng)應(yīng)該做下面這些事情:
當(dāng)錯(cuò)誤發(fā)生的時(shí)候我們更需要一些輔助信息來(lái)幫我們更快的定位錯(cuò)誤,比如 JS錯(cuò)誤類型、 JS錯(cuò)誤信息、JS錯(cuò)誤堆棧、JS錯(cuò)誤發(fā)生的位置以及相關(guān)位置的代碼;JS錯(cuò)誤發(fā)生的幾率、瀏覽器的類型,版本號(hào),設(shè)備機(jī)型等等輔助信息。
技術(shù)方案
- 自研。
- fundebug、sentry、bat的...
- 由于我們前端不到10人沒(méi)有太多的精力搞基建自研,然后付費(fèi)的一般公司都不會(huì)愿意花錢(大家懂的),所以選了國(guó)外比較成熟的方案 sentry[1]。
sentry
- 有免費(fèi)版的付費(fèi)版,免費(fèi)版。付費(fèi)版和免費(fèi)版其實(shí)差不多,免費(fèi)夠我們用了,付費(fèi)的就是他啥都幫你弄好,你只需要裝sdk 就行了。
- sentry 是一個(gè)實(shí)時(shí)事件日志記錄和聚合平臺(tái)。它專門用于監(jiān)視錯(cuò)誤和提取執(zhí)行適當(dāng)?shù)氖潞蟛僮魉璧乃行畔? 而無(wú)需使用標(biāo)準(zhǔn)用戶反饋循環(huán)的任何麻煩。
- Sentry 是一個(gè)日志平臺(tái),分為客戶端和服務(wù)端,客戶端(目前客戶端有Python, PHP,C#, Ruby等多種語(yǔ)言)就嵌入在你的應(yīng)用程序中間,程序出現(xiàn)異常就向服務(wù)端發(fā)送消息,服務(wù)端將消息記錄到數(shù)據(jù)庫(kù)中并提供一個(gè)web節(jié)目方便查看。Sentry由python編寫,源碼開(kāi)放,性能卓越,易于擴(kuò)展,目前著名的用戶有Disqus, Path, mozilla, Pinterest等。
有哪些功能
項(xiàng)目
配置多個(gè)項(xiàng)目如下圖:
上報(bào)過(guò)來(lái)的問(wèn)題
這個(gè)就是你的應(yīng)用所有的異常:
- 問(wèn)題總數(shù)是指當(dāng)前不同的問(wèn)題,同一個(gè)問(wèn)題出現(xiàn)的次數(shù)會(huì)在末尾那個(gè)數(shù)字體現(xiàn)。
- 然后管理員可以將這個(gè)問(wèn)題勾選后分配給其它成員。
- 有的問(wèn)題可以將其 ignore 或者 resolve, 之后就不會(huì)出現(xiàn)在你的列表里面。
- 還有自定義搜索:最多出現(xiàn)、最后出現(xiàn)時(shí)間、首頁(yè)出現(xiàn)等等。
- 當(dāng)前錯(cuò)誤所發(fā)生的 url。
- 瀏覽器的名字、版本、ua。
- 用戶的設(shè)備信息例如 XiaoMi MI MAX 3 android10.0 ipxxx。
- 用戶的基礎(chǔ)信息例如 name 、userid等更多業(yè)務(wù)相關(guān)的需要自己配置。
- 如果頁(yè)面有 xhr 信息會(huì)將請(qǐng)求信息響應(yīng)狀態(tài)碼顯示出來(lái)。
- 畫重點(diǎn)——當(dāng)碰到 js 錯(cuò)誤的時(shí)候會(huì)將調(diào)用棧、錯(cuò)誤類型、錯(cuò)誤發(fā)生文章打印出來(lái),如果配了sourcemap 可以將壓縮混淆前的代碼清楚的定位到哪一行。
可視化
- 內(nèi)置各種維度的數(shù)據(jù)可視化。
- 如果不滿意,它也提供了一些 api、類似 gitlab、 github會(huì)提供一樣的 api 進(jìn)行二次開(kāi)發(fā)。
報(bào)警
可以安裝一些額外的插件,比如 釘釘機(jī)器人、郵件提醒。
安裝與部署
安裝方式
- Python
- Docker 這里使用了 docker 安裝比較簡(jiǎn)單一點(diǎn)
環(huán)境
MIN_DOCKER_VERSION='1.10.0' //docker -v
MIN_COMPOSE_VERSION='1.17.0' //docker-compose -v
MIN_RAM=3072 # MB //你的內(nèi)存至少3G
一鍵生成
官方在19年的時(shí)候提供給了腳本一鍵生成的方式,倉(cāng)庫(kù)在這里onpremise[2]。
git clone https://github.com/getsentry/onpremise
cd onpremise
./install.sh
如果 docker 沒(méi)有配置國(guó)內(nèi)鏡像估計(jì)會(huì)很慢,提一下配置鏡像。
## 有的話就忽略
mkdir /etc/docker
## 沒(méi)有的直接執(zhí)行
vim /etc/docker/daemon.json
{
"registry-mirrors" : [
"https://mirror.ccs.tencentyun.com",
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
],
...
}
中間會(huì)有一次讓你配置管理員賬號(hào)密碼的過(guò)程 下載完畢以后執(zhí)行。
docker-comose up -d
配置完以后基本上就整個(gè)安裝過(guò)程應(yīng)該不會(huì)有啥大問(wèn)題,有問(wèn)題估計(jì)是網(wǎng)絡(luò)問(wèn)題。
手動(dòng)安裝
準(zhǔn)備
- Docker-ce
- Docker-compose
鏡像拉取
docker pull sentry
docker pull redis
docker pull postgres
啟動(dòng)
docker run -d --name sentry-redis --restart=always redis ###保證了,異常自動(dòng)拉起
docker run -d --name sentry-postgres -e POSTGRES_PASSWORD=secret -e POSTGRES_USER=sentry --restart=always postgres
生成唯一秘鑰
docker run --rm sentry config generate-secret-key
12345 ###打印出secret-keys,這里最好復(fù)制一下,接下來(lái)會(huì)用到
初始化以及創(chuàng)建Admin
docker run -it --rm -e SENTRY_SECRET_KEY='12345' --link sentry-postgres:postgres --link sentry-redis:redis sentry upgrade
啟動(dòng)三個(gè)服務(wù)
### web服務(wù)
docker run -d -p 9000:9000 --name my-sentry -e SENTRY_SECRET_KEY='12345' --link sentry-redis:redis --link sentry-postgres:postgres --restart=always sentry
### cropn 服務(wù)
docker run -d --name sentry-cron -e SENTRY_SECRET_KEY='12345' --link sentry-postgres:postgres --link sentry-redis:redis sentry run cron
### work 服務(wù)
docker run -d --name sentry-worker-1 -e SENTRY_SECRET_KEY='12345' --link sentry-postgres:postgres --link sentry-redis:redis sentry run worker
打開(kāi)
賬號(hào)密碼是剛才創(chuàng)建的管理員的密碼:
配置后臺(tái)地址、預(yù)警郵件地址、以及其他的一些功能:
前端接入
創(chuàng)建項(xiàng)目
這里我們選 javascript 項(xiàng)目名叫 myapp。
然后sentry后臺(tái)多了個(gè)項(xiàng)目, 然后在我們的前端項(xiàng)目里面像下面這樣引入:
// 腳本引入
<script
src="https://browser.sentry-cdn.com/5.22.3/bundle.tracing.min.js"
integrity="sha384-HfEJlGrJtFM0B01Wt4sGzTbxWqLMcMeGAXCbyQyB+iK9BhnDmNAtIGovhekIQOa2"
crossorigin="anonymous"
></script>
// npm
import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing';
Sentry.init({
dsn: 'xxxx',
integrations: [
new Integrations.BrowserTracing(),
],
tracesSampleRate: 1.0,
});
這樣整個(gè)流程就通了,可以用起來(lái)了。
Sourcemap 上傳
眾所周知,我們的線上代碼都是被壓縮混淆過(guò)的。所以就算拿到了錯(cuò)誤信息,只能靠猜了,所以要配合 souremap 精準(zhǔn)定位錯(cuò)誤信息。
準(zhǔn)備
- sentry 后臺(tái)配置 authToken 用于上傳sourcemap 使用,如下圖注意勾選。
- 下載 webpack 插件。
npm i @sentry/webpack-plugin -D
然后在根目錄下新建 .sentryclirc。
[defaults]
### 你的域名
defaults.url='http://localhost:9000'
### 組織團(tuán)隊(duì)名默認(rèn)是 sentry
org=sentry
### 項(xiàng)目名稱
project=myapp
### 步驟1創(chuàng)建的
[auth]
token=1234
配置插件。
const SentryWebpackPlugin = require('@sentry/webpack-plugin');
if (process.env.NODE_ENV !== 'development') { // 注意只在生成環(huán)境開(kāi)啟,不然npm run dev也會(huì)上傳
new SentryWebpackPlugin({
release: Date.now(), // 唯一標(biāo)識(shí),可以用其他的比如 hash
include: './build', // 要上傳的文件夾 有的叫 dist
ignoreFile: '.sentrycliignore', // 可不要
ignore: ['node_modules', 'config-overrides.js'],
configFile: '.sentryclirc' // 默認(rèn)同級(jí),如果不一樣需要用node path模塊處理一下
});
}
然后運(yùn)行 npm run build。
Creating an optimized production build...
> Found 10 release files
> Analyzing 10 sources
> Rewriting sources
> Adding source map references
> Bundled 10 files for upload
> Uploaded release files to Sentry
> File upload complete
恭喜你配置成功了。
其他常用api
主動(dòng)上報(bào)
Sentry.captureMessage('Hello, world!'); // 上報(bào)信息
Sentry.captureException(new Error('Good bye')); // 上報(bào)異常
Sentry.captureEvent({ // 上報(bào)事件
message: 'Manual',
stacktrace: [
// ...
],
});
配置用戶信息
Sentry.configureScope((scope) => {
scope.setUser({
...data.userInfo,
time: new Date().toLocaleString()
});
});
其他
- 郵件。
- 釘釘機(jī)器 可以去自己下載一些插件配置。