背景
当我们开发的系统上线之后,需要对其运行状况进行监控。因为测试往往不可能覆盖所有可能出现的异常,用户也不一定会完全按照理想的方式去操作我们的系统,上游数据返回非预期可能也会导致触发一些异常。
对于后端应用,我们一般会通过日志的方式去发现和定位问题(比如 level 为 ERROR 的日志,响应状态码为非正常状态码的日志)。
对于前端代码,因为运行在用户端,如果出现一些 JS 运行时的异常,如果没有上报措施和用户反馈,那么这个错误可能就永远被忽略了。如果错误已经严重到影响到多数用户的使用,可能会有用户反馈,这时也会出现反复沟通确认,复现过程复杂。
对于系统运行中的异常,我们总是希望能够尽早发现,快速定位和解决,从而让异常影响到更少的用户。Sentry 是一套开源的错误上报和应用性能监控平台,适用于各类主流语言开发的应用。很早之前就听说过 Sentry,20 年下半年尝试在一些应用上进行了使用。本文主要介绍 Sentry 的基本概念、在前后端应用(Vue/Django)中接入的过程,以及它在错误上报、管理和应用性能监控上的基本使用。
Sentry 提供了 SaaS 服务和本地部署两种方式,两种方式主要功能上没有区别(SaaS服务当使用的量大了需要付费)。对于企业应用如果不希望代码外泄那一般采用本地部署方式。
Sentry 接入
Vue 应用接入主要步骤
- 创建项目,选择 Browser Tab 选择 Vue 应用。
接下来就有简单的接入指南。
实现错误和性能数据上报需要安装以下三个包,如果不想启用性能监控直接上面两个包即可。
- @sentry/browser (Sentry's core browser SDK)
- @sentry/integrations (contains Sentry's Vue integration)
- @sentry/tracing (instruments performance data)
按照 npm 包之后在main.js 中进行 Sentry 的初始化
// main.js // 配置仅在正式环境中启用 if (process.env.VUE_APP_ENV === 'production') { Sentry.init({ // data source name dsn: 'xxxxx', integrations: [ new VueIntegration({ Vue, // 开启性能监控 tracing: true }), new Integrations.BrowserTracing() ], // 设置性能监控采样率 tracesSampleRate: 0.2, // 我们正式环境又部分了两套,这里用了 vue 的环境变量进行区分 environment: process.env.VUE_APP_REGION_ENV, // 应用的版本,错误上报时会携带,可以区分上报的数据是出于哪个版本的代码 release: `${process.env.VUE_APP_VERSION}-${process.env.VUE_APP_REGION_ENV}` }) Vue.prototype.$sentry = Sentry }
我们希望在上报的数据中包含用户信息(可以查看用户操作行为,当出现异常时还可以主动联系用户),在 Vuex actions 中获取到用户信息的逻辑中主动进行设置
// src/store/modules/user.js // 设置sentry中的上下文 setSentryInfo({ commit, state }) { return new Promise((resolve, reject) => { this._vm.$sentry.configureScope(scope => { scope.setUser({ username: state.name }) }) resolve() }) }, // 获取用户信息 getUserInfo(...省略) { return new Promise((resolve, reject) => { getUserInfo(...省略).then(response => { ... // 当前 vue 实例 sentry 属性,设置 user 信息 if (this._vm.$sentry) { dispatch('setSentryInfo') } ... resolve(data) }).catch(error => { reject(error) }) }) },
上传 sourcemap。由于现在前端工程化应用一般会对源代码进行混淆压缩。如果没有 sourcemap,那么上报的错误晦涩难懂,难以定位到源代码中的具体逻辑。
// vue.config.js 配置 webpack 链式操作 config .when(process.env.VUE_APP_ENV === 'production', config => { config .plugin('@sentry/webpack-plugin') .use(SentryWebpackPlugin, [{ authToken: 'xxxx', org: 'xxx', project: 'xx', url: 'xxxx', // webpack specific configuration include: './dist', // 上传的 sourcemap 的版本,配合 vue 中 sentry 的初始化 release: `${process.env.npm_package_version}-${process.env.VUE_APP_REGION_ENV}` }]) .end() } )
实现基本的错误上报和应用性能监控上面的配置就够了。还有其他的一些更加丰富的设置,可以查看文档。Vue 接入文档
Django 应用接入主要步骤
和上面类似创建项目,然后选择 Django 应用。
安装 sentry_sdk pip包,在 setting.py 中初始化
import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration sentry_sdk.init( dsn=os.environ.get('SENTRY_DSN'), integrations=[DjangoIntegration()], traces_sample_rate=1.0, # If you wish to associate users to errors (assuming you are using # django.contrib.auth) you may enable sending PII data. # 上报数据的使用用户信息,如果使用了 Django 自带的认证,可以开启,如果没有采用那么需要自己再另外配置 default personal identification info send_default_pii=True )
配置上报数据的用户信息,如果你是自己实现的认证逻辑,在认证逻辑代码中添加如下代码即可。
from sentry_sdk import set_user set_user({'username': username})
除了在上报数据中添加识别用户信息,还可以丰富其他内容,可以查看 Django Enrich Events
Sentry 使用
基本术语
- Event:应用端每次触发异常,就是一个 Event,会上报到 Sentry 中
- Issue:Sentry 会对上报的异常按照一定的指纹算法进行 Group,(具体算法可以查看不同 SDK 的 Issue Group 文档,比如 Django Issue Grouping)相同的异常 event 会被归类到一个 Issue 下。
了解这两个基本概念之后,主要介绍一下 Sentry 的 Issue 和Performance。
Sentry Issue
Issue 列表和详情
下面以前端应用上报的数据举例。
- Issue 列表
在异常列表,我们可以看到异常类型、异常名称、触发位置、首次触发时间、最近一次触发时间、最近 24/14d 该类异常触发图标走势、总触发此处、总触发的人数、该 Issue 指派跟进人。
- Issue 详情
在 Issue 详情页面,我们可以查看到这个 Issue 最近触发的 event 的具体信息,比如触发的环境、用户、报错的具体位置。同时如果这个 issue 触发了多次,可以在右上角点击进行该 Issue 下多次上报 event 数据的切换。
在详情的下方,我们还可以看到该 event 的时间的 Breadcrumbs。Breadcrumbs 是该异常触发之前的一些事件线索,我们可以参考该数据从而对该操作触发前的一些操作行为进行模拟,从而可以更加快速的复现和定位问题。(后端应用的话则是异常触发前的一些代码逻辑,如请求外部接口、查询数据库等)
我们还可以对Issue 进行管理,如指派跟进人、标识解决的版本、忽略,同时在该 Issue 的 Activity Tab 下也可以看到该 Issue 的一些动态。
报警
当异常触发后,我们希望可以尽快收到异常的相关告警。这个时候我们就可以设置 Alert。比如设置邮件或者 IM 告警(Github 有 DingDing 的插件),如果是企业内部的 IM 也可以去开发响应的插件。
Sentry Performance
除了错误上报,Sentry 也可用作应用的性能监控。
这里以后端应用为例。
在 Performance 列表我们可以看到不同接口的加载时长,TPM、50 线、95 线等数据,可以按照响应时长进行排序,从而可以评估我们不同接口的性能,对响应比较慢的接口进行优化。
在性能监控上报的 event 数据,可以查看到接口中代码的调用栈,发现其中各个步骤的调用时长。
其他常用高级使用方法
- 主动补货并上报错误
有时我们可能需要自己去主动去触发一些错误上报,比如一些特定操作、某些已经被弃用的接口被调用了、捕获一些线上运行数据去排查问题。可以利用 Sentry 提供过的 captureException 或者 captureMessage 去上报错误或者文本信息。 - 丰富上报数据上下文
除了刚刚我们介入过程中提到的 user 用户信息,还可以有tags、level、fingerprint、extra data。
比如添加一些 tags,可以使用 scope.setTags(前端,不同语言语法不一样,如 Django 为sentry_sdk.set_context
) 可以给事件定义不同的键/值对。我们在后台查找的时候,筛选条件选项会多出来一些选项,就是通过 setTags 来设置的这些键值对。
总结
Sentry 为一套开源的错误上报和应用监控的解决方案。可以接入各类主流语言开发的应用提供,在异常上报之后,会进行过滤、按照一定的算法进行归类、集成丰富的环境和上下文信息,可以方便我们对异常的触发进行复现还原。
它不是传统日志、监控系统的替代品,它专注于应用的异常信息,从而让我们更快地发现问题、定位问题、解决问题,将异常尽早解决,从而影响更少的用户。同时性能监控数据,也可以为我们的应用优化提供方向。