Sentry接入及上报

Sentry接入及上报

Installation
1
2
3
4
5
# Using yarn
$ yarn add @sentry/browser

# Using npm
$ npm install @sentry/browser

Vue项目需要安装以下包

1
2
3
4
5
# Using yarn
yarn add @sentry/integrations

# Using npm
npm install @sentry/integrations

创建

Sentry网站创建对应项目 AKC Sentry

Vue项目接入Sentry

以下代码添加到 main.js 里面

1
2
3
4
5
6
7
8
9
10
import Vue from 'vue'
import * as Sentry from '@sentry/browser';
import * as Integrations from '@sentry/integrations';

// dsn是创建项目自动生成的
Sentry.init({
dsn: 'https://************@sentry.io/********',
release: 'release@0.0.1',
integrations: [new Integrations.Vue({Vue, attachProps: true})],
});

React项目接入Sentry

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import ReactDOM from 'react-dom';
import * as Sentry from '@sentry/browser';
import App from 'src/App';

Sentry.init({
dsn: "https://*******@sentry.io/****",
release: 'release@0.0.1'
});

ReactDOM.render(<App />, document.getElementById('root'));

DSN(客户端秘钥) Sentry控制台建立项目之后,项目->设置->DSN秘钥

★使用 @sentry/webpack-plugin 插件上传sourceMap并写脚本删除sourceMap文件

Installation
Using yarn
1
2
3
4
5
# Using yarn
$ yarn add @sentry/webpack-plugin

# Using npm
$ npm install @sentry/webpack-plugin

Vue项目中用法

vue.config.js

Using yarn
1
2
3
4
5
# Using yarn
$ yarn add fs-extra --dev

# Using npm
$ npm install fs-extra --save-dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
const SentryCliPlugin = require('@sentry/webpack-plugin')
const fs = require('fs-extra')

module.exports = {
// 选项...
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
config.plugins.push(
new SentryCliPlugin({
baseSentryURL: 'https://sentry.aikucun.com/api/0',
release: process.env.VUE_APP_RELEASE,
include: './dist/js',
urlPrefix: '~/aftersale/js',
ignore: /.js$/,
configFile: '.sentryclirc'
}),
// build完成之后删除sourceMap的插件
{
apply: (compiler) => {
compiler.plugin('done', compilation => {
console.log('build完成')
const sourceMapFileDir = './dist/js'
fs.pathExists(sourceMapFileDir)
.then(exists => {
if (exists) {
fs.readdir(sourceMapFileDir, 'utf8', (err, files) => {
if (err) {
return console.log(err)
}
files.forEach(item => {
if (/.map$/.test(item)) {
fs.remove(sourceMapFileDir + '/' + item).then(() => {
console.log(item + ' Remove success!')
}).catch(err => {
console.log(err)
})
}
})
})
} else {
console.log('不存在此目录!')
}
}
)
})
}
}
)
} else {
// 为开发环境修改配置...
}
}

根目录的 .sentryclirc 文件设置,token可以保存在服务器的sentry-cli设置上面

1
2
3
4
5
6
7
8
[defaults]
url=https://sentry.aikucun.com/
http.verify_ssl = false
org=aikucun
project=*********

[auth]
token=***********************

React项目用法

Using yarn
1
2
3
4
5
Using yarn
$ yarn add fs-extra --dev

# Using npm
$ npm install fs-extra --save-dev

对应的 webpack.config.js文件

1
2
3
4
5
6
7
8
9
10
11
const SentryCliPlugin = require('@sentry/webpack-plugin');

// 对应的plugins 数组下面加上以下插件

new SentryCliPlugin({
baseSentryURL: 'https://sentry.aikucun.com/api/0',
release: 'test@0.0.13',
include: './build',
urlPrefix: process.env.REACT_APP_ENV === 'prod' ? '~/akim/' : '~//', // 根据不同环境 更改不同地址前缀
configFile: '.sentryclirc'
})

