前端错误监控系统搭建

发表于2019-07-02 10:34 阅读(91)

当我们完成一个业务系统的上线时,总是要观察线上的运行情况,查看日志发现问题并进行优化迭代。

因为测试永远无法做到100%覆盖,用户也不会总是按照我们所预期的进行操作,因此我们需要在系统异常时主动对其进行收集上报,以制定解决方案。

当生产环境中产生了一个 bug 时,如何做到迅速报警,找到问题原因,修复后又如何在线上验证?此时我们需要一个高效的错误监控系统。

 前端错误监控

后端有各种强大的监控服务,给我们的应用稳定性保驾护航,然而大多数情况只能记录接口被请求之后所发生的错误。随着 Web 应用越来越强大,客户端的代码可就越来越复杂,很多不可预期错误发生在用户端,因此前端错误监控就不可或缺了。 

Why Sentry

我们需要一个成熟的监控系统,Sentry 就是一个这样的工具。

Sentry – 正如其名「哨兵」,可以实时监控生产环境上的系统运行状态,一旦发生异常会第一时间把报错的路由路径、错误所在文件等详细信息以邮件形式通知我们,并且利用错误信息的堆栈跟踪快速定位到需要处理的问题。

选择 Sentry 作为前端监控系统,还因为下几点:

  • 开源
  • 对各种前端框架的友好支持 (Vue、React、Angular)
  • 支持 SourceMap

Sentry 官方提供的免费服务有次数限制,达到一定限制后继续使用就需要收费了,但是我们可以利用 Sentry 的开源库在自己的服务器上搭建服务,官方已经提供了完善的操作文档。 

准备工作

Sentry 的搭建方式主要有两种:

  • 通过 Python 安装
  • 通过 Docker 安装

由于 Docker 更加方便易控,而且官方推荐的也是 Docker 部署,那下面就以 Docker 为例,在滴滴云的服务器上从零开始搭建一个 Sentry 服务,本示例中使用的服务器配置 1核CPU,2G 内存,操作系统 CentOs 7.4。

注意事项

  • 服务器的内存至少 2G,否则在执行 sentry upgrade 命令时会出现问题。
  • 以下所有命令在 sudo 权限下执行,否则 Docker 无法运行

安装 Docker

$ yum install docker -y

安装 Docker-Compose

$ pip install docker-compose

启动 Docker

$ systemctl start docker

开始搭建

1. 拉取 sentry-onpremise 仓库

Onpremise 是官方提供的包含了使用 Docker 部署 Sentry 所需依赖的引导程序。

$ git clone https://github.com/getsentry/onpremise.git

2. 创建服务端服务

$ cd onpremise

# 新建本地数据库和 Sentry 配置的目录
$ docker volume create --name=sentry-data && docker volume create --name=sentry-postgres

# 创建环境变量配置文件
$ cp -n .env.example .env

# 构建 Docker Services
$ docker-compose build

# 生成秘钥
$ docker-compose run --rm web config generate-secret-key

# 复制秘钥(即最后一行),编辑 .env 文件,将 SENTRY_SECRET_KEY 对应的 value 修改为刚才复制下来的秘钥
$ vim .env

# 创建数据库,生成管理员账号
$ docker-compose run --rm web upgrade

# 启动 Sentry 服务
$ docker-compose up -d

# 查看容器
$ docker-compose ps

如果执行过程中一切正常的话,在浏览器中输入http://ip:9000 就进入 Sentry 的登录页面了,使用上面创建的管理员用户名和密码登录系统。 

集成客户端 SDK

经过以上步骤我们 Sentry 服务端完成了,接下来就可以在应用中集成 Sentry 客户端 SDK,用来在前端代码中实时上报错误。

登录系统后首先会进入配置页面,简单配置一下:

  • Root URL: 绑定本 Sentry 服务的域名或者直接填写本服务的 IP
  • Admin Email: 系统管理员的邮件地址

配置好后,进入添加新项目界面,以 Vue 应用为例,点击 New Project 创建新项目,选择 Vue。创建成功后,按照指引可以看到Sentry 推荐使用 Raven.js 及其 Vue 插件,在我们的前端项目中引入监控的模块,注意监控模块要在 Vue 之后引入。

$ npm install raven-js 
// main.js

// 先引入Vue
import Vue from 'vue'

import Raven from 'raven-js'
import RavenVue from 'raven-js/plugins/vue'

Raven
  .config('https://<key>@sentry.io/<project>')
  .addPlugin(RavenVue, Vue)
  .install()

验证

到这里整个错误监控系统算是成型了,我们可以制造点错误,来验证一下功能是否符合预期。可以直接在前端程序代码里写点 bug,触发之后可以在前端调试工具的 network 中看到上报错误的网络请求,同时在 Sentry Dashboard 会发现这个错误,查看详情可以看到这个错误的详细信息了。

// main.js
// 使用一个未声明过的变量触发错误
console.log(hello)

  关联 SourceMap

