Sentry 是一个开源的实时错误追踪系统,可以帮助开发者实时监控并修复异常问题。
前端项目中上线代码都会经过编译、压缩等,当生产环境中出现异常时需要快速定位到具体报错的位置,快速修复,所以在上报异常时也需要将产生问题的 SourceMap 相关文件上传。
在具体使用时可以把项目部署在 Sentry 官方提供的系统内,也可以根据公司自身情况自己搭建 Sentry 系统。
当 Sentry 系统收集到错误信息时通过邮件等方式可以第一时间通知到开发人员。
通过 Docker 安装
通过 Python 安装
一般都是由运维人员去安装搭建,详细内容自行了解,所以具体内容略。
打开浏览器,对Sentry系统进行设置. 对时区设置是因为收集上报的错误信息的创建时间不是东八区的时间,看着不得劲。
需要同时按序引入 bundle.tracing.min.js、captureconsole.min.js 两个文件
<script src="./bundle.tracing.min.js">script>
<script src="./captureconsole.min.js">script>
try {
Sentry.init({
dsn: 'http://[email protected]:9000/3', // 密钥 DSN (数据源名称)告诉 SDK 将事件发送到何处,运维提供
integrations: [
new Sentry.Integrations.CaptureConsole({
levels: ['error'], // 设置日志记录级别
}),
],
release: '1.0.0', // 代码版本,通过版本号可以知道产生的bug是由哪个版本发布产生的
environment: 'production',
})
} catch (e) {
console.log('Sentry无法加载', e)
}
可以在浏览器中打开控制台尝试,然后在 Sentry 系统中就可以看到上报的错误信息。
Sentry.captureException('error test')
请先查看下面的踩坑记录再进行安装使用.
# Using yarn
yarn add @sentry/browser @sentry/tracing
# Using npm
npm install --save @sentry/browser @sentry/tracing
import * as Sentry from '@sentry/browser'
import { CaptureConsole as CaptureConsoleIntegration } from '@sentry/integrations'
import { SentryDSN, SentryLevels } from '@constants/Sentry'
import moment from 'moment'
/**
* 入口文件中 Sentry初始化
*/
initSentry = () => {
try {
Sentry.init({
dsn: SentryDSN,
integrations: [
new CaptureConsoleIntegration({
levels: SentryLevels,
}),
],
release: moment().format('YYYY-MM-DD HH:mm'),
environment: 'production',
})
} catch (e) {
console.log('Sentry无法加载', e)
}
}
const BasicOptions = {
dsn: '',
release: '',
environment: '',
integrations: [],
}
Sentry.init(BasicOptions)
{
...
environment: process.env.RUN_ENV,
release: `${process.env.RUN_ENV}@${moment().format('YYYY-MM-DD')}`,
}
通过上传 sourceMap,Sentry 支持通过源映射查看原始未转换编译压缩的代码,通过版本号快速定位异常代码。
Sentry 通过抓取堆栈跟踪中的 url 自动获取源代码。
window
npm install -g @sentry/cli // 全局安装时确保身份权限root
sentry-cli -V
其它
curl -sL https://sentry.io/get-cli/ | bash
获取 authToken:访问令牌。点击 Sentry 页面左下角头像,选择 API > Auth Tokens,点击右上角”Create New Token”按钮,勾选 project:write 权限,确认即可生成 Token。
登录 Sentry
使用 Sentry 官方提供系统: sentry-cli login
(默认情况下,sentry-cli 将连接到 sentry.io)
公司自己搭建 Sentry 系统:sentry-cli --url https://myserver.invalid/ login
(如:https://sentry.fescotech.com/)
登录成功后会提示创建了一个.sentrylrc 文件,根据提示路径,找到并打开。 【文件会创建在 C 盘 user 目录下,需要复制粘贴至项目根目录下.】
配置.sentrylrc 文件的相关信息: 补充url、org 和 project 信息到.sentrylrc。
[auth]
token=YOUR API TOKEN
[defaults]
url=服务器
org=组织
project=项目
创建 release:两种方式
sentry-cli releases new <版本号>
如:sentry-cli releases new dev@2021-01-01
By default the SDK will read from Application.productName and Application.version to create the release in the format $"{Application.productName}@{Application.version}".
sentry-cli releases -o sentry -p ssweb new dev@2021-01-01
sentry-cli releases -o 组织 -p 项目 delete <版本号>
上传 sourceMap:
sentry-cli releases files
sentry-cli releases files dev@2021-01-01 upload-sourcemaps --url-prefix '' './dist'
在windows的cmd下执行不灵,提示’./dist’系统找不到执行路径。
通过package.json中配置脚本执行可以成功上传。【windows系统问题】
删除sourceMap:
sentry-cli releases files 发布版本号 delete --all
至此 sentry-cli 的方式上传 sourceMap 完成。
npm install --save-dev @sentry/webpack-plugin
yarn add --dev @sentry/webpack-plugin
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
module.exports = {
...
devtool: 'source-map',
plugins: [
...
new SentryWebpackPlugin({
authToken: process.env.SENTRY_TOKEN,
org: "XXX",
project: 'XXX',
release: 'XXX',
include: "./dist",
ignore: ["node_modules", "webpack.config.js"],
urlPrefix: ''
}),
],
};
或者下面的代码(区别在于,Sentry 的配置信息 configFile)
plugins: [
...
new SentryWebpackPlugin({
release: '0.0.2',
include: './dist',
ignore: ['node_modules', 'webpack.config.js'],
// configFile: "sentry.properties", 这是用来替代第二步的.sentryclirc文件。
// 如果根项目有一个sentry.properties文件
configFile: 'sentry.properties',
urlPrefix: ''
}),
]
本人目前的使用方式如下,实测可用(前提是项目根目录下存在.sentryclirc文件)。
plugins: [
...
new SentryWebpackPlugin({
environment: process.env.RUN_ENV,
release: `${process.env.RUN_ENV}@${moment().format('YYYY-MM-DD')}`,
include: "./dist",
ignore: ["node_modules", "webpack.config.js", 'bundle.tracing.min.js', 'captureconsole.min.js'],
urlPrefix: `http://${process.env.RUN_ENV === 'PRO' ? '10.0.91.23' : '10.0.75.59'}/ssweb/`,
}),
]
urlPrefix为必须配置项。
需要注意的是urlPrefix的配置。urlPrefix指的是:线上对应的url资源的相对路径,而网上提供的配置:赋值为'~'
即可,~表示项目的根目录,如果对应的uri资源不在根目录,后面加上对应的文件路径即可。 urlPrefix的设置可以作为常量提取。
但是在实际测试时这样配置无效,即使release和sourceMap都生成和上传成功,报错信息依然无法映射到源代码。所以此处urlPrefix设置为项目的域名。然后在Sentry系统中对应的版本号下查看sourceMap文件显示的是全路径。如http://10.0.75.59/ssweb/index.3e29e915.css.map
project not found 的错误
。caused by: sentry reported an error: unknown error (http status: 413)
的错误信息,原因是要上传的map文件过大。解决方式 :需要修改nginx的配置文件信息:client_max_body_size的值需要往大了调,具体调多少看当前打包生成的map文件多大。调整后的值至少要比map文件大。x.x.x
的话 可以使用。环境@日期
的格式设置,会出现一个版本号下会有多个项目,本应该是A项目上传上来的sourceMap 也会上传在该版本的下的别的项目中。所以在设置版本号时格式可以修改为 环境_项目名@日期
的格式。基于ErrorBoundary组件,包裹在入口文件的结构外层。另外,Sentry 官网也提供了使用方式
1.定义组件
// ErrorBoundary.js
import React from 'react'
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
componentDidCatch(error, info) {
this.setState({ hasError: true })
console.error(error, info)
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>
}
return this.props.children
}
}
export default ErrorBoundary
2.使用:在页面的root节点之上的第一层节点外层包裹ErrorBoundary。
<ErrorBoundary>
<Example />
</ErrorBoundary>
3.本人使用的是自定义ErrorBoundary组件的方式,没有按官网提供的React使用方式。
1.模块安装
npm install --save @sentry/vue @sentry/tracing
2.入口文件引入并配置
// 入口文件
import Vue from "vue";
import * as Sentry from "@sentry/vue";
import { Integrations } from "@sentry/tracing";
// 也可以入口文件中
// import { CaptureConsole as CaptureConsoleIntegration } from '@sentry/integrations';
// 然后组件中console.error('错误信息'),这样也可以收集上报
Sentry.init({
Vue: Vue,
dsn: "xxx",
integrations: [new Integrations.BrowserTracing()],
// 或者
// integrations: [
// new CaptureConsoleIntegration({
// levels: ['error'],
// }),
// ],
// We recommend adjusting this value in production, or using tracesSampler
// for finer control
tracesSampleRate: 1.0,
});
3.组件中异常收集用 throw New Error(‘xxx’) 获取console.error(‘xxx’)
1.获取 bug 相关的上下文信息,如果只报错误信息,又没有相应数据的话,无法复现具体原因。封装 utils/collectionErrorInfo.js
import * as Sentry from '@sentry/browser';
/**
* 错误信息定制收集
* @param api:接口请求有误时上报相关信息。可以不传
* @param data:产生错误的上下文信息,如接口错误时的入参出参信息
* @param errorDesc:对该错误的文字描述
* 使用了 console.error 的方式上报
*/
const collectionErrorInfo = ({api = '',data = {},errDesc = '错误描述信息'}) => {
Sentry.setTag('api', api)
Sentry.setExtra('data', data)
console.error(errDesc)
}
export default collectionErrorInfo
有错误信息产生时自动发送邮件
有错误信息产生时钉钉内机器人自动通知
传统的前端监控原理分为异常捕获和异常上报,一般使用 onerror 捕获前端错误
window.addEventListener('error', (msg, url, row, col, error) => {
console.error(msg, url, row, col, error)
})
但是 onerror 事件无法捕获到网络异常的错误(图片资源加载失败、图片显示异常等),例如 img 标签下图片 url404 网络请求异常的时候,onerror 无法捕获到异常,此时需要监听 unhandledrejection
window.addEventListener('unhandledrejection', function (e) {
e.preventDefault()
console.error(e.reason)
})
总体来说,使用 Sentry 可以捕获各种类型的异常事件。在代码任意地方通过 console.error()或者 throw new Error(的方式)做任意信息的收集上报,而具体的上报信息格式看各自的需要设置。而 Sentry 也可以捕获上报任意代码未处理的异常信息。
在 Sentry 收集上报错误信息的时候,也会将上下文的接口信息、console.log()信息上报,通过 log 的上下文信息也可以对 bug 进行分析。
所以可以使用 Sentry 对一些接口偶发性异常做数据收集,拿到真实的数据去分析代码遗漏的场景。