根目录 .sentryclirc 文件内容

1
2
3
4
5
6
7
8
[defaults]
url=https://sentry.aikucun.com/
http.verify_ssl = false
org=aikucun
project=akim

[auth]
token=*********************

在 script/build.js 中的 measureFileSizesBeforeBuild 回调中添加删除sourceMap文件方法(不同版本项目位置和方法可能不同)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 删除上传之后的sourceMap文件
const sourceMapFileDir = './build/static/js'
fs.pathExists(sourceMapFileDir)
.then(exists => {
if(exists) {
fs.readdir(sourceMapFileDir, 'utf8', (err, files) => {
if(err){
return console.log(err)
}
files.forEach(item => {
if(/.map$/.test(item)) {
fs.remove(sourceMapFileDir + '/' + item).then(() => {
console.log(`${item} Remove success!`)
}).catch(err => {
console.log(err)
})
}
})
})
} else {
console.log(chalk.red('不存在此目录!'))
}
}
)

使用webpack-sentry-plugin插件上传及删除sourceMap

重点, 后来发现使用此插件会出现部分map文件没有上传到sentry服务器的问题,导致报错未定位到代码行数,建议项目不要使用此插件

使用 webpack-sentry-plugin这个插件可以做到上传并删除SourceMap文件。

Installation
Using yarn
1
2
3
4
5
# Using yarn
$ yarn add webpack-sentry-plugin

# Using npm
$ npm install webpack-sentry-plugin
Usage
  1. Require webpack-sentry-plugin:

    const SentryPlugin = require('webpack-sentry-plugin');

  2. Add to webpack config:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var config = {
    plugins: [
    new SentryPlugin({
    // Sentry options are required
    organization: 'your-organization-name',
    project: 'your-project-name',
    apiKey: 'your-api-keys',

    // Release version name/hash is required
    release: 'your-release-version'
    })
    ]
    }

Vue项目插件用法

创建vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var SentryPlugin = require('webpack-sentry-plugin');
// vue.config.js
module.exports = {
// 选项...
configureWebpack: config => {
// 可自己根据打包命令设置
config.plugins.push(
new SentryPlugin({
// 注意此处为全小写
organization: 'futuredawn',
// 对应的项目名字
project: 'vue01',
// Sentry 设置里面生成的 Api keys
apiKey: 'b2d7c7c66b2c4e0d9086f0abe6e535722b9b1b5e417c45eabeaae119b13216e8',

// Release version name/hash is required
release: 'test@0.0.1',
// 设置dist目录上传文件
include: /\.js.map$/,
// 上传完毕之后删除source map文件
deleteAfterCompile: true
})
)
}
}

可以根据运行环境判断是否使用SentryPlugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var SentryPlugin = require('webpack-sentry-plugin');
// vue.config.js
module.exports = {
// 选项...
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
config.plugins.push(
new SentryPlugin({
organization: process.env.VUE_APP_ORGANIZATION,
project: process.env.VUE_APP_PROJECT,
apiKey: process.env.VUE_APP_APIKEY,

// Release version name/hash is required
release: process.env.VUE_APP_RELEASE,
// 设置dist目录上传文件
include: /\.js.map$/,
// 上传完毕之后删除source map文件
deleteAfterCompile: true
})
)
} else {
// 为开发环境修改配置...
}

}
}

.env.production 环境变量设置

1
2
3
4
VUE_APP_ORGANIZATION = *******
VUE_APP_PROJECT = vue01
VUE_APP_APIKEY = ******************
VUE_APP_RELEASE = vue01@0.0.4

上传到Sentry控制台的map文件

image-20200324145030082

本地打包编译之后的目录,可以看到map文件已经被删除

image-20200324145124604

React项目插件用法

创建项目之后 yarn eject 把配置暴露出来

打开config/webpack.config.js

添加 const SentryPlugin = require('webpack-sentry-plugin');

