点击蓝字 「前端小苑」关注我
本文概要
1. Sentry是什么?
2. Sentry的接入
3. Sentry的高级用法
前言
前端项目目前发现错误的方法有哪些呢?
测试同学测出来。
缺点:现在浏览器版本、手机机型太多,兼容性问题很难测完全。另外有些项目流程非常长和复杂,测试同学不能确保每次都能覆盖100%的Case;
同事code review。
缺点:这个的缺点是时间成本高、而且大多时候,code review也只是发现代码风格问题,对于逻辑和业务,其他同学没有时间深入去读的;
上线线后用户投诉反馈。
缺点:用户的机型、浏览器百花齐放,我们复现问题很困难。另外大多用户不懂专业术语,表达问题不准确,沟通成本很高,这些都导致解决问题效率非常低下。
为了解决目前项目开发和管理流程中:上线前case很难测全、上线后问题复现困难,并且沟通成本高的现状,我的项目接入了sentry。
Sentry是什么?
sentry,中文翻译是哨兵。它是一个错误监控和收集工具。用户在项目使用中,遇到报错,sentry会第一时间通知开发者,项目出现了什么错误,错误出现在哪儿,并且会帮我们记录错误。
使用sentry需要结合两个部分,客户端与服务端。客户端就是你需要去监听的项目。而服务端就是一个数据管理平台,它会展示已收集到的错误信息和项目信息。并支持项目管理,组员管理、邮件报警等功能。
服务端平台可以自己搭建,也可以直接使用sentry官方平台。
另外,sentry非常强大之处在于支持多种语言和框架 (https://docs.sentry.io/platforms/) 这里我只研究了一下前端如何使用。其他语言和框架、以及服务端的搭建暂时不涉及。
我们已经知道了sentry是什么,那么sentry到底怎么用呢?
Sentry的接入
新建项目
首先,新建项目在sentry服务端平台完成。sentry.io/。新建完项目后,就会生成一个DSN串。DSN是链接我们要上报的项目和sentry服务端的钥匙。每当我们在sentry服务端创建一个新的项目,都会得到一个独一无二的DSN。在项目初始化时需要配置DSN到项目.这样客户端报错,服务端就能抓到对应项目的错误了。
安装SDK
SDK的安装和我们平时项目引用第三方包的方式完全一样。有cdn引入和npm包注入两种方式,这两种引入方式配置也一样。
npm install @sentry/browser
配置
// When using npm, import Sentry
import * as Sentry from '@sentry/browser';
Sentry.init({ dsn: 'https://[email protected]/1509915' });
注意:如果是Vue项目,请不要在开发环境使用sentry。
因为Vue项目使用sentry时,需要配置@sentry/integrations。而@sentry/integrations是通过自定义Vue的errorHandler hook实现的,这将会停止激活Vue原始logError。会导致Vue组件中的错误不被打印在控制台中。所以vue项目不要在开发环境使用sentry。
这里我再补充一下,为什么Vue项目要配置sentry集成器?
这里说的sentry集成器是用于增强sentry Api的SDK。 VUE项目配置了它, 就可以捕获引发错误的组件名称和props状态。
此外,Integrations.Vue有以下配置选项:
1. Vue:可选的,如果你不传入,则window.Vue必须存在;
2. attachProps:可选的,默认为true。如果将其设置为false,Sentry将禁止发送所有Vue组件的活动组件的名称和props状态。
3. logErrors:可选的,默认为false。如果设置为true,Sentry会调用原始Vue的logError功能。
import Vue from 'vue'
import * as Sentry from '@sentry/browser'
import * as Integrations from '@sentry/integrations'
Sentry.init({
release: VERSION,
dsn: 'https://[email protected]/1509915',
integrations: [
new Integrations.Vue({
Vue,
attachProps: true // 是否上报组件的 props
})
]
})
高级用法
前面我们已经知道了如何将sentry的接入到项目中,这个时候sentry就已经可以帮我们上报错误信息啦。sentry会默认上报页面抛出的所有未被捕获的错误(包括window.error 和promise异常)。但是,sentry还为我们提供了一些更高级的功能。接下来,我们看一下sentry高级用法。
常用功能
1. 主动捕获并上报错误。
主动上报的方式有两种:一种是直接上报文本信息,参数为一个字符串;
另一种是上报错误对象,参数为一个error 对象或者类对象。
try {
aFunctionThatMightFail();
} catch (error) {
// 上报error对象
Sentry.captureException(error);
}
// 上报文本信息
Sentry.captureMessage('Something went wrong');
2. 丰富BUG上下文数据。
丰富BUG上下文数据其实就是添加自定义信息到上报事件。
Sentry提供给我们可自定义的上下文信息的有:user 、 tags 、 level 、fingerprint 、 extra data。
这些信息我们可以通过在 scope 上面设置来定义。有两种设置方式:
一种是 sentry.configScope, 它会设置信息到sentry全局作用域。使用这种方式设置的信息,会被后续所有的上报事件携带。
另一种 sentry.withScope, 这种方式会设置一个临时信息到当前事件上。可以理解为一次性的信息设置。这种方式设置的数据,只在当前事件生效。当我们想为某个事件单独设置信息,而不想影响“全局”作用域时,就可以用它。
下面是添加上下文信息的具体方法:
// 设置用户信息:
scope.setUser({ “email”: “[email protected]”})
// 给事件定义标签:
scope.setTags({ ‘api’, ‘api/ list / get’})
// 设置事件的严重性:
scope.setLevel(‘error’)
// 设置事件的分组规则:
scope.setFingerprint(['{{ default }}', url])
// 设置附加数据:
scope.setExtra(‘data’, { request: { a: 1, b: 2 })
使用scope.setUser 可以设置用户的id 、 username 、 ip、email等信息。
使用scope.setTags可以给事件定义不同的键/值对。事件上报后,我们在后台查找的时候,筛选条件选项会多出来一些选项,就是通过setTags来设置的这些键值对。
scope.setLevel是用来设置事件的严重性的。参数包括:fatal 、error 、 warning 、 info 、 debug 。( fatal : 是事故,error 代表错误,上报的事件默认都为error )
使用scope.setFingerprint可以自定义事件的分组规则。Sentry拥有一套默认的分组策略。但是这个有时候并不能满足我们的需求。例如sentry会将所有的UnhandledRejection分组在一起,但事实上我们想要更加细致的分组,比如按接口URL来分组。这里就可以使用scope.setFingerprint([‘{{ default }}’, url])来设置。
Sentry.setExtra可以设置附加数据,例如记录ajax请求的参数,返回值,header信息等
3. 上传SourceMap文件。
Sentry强于其他错误监控平台的特点之一就是支持sourcemap。只要我们将sourcemap文件也上传到服务器,就可以在sentry平台看到源代码,从而快速定位错误。
前面提到需要将souceMap文件上传到服务器,但是这样子会将我们的源码文件暴露在客户端,非常不安全。另外sentry解析需要从另外一台的服务器获取sourcemap文件,也增加了服务器之间的开销。
所以,官方推荐将sourcemap上传到sentry服务器上。
将sourcemap上传到sentry服务器的方式有3种。
第一种是使用sentry提供的webpack插件在项目打包时自动上传。这种方式只需要在webpack打包配置中加入相关配置信息即可,是三种方式中最方便的方式。所以在业界大多使用这个方式。
第二种是使用sentry提供的上传脚本,sentry-cli上传。
第三种是直接直接调用sentry API 上传,这种配置参数较多,比较麻烦。
综合对比上面3种上传方式,我毫不犹豫的选择了第一种,上传后,错误能定位到源码,看似非常顺利。
但是使用没多久,就发现一个问题,我们的项目上线变慢了。
原来,sentry提供的上传sourcemap的方法都是同步上传,会导致上线变慢。
所以,我们可以将其优化为异步上传方式。
其他
1. 捕获用户对崩溃的反馈。
2. 在beforeSend等hook中添加过滤事件和自定义逻辑。
3. addBreadcrumb 添加一次行为记录等。
Sentry.init({
dsn: 'https://[email protected]/1509915',
beforeSend(event, hint) {
// Check if it is an exception, and if so, show the report dialog
if (event.exception) {
Sentry.showReportDialog({ eventId: event.event_id });
}
return event;
}
});
捕获用户反馈的的方法是在sentry的beforeSend hook里调用 showReportDialog方法。这样子,当错误发生时,客户端就会弹出让用户填写错误信息的弹窗。
另外sentry还加入面包屑的概念。sentry中的面包屑其实就是Sentry自动记录的一些日志和事件。例如浏览器URL的改变,ajax请求、之前的错误事件等。记录这些信息可以为当前错误提供上下文,重现导致错误发生的步骤,为我们复现和调试错误提供了关键信息。Sentry也提供了自定义添加面包屑和关闭面包屑的API。这个不太常用,我就不赘述了。
今天主要先讲sentry的作用和使用方法,要讲的就是这些了。最后总结一下:
Sentry是一个开箱即用、兼容性较好、功能强悍、并且生态圈非常完善的监控工具。你值得拥有????。
关于本文
作者:眉芳
原文链接:https://juejin.im/post/5dafc3df5188257a63539c64
更多文章请点击“阅读原文”
喜欢本文点个“在看”哟!