Sentry 在 web 端的主要应用集中在错误捕获和性能数据上报。本文旨在总结如何优化 Sentry 的上报方式,以实现更丰富的信息收集和减少接口请求量。本文将分享一些个人经验,以规范上报格式并提供实用的优化方案。请将本文视为一篇启发性的文章,希望能为你提供有价值的参考。
前言
Sentry 的搭建可以参考这个文章:一口气完成 Sentry Docker 部署,本文不会赘述
本文针对的是 Sentry 在 React 端的上报优化,对于 web 端的上报同样具有一定的参考意义,主要总结的是以下内容:
- Sentry 的异步初始化
- Sentry 性能上报优化
- 报文信息优化
一、Sentry 初始化优化方案
1.1. 异步初始化
根据 Sentry 的官方的使用例子,Sentry 会以同步的方式在程序启动时进行初始化。那么为了防止 Sentry 的初始化会堵塞进程或者 Sentry 加载过程中自身发生了错误导致程序初始化失败,那么我们可以把它变为了异步加载,如下:
1.2. 处理 Sentry 初始化前的错误
1.2.1. 捕获初始化前的错误
异步加载 Sentry 会带来另一个问题,那就是如果程序初始化时的同步任务发生了错误,这些错误就会丢失在 Sentry 初始化前。
为了解决这一点,可以在程序初始化的最开始先注册一个全局的错误监听,收集这些没被 Sentry 捕获的错误,然后在 Sentry 初始化完成后统一上报,如下:
1.2.2. 系统崩溃导致 Sentry 无法初始化的情况
还有一种情况就是在 runSentry
之前已经发生了会导致系统崩溃的错误(例如 SyntaxError
),让整个程序停止执行,这时候连 Sentry 都不会被初始化。遇到这种情况,我们依然希望 Sentry 能被初始化,然后上报这个致命错误。
这种情况下因为无法判断 Sentry 完成加载的时机,因此可以增加一个倒计时来触发 Sentry 的初始化,在出现错误之后的 n(ms) 后如果 Sentry 还没有初始化完毕,则自动触发 runSentry
。
注:上方的 n(ms) 可以是任意值,只要你觉得正常情况下你的网站中 Sentry 可以在这个时间内完成加载即可。这里建议可以设置为正常情况下你的 web 程序的首屏渲染结束的平均时间(这需要你自己进行统计),可以使用 LCP
或 FCP
的平均时间。
下方是示例:
二、性能上报优化
2.1. 性能事务优化
Sentry 收集的 web 程序性能信息主要是通过插件 BrowserTracing
实现的,基本使用如下:
这样使用的话,Sentry 会在首屏加载结束(记为 pageload
事件)和路由跳转事件(记为 navigation
事件)都会进行采集相应的性能数据,并上报。
而考虑到路由切换会比较频繁,并且性能数据量会较多(10kb ~ 30kb),所以可以选择关闭路由跳转的性能上报:
或者
不过关闭 navigation
事件的性能上报并不是绝对的,任何时候你都要考虑项目的需求,如果你需要记录路由跳转性能,自然是不用关闭的。
2.2. LCP 上报
LCP
(Large Content Print)事件是评估 web 性能的一个重要标准,即首屏最大元素的渲染时间,但是它的记录时间很特殊,并不是在最大元素的渲染完成的时机,而是用户第一次操作(如点击页面)时才会正式记录下来,例如 LCP
时间为 15000ms
,但是 web 性能监控并不会在 15000ms
时存储这个时间,而是在用户第一次操作页面后才会存下这个 15000ms
。
这就导致了 Sentry 一般无法在首屏性能上报之前获得 LCP
时间(除非用户在上报前操作了页面),所以大多数情况下看 Sentry 后台的性能数据中都是没有 LCP
的。对于旧版本的 Sentry,一般会延长上报等待时间 idleTimeout
来延迟上报尽可能在用户操作后进行性能上报:
但是这种方法依然无法百分百保证 LCP
能被收集到,因为总是存在用户一直不操作页面的可能性。但是在 Sentry 7.42.0 以及之后版本,Sentry 进行了调整,它会模拟一次页面操作,从而让浏览器产生 LCP
记录。所以请尽可能使用 7.42.0 或更高版本的 Sentry。
三、报文信息优化
3.1. 过滤上下文信息
Sentry 在上报任何信息(错误日志、性能日志等)时都会携带这次事件的上下文,这些上下文包括打印信息、接口调用等,如果你的 web 程序没有对打印日志进行处理,例如在生产环境中也产生打印信息(console.log
),那么就会导致 Sentry 的上报请求体积过大。
为了解决这个问题,可以使用 Sentry 的钩子 beforeBreadcrumb
,对上下文信息进行过滤处理,以下是一个简单的示例:
注:这样的过滤同样不是必须的,如果你需要这些信息进行 debug,那么你就不需要过滤。但是保持 web 程序在线上环境的 console 的干净是一个好的规范。
3.2. 上报信息格式优化
为了对上报信息进行好的分类、增强 Sentry 后台上报信息的可读性,可以在 Sentry 上报前统一对这些信息进行处理、规范上报的格式。为了实现这一点,可以利用 Sentry 钩子 beforeSend
:
可以留意到,上面的示例中我们修改了 tags
、extra
、level
这几个值,下面会说明为什么本文会建议修改这几个。
3.2.1. 自定义哪些上报值?
这几个变量在 sentry 后台中的呈现分别为:
tags
:标签(tags: Record<string, string>
)
extra
:附加信息(extra: any
)
level
:严重程度(level: "debug" | "error" | "fatal" | "log" | "info" |
"warning"
)
- 除此以外,还应该注重【错误类型】和【错误值】的规范性:
其中 tags
、extra
、level
均可以通过上面 beforeSend
的第一个参数 event
直接进行修改,而【错误类型】和【错误值】则建议使用下文要讲的自定义异常类型的方式进行自定义(即使这两个也可以直接修改 event
进行自定义)
3.2.2. 自定义异常类型
对于可控的异常,例如可以被拦截器捕获的网络错误、手动上报的业务埋点等异常,建议自行封装异常类型,并配合统一的 handleError
函数来规范上报格式,以下是一个网络错误的例子:
经过上述封装,上报后的异常信息就会在 Sentry 后台中展示出有序分类、可读性强异常信息,从而提升排查故障的效率。
总结
以上是本文总结的一些 Sentry 上报优化的优化方案,从 Sentry 初始化、性能日志优化、上报信息优化三个方面提出了优化方案,可以为 React 端或 web 端的 Sentry 上报制定规范提供参考。