Sentry 接入手册
Sentry 是一个开源的异常监控工具,支持前后端多个框架。
本文主要介绍如何接入前端的 Vue 及 Uni-app 项目。
更多用户可以查阅官方文档。
# 准备工作
# 创建项目
首先需要在 Sentry 后台创建一个项目,platform 一律选取“VUE”。其余参数保留默认。
# 获取项目信息
创建成功之后,需要获取项目的几项参数。
建议由项目管理员操作。
- 获取组织名称
点击左上角头像,选择 Organization Settings,查看 Organization Slug - 获取项目名称
通过项目列表卡片的齿轮,或者项目页面的右上角齿轮进入 Project Settings 页面,查看 Name - 获取项目 DSN(上报地址)
同样在 Project Settings 页面,点击右侧的“Client Keys (DSN)”查看 DSN - 获取用户 Token(用于上传 Sourcemap) 点击左上角头像,选择 User auth tokens,点击左上角 Create New Token,勾选如下图中的权限
第 4 步的 token 绑定到当前操作人员的帐号,当该帐号发生变动时(禁用或权限变动),需要重新生成 token。
# Uni-app H5 接入步骤
以下内容适用于使用 uni-app 框架的 H5 应用。
# H5 初始化配置
首先安装依赖:
npm install --save @sentry/vue @sentry/tracing --registry https://npm.devops.cndinfo.com/
复制代码
文档所使用的版本号如下:
"dependencies": {
"@sentry/tracing": "7.69.0",
"@sentry/vue": "7.69.0",
},
复制代码
在 main.js
中初始化:
import * as Sentry from "@sentry/vue";
Sentry.init({
Vue,
dsn: "https://XXXXXXXXXX@mydsn.com/4", // 上文提到的项目 DSN 配置
integrations: [new Sentry.BrowserTracing({})], // 配置额外的 sdk 集成
release: process.env.SENTRY_RELEASE, // 项目的版本号,方便区分报错对应的版本;手动写死或者使用本地环境变量
environment: "development", // 环境变量,建议和项目的环境变量保持一致(例如 development、testing、uat、production)
attachStacktrace: true, // 是否开启堆栈跟踪(默认开),开启后跟着消息一起收集
beforeSend: (event, hint) => {
// 发送报错前的额外操作
return event;
},
tracesSampleRate: 1.0, // 随机事件发送给 sentry 的几率
});
// 上报自定义 Tag,见下文的 setTag()
// 上报用户信息,见下文的 setUser()
复制代码
release
: 版本号的命名可以和项目package.json
中的version
保持一致。
如果你的项目是将多个子应用上报到同一个 Sentry 项目,可以添加子应用前缀,便于区分。例如subapp@0.0.1
。
# 验证错误是否上报成功
在 Web 类型的项目中,Sentry 会自动上报错误信息。
我们可以手动添加几行会报错的代码。
const a = {};
console.log(a.b.c);
复制代码
运行之后,可以在后台查看到报错已被采集。
# 上传 Source Map
按上述步骤采集的报错会有个问题,无法定位到报错代码的具体位置(代码行号)。
因此必须要上传 Source Map 到 Sentry,才能将编译部署后的代码和原始代码进行映射,从而在 Sentry 中显示报错代码的具体位置。
Sentry 有两种上传方法,通过 @sentry/cli
手动上传和 @sentry/webpack-plugin
自动上传。
Web 类的项目建议使用后者。
# Source Map 上传步骤
# 自动上传
Node 版本必须 ≥14。如果 Node 仍使用较早的版本,可以采用手动上传的方式(见下文)。
首先安装依赖:
npm install --save-dev @sentry/webpack-plugin --registry https://npm.devops.cndinfo.com/
复制代码
文档所使用的版本号如下:
"devDependencies": {
"@sentry/webpack-plugin": "2.7.1",
},
复制代码
在 vue.config.js
中添加:
const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");
module.exports = {
configureWebpack: (config) => {
Object.assign(config, {
plugins: [
...config.plugins,
sentryWebpackPlugin({
url: "https://sentry.devops.cndinfo.com/", // Sentry 后台地址
release: process.env.SENTRY_RELEASE, // 和 `Sentry.init` 中的保持一致
include: path.join(process.cwd(), "/dist"), // 需要上传到 sentry 服务器的资源目录
ignore: ["node_modules", "vue.config.js"], // 忽略文件目录,如果在 inlcude 中已经定义了具体路径,这个参数可以不加
authToken: process.env.SENTRY_AUTH_TOKEN, // 上文中的 User auth tokens
org: process.env.SENTRY_ORG, // 上文中的组织名称
project: process.env.SENTRY_PROJECT, // 上文中的项目名称
urlPrefix: "~/static/js", // 上传资源的路径前缀,uni-app build 的路径通常是 `/static/js`, 如有变化自行更改
}),
],
// 不加这个uni-app不会生成soucemap文件
devtool: "source-map",
});
},
};
复制代码
authToken
, org
和 project
均为获取项目信息中得到的信息。
打包后 Source Map 会自动上传至 Sentry。
# 执行打包命令(具体命令以各自项目为准)
npm run build
复制代码
# 手动上传
首先安装依赖:
npm install -D @sentry/cli --registry https://npm.devops.cndinfo.com/
# 如果下载超时,可以使用国内源
npm install -D @sentry/cli --registry https://npm.devops.cndinfo.com/ --sentrycli_cdnurl=https://cdn.npm.taobao.org/dist/sentry-cli
# 也可以直接设置成国内地址
npm config set sentrycli_cdnurl https://cdn.npm.taobao.org/dist/sentry-cli
复制代码
文档所使用的版本号如下:
"devDependencies": {
"@sentry/cli": "^2.20.7",
},
复制代码
在 vue.config.js
中添加一行 devtool
配置,允许打包 Source Map:
module.exports = {
configureWebpack: {
// 不加这个uni-app不会生成soucemap文件
devtool: "source-map"
}
}
复制代码
在根目录添加配置文件 .sentryclirc
:
[auth]
token=和自动上传相同的token
[defaults]
url=https://sentry.devops.cndinfo.com/
org=sentry
project=项目名称
复制代码
每个参数的值都和自动上传相同。
在 package.json
添加自定义指令:
"sentry": "sentry-cli releases new 0.0.1 && sentry-cli releases files 0.0.1 upload-sourcemaps ./dist/build/h5/static/js --url-prefix '~/static/js'",
"build": "npm run build:h5 && npm run sentry && rm -rf ./dist/build/h5/static/js/*.map",
复制代码
0.0.1
是版本号,和Sentry.init
中保持一致,每次变化需要手动修改./dist/build/h5/static/js
为打包后需要上传的地址~/static/js
为线上部署后的 js 的地址 两者根据实际情况进行调整。
uni-app H5 项目的测试环境使用的是单独的命令,因此还需要给测试环境配置单独的命令:
"sentry-test": "sentry-cli releases new 0.0.1 && sentry-cli releases files 0.0.1 upload-sourcemaps ./dist/dev/h5/static/js --url-prefix '~/static/js'",
"build-test": "npm run build:h5-test && npm run sentry-test && rm -rf ./dist/dev/h5/static/js/*.map",
复制代码
打包后 Source Map 会自动上传至 Sentry。
# 执行打包命令(具体命令以各自项目为准)
npm run build
复制代码
# 删除生产环境的 Source Map 文件
我们的目的仅仅是把 map 文件上传到 Sentry。生产环境部署本身并不需要 map 文件。
而且 map 上传到生产环境会导致包体积变大,此外 map 中包含 sentry 的 token 信息,有泄漏风险。
因此建议删除。
对于 uni-app H5 项目,可以通过调整 package.json
中的 build:h5
命令来删除。
// 在结尾增加 rm -rf ./dist/build/h5/static/js/*.map"
"build": "npm run build:h5 && rm -rf ./dist/build/h5/static/js/*.map"
复制代码
如果是手动上传的 Source Map 文件,需要改为:
// 在结尾增加 rm -rf ./dist/build/h5/static/js/*.map"
"build": "npm run build:h5 && npm run sentry && rm -rf ./dist/build/h5/static/js/*.map"
复制代码
这样在 build 时就会自动删除 dist
目录下的 *.map
文件。
# 查看 Source Map 是否上传
在 Project Settings 页面,点击左侧 Source Maps
,根据 Release 版本号和上传时间判断你的 map 文件是否成功上传。
如果 map 文件已上传,可以在部署后的线上环境运行有报错的页面,此时在报错信息中可以看到报错代码的具体位置:
此处需要注意,必须在“线上环境”运行有报错的页面,在本地的 npm run serve
开发环境是无用的。因为 Sentry 中的 map 文件是 build 之后生成的,和 npm run serve
无关。
如果开发人员想在本地环境验证,可以使用下面的方式来模拟线上环境:
安装 http-server
工具,这个工具可以在本地运行 http 服务。
npm install http-server -g
复制代码
进入打包后的 dist/build/h5
目录,运行命令 http-server
,在 http-server
打开的页面中的运行报错的页面。
# Uni-app App 接入步骤
由于 Sentry 官方没有原生支持 uni-app 的 App 类型,因此不支持自动上报异常信息,只能通过 uni-app 的 onError
生命周期去捕获异常并且上报。
另外 uni.request
接口请求的 fail
并不会出现在 uni-app
的 onError
生命周期,也只能手动上报异常信息。
# App 初始化配置
安装 sentry-uniapp
库:
npm install sentry-uniapp -S
复制代码
在 main.js
中初始化:
import * as Sentry from "sentry-uniapp";
Sentry.init({
// 初始化代码同 H5, 但需要去掉 integrations
dsn: "https://XXXXXXXXXX@mydsn.com/4", // 上文提到的项目 DSN 配置
release: process.env.SENTRY_RELEASE, // 项目的版本号,方便区分报错对应的版本;手动写死或者使用本地环境变量
environment: "development", // 环境变量,建议和项目的环境变量保持一致(例如 development、testing、uat、production)
attachStacktrace: true, // 是否开启堆栈跟踪(默认开),开启后跟着消息一起收集
beforeSend: (event, hint) => {
// 发送报错前的额外操作
return event;
},
tracesSampleRate: 1.0, // 随机事件发送给 sentry 的几率
});
// 上报自定义 Tag,见下文的 setTag()
// 上报用户信息,见下文的 setUser()
复制代码
初始化参数和 H5 一样,参考H5 初始化配置。
在 App.vue
的 onError
生命周期中上报捕获到的错误信息:
注意:要在捕获错误之前上报用户信息。
import * as Sentry from "sentry-uniapp";
export default {
onError: function (err) {
// #ifdef APP-PLUS
const userData = uni.getStorageSync("userInfo");
if (userData) {
Sentry.setUser({
id: userData.usercode,
username: userData.username,
email: userData.email,
ip_address: "{{auto}}",
});
}
Sentry.captureException(err);
// #endif
},
};
复制代码
# Sentry API 介绍
此处介绍一些常用的 API ,更多 API 可自行查阅官方文档。
# setTag()
给报错事件设置全局标签,方便对报错进行自定义分类。
注意:页面刷新后数据会丢失。如果想要对每个报错事件都进行设置,需要放在 main.js
中。
// 一次只能上传一个 tag,若要上传多个 tag,可以添加多行
Sentry.setTag("test", "test-name");
Sentry.setTag("test_user", "test-user");
Sentry.setTag("test_id", "test123");
复制代码
根据官方的建议,tag 的名称建议使用下划线。如果使用其他形式,需参考下面的要求。
Tag keys have a maximum length of 32 characters and can contain only letters (a-zA-Z), numbers (0-9), underscores (_), periods (.), colons (:), and dashes (-).
标签效果如下,browser
, device
等均为 Sentry 自带的标签,test
则是我们自定义的标签。
# setUser()
- 官方文档: Identify Users
设置用户的信息,方便查询该报错是由哪个用户触发。
注意:页面刷新后数据会丢失。如果想要对每个报错事件都进行设置,需要放在 main.js
中。
可以设置的用户信息共 4 个,均非必传字段,但至少需要上传一个字段。
id
: 用户 ID,系统内部的用户唯一标识符username
: 用户名称,例如用户姓名或者昵称,无需唯一email
: 用户邮箱ip_address
: 用户的 IP 地址,建议设置为。Sentry 会自动获取 IP。如果用户未经身份验证,Sentry 将使用 IP 地址作为用户的唯一标识符
Sentry.setUser({
id: "12345",
username: "王明",
email: "wangming@test.com",
ip_address: "{{auto}}",
});
复制代码
上传其他字段是不会被 Sentry 采集的。因此有其他字段需求可以使用 setTag
。
# 调用时机
由于页面刷新后原先的数据会丢失,所以不能只在登录成功时调用。可以在 main.js
和登录获取用户信息两个位置都进行上传。
- 登录获取用户信息后调用
login.vue
:
login(){
// 登录成功并获取到用户信息后
const userData = { id: "123", username: "test" }
Sentry.setUser(userData);
}
复制代码
如果项目同时有使用行为分析 SDK,可以和行为分析的profileSet调用时机保持一致。
main.js
中调用
// Sentry 初始化成功后调用
// 从缓存中取用户信息,有缓存才调用
const userData = uni.getStorageSync("userInfo");
if (userData) {
Sentry.setUser({
id: userData.usercode,
username: userData.username,
email: userData.email,
ip_address: "{{auto}}",
});
}
复制代码
# captureException(exception)
手动上报错误。传入一个 exception
对象或者类对象。
Sentry 无法自动捕获 catch
中的异常信息,因此 catch
中的异常必须要手动上传。
try {
const a = {};
console.log(a.b.c);
} catch (error) {
Sentry.captureException(error);
}
复制代码
# 进阶用法
# 不同子应用使用同一个项目
如果你的项目中包含多个子应用,且所有子应用都想上报到同一个 Sentry 项目,可以使用下面的方式来区分:
通过自定义的 tag 和 release 版本号共同自定义。
main.js
:
Sentry.init({
// ...
release: process.env.SENTRY_RELEASE, // 使用带子应用名称的版本号,例如 `sub_app_name@1.0.0`
// ...
});
// 初始化之后 通过自定义的 sub_app_name 填写对应的子应用名称
Sentry.setTag("sub_app_name", "应用名称");
复制代码
# 在统一接口请求中上报异常
// App
import * as Sentry from "sentry-uniapp";
// Web (H5)
import * as Sentry from "@sentry/vue";
uni.request({
success:(res)=>{
if(res.code !== 200) {
Sentry.captureMessage("自定义上报的错误信息");
}
}
fail: (err) => {
Sentry.captureException(err);
},
});
复制代码
# 注意事项
# Sentry 的不足点
# 无法自动捕获部分异常
Sentry 无法捕获 try/catch
, ajax 请求的失败回调(例如 uni.request
中的 fail
,以及 axios
中的 catch
)等异常,在这些场景中必须要使用 captureException 进行上报。
try {
const a = {};
console.log(a.b.c);
} catch (error) {
// 如果 catch 没有暴露错误出来 是不会被捕获的,sentry 后台不可查到
// 需要自己手动暴露报错,或者通过 API 手动上报
Sentry.captureException(error);
}
复制代码
# App 不支持 Source Map
Sentry 暂不支持 uni-app App 的 Source Map。因此无法定位到报错代码的具体位置。
# 常见问题
# 上传 Source Map 报错 401
检查 url
和 token
是否一致,token
权限是否给够,创建 Token 时是否勾选了 project:write
。
# 报错 project not found
检查配置中的组织名称和项目名称是否和 Sentry 后台一致。
# Source Map 上传成功,但映射失败
后台可以看到上传的 map 信息,但无法看到报错的具体行号。
检查上传的路径是否正确。