1.简介
Sentry 是一个开源的实时错误追踪系统,可以帮助开发者实时监控并修复异常问题。它主要专注于持续集成、提高效率并且提升用户体验。Sentry 分为服务端和客户端 SDK,前者可以直接使用它家提供的在线服务,也可以本地自行搭建;后者提供了对多种主流语言和框架的支持,包括 React、Angular、Node、Django、RoR、PHP、Laravel、Android、.NET、JAVA 等。同时它可提供了和其他流行服务集成的方案,例如 GitHub、GitLab、bitbuck、heroku、slack、Trello 等。目前公司的项目也都在逐步应用上 Sentry 进行错误日志管理。
2.本地搭建sentry服务
Sentry 本身是基于 Django 开发的,而且也依赖到其他的如 Postgresql、 Redis 等组件,所以一般有两种途径进行安装:通过 Docker 或用 Python 搭建。官网下分别有以下的两个介绍:
因为在 Github 上有一个开源项目用于部署 Sentry ,所以我们这里以Docker安装为例。
要求:
- 服务器的内存至少 3G,否则在执行 sentry upgrade 命令时会出现问题
- Docker 19.03.6+
- Compose 1.24.1+
我们可以直接使用该项目进行部署,首先是克隆该项目:
git clone https://github.com/getsentry/onpremise.git
会看到有一个 onpremise 文件夹。后续的操作都在这个文件夹里面,如果并没有特殊要求或者额外的组件配置的话(比如说使用已有的 Postgresql 和 redis),可以直接运行 ./install.sh 将 Sentry 及其依赖都通过 docker 安装。
cd onpremise
# 执行安装
./install.sh
后续一步一步安装下来
然后你会发现 Fetching and updating Docker images 等了几个世纪都没反应!实在是太慢了,所以我们要改成阿里云的镜像在执行 install 命令,到阿里云里面获取最新的镜像地址
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
根据图中的描述操作就可以替换成阿里云的镜像。然后重新跑命令./install.sh,几分钟后,我们就可以按照下图所示创建admin账户用来登陆本地sentry服务。
如果要自定义配置文件,推荐根据需求修改一下文件配置
- config.yml
- sentry.conf.py
- .env w/ environment variables
以下是简单的邮件配置
Sentry 支持邮件发送的功能非常重要,当 Sentry 捕获事件之后,可以将此捕获的事件发送到你的个人邮箱(针对 Sentry 管理员账号)。要修改目前的邮件配置是不能在界面上操作的,需要进行以下步骤:
修改 sentry/config.yml文件配置
###############
# Mail Server #
###############
# mail.backend: 'smtp' # Use dummy if you want to disable email entirely
mail.host: 'smtp'
mail.port: 25
mail.username: ''
mail.password: ''
mail.use-tls: false
The email address to send on behalf of
mail.from: 'root@localhost'
在docker-compose.yml 文件中加入以下配置
x-sentry-defaults: &sentry_defaults
<< : *restart_policy
build:
context: ./sentry
args:
- SENTRY_IMAGE
- SENTRY_PYTHON3
image: sentry-onpremise-local
depends_on:
- redis
- postgres
- memcached
- smtp
- snuba-api
- snuba-consumer
- snuba-outcomes-consumer
- snuba-sessions-consumer
- snuba-transactions-consumer
- snuba-replacer
- symbolicator
- kafka
environment:
...
#这里开始
SENTRY_EMAIL_HOST: #邮件host 例如smtp.qq.com
SENTRY_EMAIL_USER: #邮件地址 例如testuser@qq.com
SENTRY_EMAIL_PASSWORD: # 填写自己的密码
SENTRY_SERVER_EMAIL: #邮件地址
SENTRY_EMAIL_PORT: 587 # port
SENTRY_EMAIL_USE_TLS: 'true'
修改完以上配置后run ./install.sh
启动sentry
待./install.sh结束后,run docker-compose up -d 即可启动本地的sentry服务,你将看到以下登陆界面。
使用已经建立的admin user登陆即可,如果run ./install.sh 过程中我们没有创建用户,接下来我们可以run docker-compose run --rm web createuser 创建用户。
然后可以测试一下邮件发送。登陆超级用户下点击左上角头像选择 Admin 进入到管理员界面,选择 mail(邮箱)菜单,看到更新后的邮箱设置:
点击最下方的 发送测试邮件 到当前用户的邮箱上,即可测试邮件发送功能是否配置成功。
3.官方Sentry服务
如果要使用官方的Sentry服务,我们只需去它的官网注册就行,一般是配合企业用户使用的付费模式。
4.简单的使用
1. 创建project
- 登录Sentry组织
- 选择
Projects
从左侧导航菜单中显示的所有项目名单 - 点击
+ Create Project
按钮
根据您要监视的代码为您的项目选择语言或框架,在这种情况下为JavaScript。
- 给项目一个Name。
- 正在Set your default alert settings检查中i'll create my own alerts later
- Assign a Team 到项目。
4.复制DSN key和方便使用,因为我们会将密钥复制到源代码中。
2.创建Alert
为每个项目创建各种警报规则,并在应用程序中发生错误时让Sentry通知何时,如何以及要通知谁。警报规则由“条件”和“操作”组成,它们在满足相关条件时执行。有关更多信息,请参阅警报。创建新项目时,可以选择使用警报规则创建该项目,该规则将在第一次出现新问题时(通过电子邮件)通知所有项目团队成员。这意味着下次发生类似错误时,由于错误不是“新的”,因此不会触发通知。
1.单击Alerts以打开“警报配置”页面
2.点击 New Alert Rule
3.在“新警报规则”表单中,选择一种Issue Alert类型并输入以下值
每当在“所有环境”中通过邮件看到事件时,新的警报规则就会通知选定的团队成员
4.点击Save Rule创建新规则
3.将Sentry SDK引入前端代码
- 在GitHub上打开
frontend-monitoring
示例代码存储库 - 单击
Fork
并选择您希望将此存储库分支到的目标GitHub帐户 - 派生完成后,单击Clone or download,然后复制存储库HTTPS URL
- 克隆项目到本地
git clone <repository HTTPS url>
5.安装SDK
Sentry通过在应用程序运行时中使用特定于平台的SDK捕获数据。要使用SDK,需要在源代码中导入并配置它。该演示项目使用React和Browser JS。最快的入门方法是使用CDN托管版本的JavaScript浏览器SDK,也可以NPM安装浏览器SDK。
- 打开index.html文件(位于./frontend-monitoring/public/下)
- 在Sentry SDK配置中,输入DSN从上一节中创建的项目中复制的键值
Sentry.init({
dsn: "<PASTE YOUR DSN KEY HERE>",
});
- 启动应用
1.打开一个shell终端,并将目录更改为frontend-monitoring项目文件夹
2.使用该.nvmrc文件来设置与此项目兼容的Node版本。跑:
3.通过运行以下命令安装项目依赖项:> nvm use
4.通过运行以下命令在本地主机上构建,部署和运行项目> npm install
> npm run deploy
部署成功完成后,您将在终端中看到确认信息。
5.React集成
因为Sentry使用的是一种Hook错误函数的技术,来达到捕获错误的目的,所以我们基本可以无损耗的接入到现有的项目中去。
下面是React与Sentry进行结合的核心代码
- 自定义错误捕获的组件
#SentryBoundary.js
import { Component } from "react";
import Raven from "raven-js";
export default class SentryBoundary extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error, errorInfo) {
this.setState({ error });
// 发送错误信息
Raven.captureException(error, { extra: errorInfo });
}
render() {
if (this.state.error) {
// 此处可以写成组件,当组件崩溃后,可以替换崩溃的组件
console.log("React Error");
}
return this.props.children;
}
}
- 配置客户端 (https://github.com/getsentry/sentry-javascript#other-packages)
这里我们配置Raven.js以使用Sentry DS
#index.js
Raven.config("DSN", {
release: release,
}).install();
ReactDOM.render(
<div>
<SentryBoundary>
<App />
</SentryBoundary>
</div>,
document.getElementById("root")
);
Raven.js支持所有主要的浏览器。在较旧的浏览器中,Raven.js收集的错误报告的详细程度可能会降低–例如,缺少堆栈跟踪数据或缺少源代码列号。
- 上传source-map
如果上面的代码已经配置好后,那么现在的应用是可以捕获到错误的,但是存在了一个问题,我们目前的项目大多都使用webpack
进行打包,而打包后的代码是混淆加密的代码,无法让我们准确的知道抛出错误的位置在哪里。所以我们需要上传source-map
和混淆后的文件一起上传到Sentry
服务器上。方便我们快速查找到问题所在的位置。
这个上传的配置及命令是比较繁琐的。也是项目结合Sentry
的一个难点。
上传source-map
目前有两种方式:
1.使用Sentry
提供的Webpack
插件进行配置,但是其灵活性不高。
Sentry提供了一个方便的Webpack插件,该插件可配置源地图并将其在构建过程中上载到Sentry。建议使用此过程将源上传到Sentry:
初始化插件时仅绑定必需的参数:npm install --save-dev @sentry/webpack-plugin
2.使用const SentryWebpackPlugin = require("@sentry/webpack-plugin"); module.exports = { // other configuration configureWebpack: { plugins: [ new SentryWebpackPlugin({ // sentry-cli configuration authToken: process.env.SENTRY_AUTH_TOKEN, org: "exmaple-org", project: "example-project", // webpack specific configuration include: ".", ignore: ["node_modules", "webpack.config.js"], }), ], }, };
sentry-cli
的,其灵活性比较高,可以针对不同项目进行单独的配置。
其配置较为繁琐,具体的React与Sentry结合的例子。可见参见github上的项目: react-sentry-demo。对每个配置都有详细的说明。其中的上传source-map
,实现了: 打包、环境检测、认证检测、上传source-map、删除本地source-map的操作,完成自动化,可以把脚本直接迁移到现有的项目中去,改动也不会太大。
其核心上传命令如下:sentry-cli releases files <release_name> upload-sourcemaps /path/to/files
6.浅入原理
在JavaScript中是有window.onerror这个方法的,而Sentry在前端的核心捕获原理,就是通过重写此方法,来对所有的错误进行捕获。其实现的代码大致如下:
let _winError = window.onerror;
window.onerror = function (message, url, lineNo, colNo, errorObj) {
console.log(`
错误信息: ${message}
错误文件地址: ${url}
错误行号: ${lineNo}
错误列号: ${colNo}
错误的详细信息 ${errorObj}`);
}
然后Sentry的工作就是获取非错误的数据,如: user-agent、浏览器信息、系统信息、自定义信息等信息,然后交给Sentry的生命周期函数,最后在把数据发送到Sentry服务端,进行错误信息展示。
从上面的浅入原理可以看到,其核心捕获是window.onerror。那么只要它可以捕获到的错误,都会发送到Sentry上。而window.onerror能捕获到的错误,除了Promise,基本上能在控制台出现的错误,都会捕获到。也就是运行时的错误,包括语法错误。