目前大多数前端程序基本都会使用 Webpack 之类的工具构建,上线之后的代码都是经过压缩混淆的,所以这样的报错信息其实意义不大,错误位置根本无从定位,异常堆栈也难以理解,排查非常耗时费力,此时就要使用 SourceMap 对错误进行定位了,而 Sentry 也正对此有很好的支持。

 使用 sentry-cli

查看官方文档对引入 SourceMaps 的说明,可以看到有两种方式来上传 SourceMap 文件:

  • sentry-webpack-plugin: Sentry 提供的 Webpack 插件,灵活性不高
  • sentry-cli: 灵活性比较高,可以针对不同项目进行单独的配置

下面以 sentry-cli 的方式为例,看一下具体流程。

1、安装 sentry-cli

$ npm install sentry-cli-binary -g

2、生成 token

在 Sentry Dashboard 页面选择 API,生成 token,注意要勾选 project:write,开启项目的写权限。

3、登录 cli

$ sentry-cli login

执行后输入上生成的 token

关于 Relese 控制

说到上传 SourceMap 就要提一下 Release。在平时开发过程中我们希望不监控开发环境下的异常,也有区分测试环境和生产环境异常的需求,此时就需要 Release 将异常进行版本控制。

  • 创建 Release
$ sentry-cli releases -o 组织名称 -p 项目名称 new 版本号

组织名称、项目名称可以在 Sentry Dashboard 中查看,同时可以在 “Releases” 中查看是否创建成功。这样一来,通过生成不同的版本号,我们可以对异常进行分类。

  • 本地应用 Release 回到前端项目,在 Raven config 中添加对应的 Release,并指定版本号,每次上报的异常就会被分类到该版本下。
// main.js
...
import Raven from 'raven-js';

Raven
  .config(DSN, {
    release: '版本号'
  })
  .addPlugin(RavenVue, Vue)
  .install()
  • 删除 Release 在删除 Release 时需要将其下的异常处理掉,并将该版本的 SourceMap 文件清空,否则会报错
$ sentry-cli releases -o 组织名称 -p 项目名称 delete 版本号

上传 SourceMap

以上概念了解之后,就可以开始上传 SourceMap 文件了。

sentry-cli releases -o 组织名称 -p 项目名称 files 版本号 upload-sourcemaps --url-prefix 线上js文件所在目录

注意:

  • 通常来说 vendor.js 这种各种类库打包后生成的代码,并不是我们程序的源代码,不需要上传
  • --url-prefix 对应的是线上JS文件的目录,例如 ~/static/js/,其中~/代表网站根目录

SourceMap 上传成功后,就可以在 Sentry 上直接看到报错所在的源码了。

主动捕获错误

现在我们已经能成功监控程序中的大多数错误,但是无法捕获异步错误(比如定时器、接口请求错误)此时可以利用 raven.caputureException() 进行主动上报。

// 接口请求
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    window.$Raven.captureException(error);
  })

// 定时器任务
setTimeout(()=>{
  try {
    // do something
  } catch (err) {
    window.$Raven.captureException(err);
  }
}, 300)

邮箱设置

完成上面的所有步骤,我们的 Sentry 可以使用了,但是还有一个问题,上报错误时并没有收到邮件,作为一个自动化的异常提醒工具,没有了提醒功能,它价值就打大打折扣了。

在搭建好的 Sentry 的 Web 页面中无法配置邮箱 smtp 信息,需要修改配置文件 config.yml。

###############
# Mail Server #
###############

mail.backend: 'smtp'  # Use dummy if you want to disable email entirely
mail.host: 'smpt.gmail.com' # 输入邮箱smpt服务器地址
mail.port: 25
mail.username: 'your-email-address'
mail.password: 'your-email-password'
mail.use-tls: false

然后修改 docker-compose.yml,为其中的 Web 容器添加 volumes 卷,使刚才修改的 config.yml 配置文件生效。

 web:
    volumes:
      - ./config.yml:/etc/sentry/config.yml
    ....
 

然后重启服务

$ docker-compose up

测试一下,去触发一个错误,应该可以正常接收邮件了。


搭建过程中可能出现的错误

$ docker-compose run --rm web upgrade

在执行上面的命令过程中,可能会出现创建数据库失败、跳过了创建管理员账号步骤等错误,导致 Web页面无法使用。首先检查服务器的硬件配置,内存是否满足要求 (2G 以上),否则大概率就是数据库初始化时出错,此时可以手动初始化数据可以及创建管理员用户。

1、进入 sentry-web 的 shell

$ docker-compose run --rm web shell  

2、初始化数据

$ from sentry.models import Project
$ from sentry.receivers.core import create_default_projects
$ create_default_projects([Project])
  1. 退出 sentry-web 的 shell,手动创建用户
 $ docker-compose run --rm web createuser

刷新网页就可以使用刚刚创建好的账户登录。

原文地址: https://www.misuland.com/news/3255818066314922892