在文件510行(HtmlWebpackPlugin上面)添加plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
new SentryPlugin({
// 注意此处为全小写
organization: '*****',
// 对应的项目名字
project: 'react01',
// Sentry 设置里面生成的 Api keys
apiKey: '******',

// Release version name/hash is required
release: 'react@0.0.1',
// 设置dist目录上传文件
include: /\.map$/,
// 上传完毕之后删除source map文件
deleteAfterCompile: true,
// 支持复写同文件
suppressConflictError: true
}),

注意事项

如果是使用私有sentry 需要修改下baseUrl

1
baseSentryURL`: Fully qualified URL of Sentry instance. Defaults to `https://sentry.io/api/0` for sentry.io. If self-hosting, set this to the fully qualified domain name of your instance, e.g. `https://mysentryinstance.com/api/0

init Sentry的地方和插件设置的地方的release要设置一致,并且两个地方都要有release设置字段,才可以保证map文件正常上传。

额外上报信息

某些时候我们需要额外一些信息用于代码错误定位,例如时间、用户ID、单号等信息,这时候我们需要额外设置以便于Sentry报错时可以上传到Sentry服务器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import * as Sentry from '@sentry/browser'

// configureScope 全局设置上报信息
Sentry.configureScope(scope => {
const userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
// setUser 方法中的四项是固定的
scope.setUser({
id: userInfo.staffCode,
username: userInfo.username,
email: userInfo.email,
ip_address: userInfo.akid
})
// 打tag标志以便于可以直接点击查询有关此tag的相关错误
scope.setTag('staffCode', userInfo.staffCode)
scope.setTag('akid', userInfo.akid)
scope.setTag('groupId', userInfo.groupId)
// 设置错误级别
scope.setLevel('waring')
// 设置额外信息 此信息可以携带大量数据 缺点是无法直接被检索到
scope.setExtra('serverUserInfo', JSON.stringify(userInfo))
})

withScope 是局部设置,可以使用此方法覆盖全局设置

必须先设置才能在上报的错误中带上额外信息

掘金参考资料

参考资料

问题解决

ssl证书校验失败

如果报ssl证书校验失败问题,需要在请求头设置不校验证书 rejectUnauthorized: false

因为使用的两个webpack-sentry插件不同,对应不同的设置:

webpack-sentry-plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new SentryPlugin({
baseSentryURL: 'https://***/api/0',
organization: process.env.VUE_APP_ORGANIZATION,
project: process.env.VUE_APP_PROJECT,
apiKey: process.env.VUE_APP_APIKEY,

// Release version name/hash is required
release: process.env.VUE_APP_RELEASE,
// 设置dist目录上传文件
include: /\.js.map$/,
// 上传完毕之后删除source map文件
deleteAfterCompile: true,
uploadFileRequestOptions: {
rejectUnauthorized: false
},
createReleaseRequestOptions: {
rejectUnauthorized: false
}
})

@sentry/webpack-plugin

1
2
3
4
5
6
7
new SentryCliPlugin({
baseSentryURL: 'https://***/api/0',
release: 'test@0.0.6',
include: './build',
urlPrefix: 'https://***/',
configFile: '.sentryclirc'
})

根目录文件 .sentryclirc

1
2
3
4
5
6
7
url=https://***/
http.verify_ssl = false
org=**
project=**

[auth]
token=***

http.verify_ssl = false

409

如果报409错误 Sentry Plugin: StatusCodeError: 409 - "{\"detail\": \"A file matching this name already exists for the given release\"}" 阻断打包过程,需要加一个配置项以便打包过程不会被阻断

suppressConflictError: true,

其余功能

Sentry还可以将Github、Gitlab等接入工作流,甚至可以定位到具体出问题的提交commit上面,并且还有可以自动提出issues等功能。

参考资料

掘金参考文档

webpack-sentry-plugin

Author: XavierShi
Link: https://blog.xaviershi.com/2020/03/23/Sentry接入及上报/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.