最近我们团队把前端监控从自建的简陋方案迁移到了Sentry,用了一段时间,踩了不少坑,也积累了一些实战经验。

Sentry是一个开源的错误监控和性能监控平台,支持前端、后端、移动端等多种平台,功能强大,社区活跃,是现在比较流行的监控方案。它能自动捕获前端的JavaScript错误、异常、性能问题,还能记录用户行为,帮助开发者快速定位和解决问题。对于前端团队来说,有一个好的监控平台,能大大提升线上问题的排查效率,减少故障影响时间。

但真正用起来,会发现Sentry虽然功能强大,但有很多细节需要注意,有很多坑要踩。从部署、接入、配置,到错误过滤、告警、性能监控,每一步都可能遇到问题。我们团队在迁移和使用的过程中,就踩了不少坑,花了很多时间排查和解决。今天来总结一下我们使用Sentry过程中遇到的坑和解决方法,以及一些实战经验,希望能给正在用或者准备用Sentry的朋友一些参考。

一、为什么选择Sentry

先简单说说我们为什么选择Sentry。

在这之前,我们的前端监控是自建的简陋方案,就是在前端捕获window.onerror,把错误信息通过接口上报到后端,存到数据库里,然后做了一个简单的后台页面,可以查看错误列表和详情。这个方案能用,但问题很多:

  1. 错误信息不完整:只能捕获到错误消息和行列号,没有错误堆栈,没有用户行为记录,没有浏览器信息,没有源码映射,排查问题很困难,很多错误根本不知道是哪里出的。
  2. 没有聚合和统计:错误都是一条条存的,没有聚合,同一个错误出现了很多次,要自己统计,很不方便。也没有趋势图、分布图,看不出错误的变化趋势。
  3. 没有告警:错误上报了,但没有告警,出了问题不知道,要等用户反馈或者自己去看后台才能发现,往往已经影响了很多用户。
  4. 没有性能监控:只能监控错误,不能监控性能,页面加载慢、接口慢、白屏等问题,发现不了。
  5. 维护成本高:自建方案,要自己维护后端服务、数据库、后台页面,功能迭代慢,很多想做的功能都没时间做。

基于这些问题,我们决定找一个成熟的开源监控方案,对比了几个,最终选择了Sentry,主要原因是:

  1. 功能强大:支持错误监控、性能监控、用户行为追踪、告警、源码映射、发布版本管理等,功能很全面,能满足我们的需求。
  2. 支持多平台:支持前端(JavaScript、React、Vue、Angular等)、后端(Java、Python、Node.js、Go等)、移动端(iOS、Android、React Native、Flutter等),一个平台监控所有端,很方便。
  3. 开源且社区活跃:Sentry是开源的,代码在GitHub上,社区活跃,文档完善,遇到问题能找到解决方案,也能自己定制和扩展。
  4. 部署方便:支持Docker部署,一键部署,维护成本低。
  5. 界面友好:Sentry的UI做得很好,错误列表、详情、趋势图、用户行为面包屑,都很清晰,排查问题很方便。

当然,Sentry也不是完美的,它的部署对服务器配置有一定要求,配置和使用也有一定的学习成本,但整体来说,是一个很成熟、很优秀的监控方案,值得推荐。

二、部署踩坑

我们选择的是私有化部署,用Docker部署,部署的过程中踩了几个坑。

坑1:服务器配置不够,部署后很卡

Sentry是一个比较重的应用,依赖很多组件(PostgreSQL、Redis、Kafka、ClickHouse、ZooKeeper等),对服务器配置要求比较高。我们一开始用了一台4核8G的服务器部署,结果部署完之后,访问很卡,错误上报也经常超时,根本没法用。

后来查了Sentry的官方文档,发现最低配置要求是4核16G,推荐配置是8核32G以上。我们把服务器升级到8核32G,就流畅了。

经验:部署Sentry,服务器配置一定要够,至少4核16G,推荐8核32G以上,不然会很卡,甚至部署失败。如果错误量很大,还需要更高的配置,或者集群部署。另外,磁盘空间也要够,Sentry会存储大量的错误数据和事件,磁盘占用增长很快,建议至少200G以上,并且定期清理旧数据。

坑2:Docker版本太低,部署失败

我们用的服务器,Docker版本比较老,是1.13的,部署Sentry的时候,docker-compose执行失败,报了一些奇怪的错误。查了半天,发现是Docker版本太低,Sentry要求Docker 19.03以上,docker-compose 1.24以上。

把Docker和docker-compose升级到最新版本,重新部署,就成功了。

经验:部署前,检查Docker和docker-compose的版本,确保满足Sentry的要求。建议用最新的稳定版本,避免兼容性问题。

坑3:内存不足,Kafka或者ClickHouse启动失败

部署过程中,遇到过Kafka或者ClickHouse启动失败的情况,查日志发现是内存不足(OOM)。Sentry依赖的组件很多,每个组件都需要内存,如果服务器内存不够,有些组件就会启动失败。

解决方法:一是升级服务器内存,二是调整各个组件的JVM内存配置,根据服务器的总内存,合理分配各个组件的内存,避免某个组件占用太多内存,导致其他组件内存不足。

经验:部署前,规划好各个组件的内存分配,不要用默认配置,默认配置可能不适合你的服务器。部署后,检查各个组件的运行状态和内存使用,确保都正常运行。如果有组件启动失败,先看日志,大概率是内存不足或者端口冲突。

坑4:端口被占用,或者防火墙没开

Sentry默认用9000端口,还有其他组件用的端口(比如PostgreSQL 5432、Redis 6379、Kafka 9092等),部署的时候,要确保这些端口没有被占用,并且防火墙开放了对应的端口。

我们部署的时候,就遇到过9000端口被其他服务占用了,导致Sentry的Web服务启动失败。后来改了端口映射,或者停掉了占用端口的服务,就好了。还有一次,部署完之后,外部访问不了,查了半天是防火墙没开9000端口,开放端口后就正常了。

经验:部署前,检查端口占用情况,确保Sentry需要的端口都没被占用。部署后,检查防火墙和安全组,开放需要的端口。如果是云服务器,还要检查云服务商的安全组配置。

三、前端接入踩坑

部署好Sentry之后,就是前端接入了,接入的过程中,也踩了不少坑。

坑1:sourcemap配置不对,错误堆栈看不懂

Sentry的一个核心功能,就是通过sourcemap把压缩后的代码错误堆栈,映射回源代码的位置,这样就能看到错误出现在源代码的哪一行哪一列,排查问题很方便。但sourcemap的配置,是一个大坑,很多人都在这里踩过坑。

我们一开始接入的时候,sourcemap配置不对,错误上报了,但堆栈还是压缩后的代码,根本看不懂,和没有sourcemap一样。查了很久,发现有几个问题:

  1. 构建的时候没有生成sourcemap:我们的构建工具(webpack)配置里,devtool设置的是false,没有生成sourcemap文件,Sentry自然就没法映射。需要把devtool设置成'source-map',生成独立的.map文件。
  2. sourcemap没有上传到Sentry:生成了sourcemap,但没有上传到Sentry,Sentry也没法映射。需要用Sentry的webpack插件(@sentry/webpack-plugin),在构建的时候自动把sourcemap上传到Sentry。
  3. release版本不一致:Sentry是通过release版本来关联sourcemap和错误事件的,如果前端代码里配置的release版本,和上传sourcemap时用的release版本不一致,就关联不上,sourcemap就不生效。需要确保两边的release版本一致,一般用git commit hash或者版本号。
  4. sourcemap上传了,但没有删除或者没有正确配置:有些团队,sourcemap上传到Sentry后,又把sourcemap文件部署到了线上,这样用户就能访问到sourcemap,有源码泄露的风险。正确的做法是,sourcemap只上传到Sentry,不要部署到线上,构建的时候生成sourcemap,上传到Sentry,然后部署的时候把sourcemap文件删掉,或者不部署到线上。

把这些问题都解决了,sourcemap就正常了,错误堆栈就能映射回源代码,排查问题方便多了。

经验:sourcemap是Sentry前端接入最重要的配置之一,一定要配置对。配置的时候,注意这几点:构建时生成sourcemap、用webpack插件自动上传、确保release版本一致、sourcemap不要部署到线上。配置完之后,故意触发一个错误,看Sentry里的堆栈是不是能映射到源代码,验证配置是否正确。

坑2:Vue/React框架的错误没有被捕获

我们的前端项目,有的用Vue,有的用React。接入Sentry之后,发现有些框架内部的错误,没有被Sentry捕获到,比如Vue组件里的错误、React的生命周期错误,这些错误在控制台里能看到,但Sentry里没有。

查了Sentry的文档,发现Sentry的JavaScript SDK,默认只捕获全局的错误(window.onerror)和未处理的Promise异常,对于框架内部的错误,需要集成框架对应的插件,才能捕获。

对于Vue,需要用@sentry/integrations里的Vue插件,配置Vue的errorHandler,这样Vue组件里的错误就能被捕获。对于React,需要用@sentry/react,它内置了React的错误边界,能捕获React组件里的错误。

我们给Vue项目配置了Vue插件,给React项目配置了@sentry/react,框架内部的错误就都能捕获了。

经验:如果用了前端框架(Vue、React、Angular等),一定要集成对应的框架插件,不然框架内部的错误捕获不到,监控就不完整。Sentry提供了主流框架的集成插件,按照文档配置就行。配置完之后,在组件里故意抛一个错误,看Sentry能不能捕获到,验证配置是否正确。

坑3:跨域脚本的错误,只有"Script error."

我们的前端项目,有些JavaScript文件是放在CDN上的,和页面不同域。接入Sentry之后,发现这些跨域脚本里的错误,上报到Sentry之后,只有一个"Script error.",没有错误消息,没有堆栈,根本没法排查。

这是因为浏览器的安全策略,对于跨域脚本的错误,为了保护用户隐私,只暴露"Script error.",不暴露详细的错误信息。要解决这个问题,需要做两件事:

  1. CDN配置CORS:在CDN服务器上,配置Access-Control-Allow-Origin响应头,允许跨域访问JavaScript文件。
  2. script标签加crossorigin属性:在页面引入跨域JavaScript的script标签上,加上crossorigin="anonymous"属性,这样浏览器就会以匿名方式请求脚本,就能获取到详细的错误信息了。

我们给CDN配置了CORS,并且在构建的时候,自动给script标签加上crossorigin属性,跨域脚本的错误就有详细信息了。

经验:如果JavaScript文件放在CDN上,和页面不同域,一定要配置CORS和crossorigin属性,不然跨域脚本的错误只有"Script error.",没法排查。这是一个很常见的坑,很多人都遇到过。

坑4:错误量太大,Sentry被打爆,或者费用太高

Sentry接入之后,有时候会遇到错误量突然暴增的情况,比如某个版本上线后有bug,或者某个第三方脚本报错,短时间内产生大量错误事件,把Sentry打爆,或者如果用Sentry的云服务,费用会很高。

我们就遇到过一次,一个版本上线后,有一个不影响使用的小bug,但触发频率很高,短时间内产生了几十万条错误事件,Sentry的处理速度跟不上,事件队列堆积,其他错误也延迟了,而且服务器磁盘占用暴增。

解决方法:

  1. 错误过滤:在Sentry的SDK配置里,设置ignoreErrors,忽略一些已知的、不影响使用的错误,或者第三方脚本的错误,减少上报量。
  2. 采样率:设置sampleRate,对错误事件进行采样,比如只上报20%的错误,这样能大大减少事件量,同时不影响错误的发现和统计。对于错误量很大的项目,采样是很有必要的。
  3. 限流:Sentry服务端可以配置限流,每个项目每分钟最多处理多少事件,超过的就丢弃,避免被打爆。
  4. 告警:配置错误量突增的告警,一旦某个项目的错误量突然增加,立即告警,及时排查,避免产生大量无用的错误。

我们配置了ignoreErrors、采样率和限流,并且加了错误量突增的告警,后来就再也没有出现过被打爆的情况。

经验:错误量控制是使用Sentry很重要的一环,尤其是错误量很大的项目,一定要配置过滤、采样和限流,避免Sentry被打爆,或者云服务费用太高。同时,配置错误量突增的告警,能及时发现线上问题,也能避免大量无用错误。

坑5:用户信息和自定义上下文没有正确设置

Sentry支持设置用户信息(id、用户名、邮箱等)和自定义上下文(比如当前页面、用户操作、业务参数等),这些信息会和错误事件一起上报,排查问题的时候,能知道是哪个用户、在什么页面、做了什么操作的时候出的错,非常有用。

我们一开始接入的时候,没有设置用户信息和自定义上下文,错误上报了,但不知道是哪个用户出的错,也不知道用户在做什么,排查问题很困难。后来,我们在用户登录之后,调用Sentry的setUser方法,设置用户信息;在路由切换的时候,设置当前页面信息;在关键的用户操作的时候,用addBreadcrumb方法,记录用户行为面包屑。这样,错误事件就带上了用户信息和上下文,排查问题方便多了。

经验:一定要设置用户信息和自定义上下文,这对排查问题非常重要。用户信息在登录后设置,登出时清除;页面信息在路由切换时设置;用户操作用面包屑记录。设置完之后,看一个错误事件的详情,就能知道用户是谁、在哪个页面、做了什么操作、之前做了什么,排查问题效率大大提升。

四、告警配置踩坑

Sentry的告警功能很强大,但配置起来也有不少坑。

坑1:告警太频繁,被骚扰到麻木

一开始配置告警的时候,我们把阈值设得太低,只要有错误就告警,结果每天收到几十上百条告警消息,大部分都是已知的、不影响使用的小错误,大家被骚扰到麻木,后来真正重要的告警也被忽略了,反而起不到告警的作用。

后来我们调整了告警策略:

  1. 只对严重的错误告警:对于影响核心功能、影响大量用户的严重错误,才告警;对于已知的、不影响使用的小错误,不告警,只在后台记录。
  2. 设置合理的阈值:不是有错误就告警,而是错误量达到一定阈值,或者影响用户数达到一定数量,才告警,避免偶发的、个别的错误触发告警。
  3. 告警去重和聚合:同一个错误,短时间内多次出现,只告警一次,不要每次都告警。Sentry的告警规则支持去重和聚合,配置好就行。
  4. 分级告警:不同级别的错误,用不同的告警方式,严重的错误用电话或者短信告警,一般的错误用邮件或者IM告警,避免所有告警都用同一种方式,分不清轻重缓急。

调整之后,告警数量大大减少,都是真正需要关注的问题,大家也不会被骚扰到麻木了,告警的效果反而好了很多。

经验:告警不是越多越好,而是要精准、有效。太频繁的告警会让人麻木,反而起不到作用。配置告警的时候,要合理设置阈值、去重聚合、分级告警,只对真正重要的问题告警,这样才能发挥告警的作用。

坑2:告警延迟,或者告警丢失

有一段时间,我们发现有些错误,Sentry里已经有了,但告警没有及时发出来,延迟了很久,甚至有些告警丢失了。排查后发现,有几个原因:

  1. Sentry处理延迟:错误量很大的时候,Sentry的事件处理有延迟,告警规则的评估也会延迟,导致告警不及时。解决方法:提升Sentry服务器配置,或者集群部署,提升处理能力;配置采样和限流,减少事件量。
  2. 告警规则配置不对:有些告警规则,条件配置得太复杂,或者用了不对的聚合方式,导致告警没有触发,或者触发延迟。解决方法:简化告警规则,用Sentry推荐的告警规则模板,配置完之后测试验证。
  3. 通知渠道问题:告警通知渠道(邮件、短信、Webhook等)配置不对,或者渠道本身有问题,导致告警发不出来。解决方法:检查通知渠道配置,定期测试告警通知是否正常。
  4. 告警被静默了:Sentry有静默规则,如果某个错误被静默了,就不会告警。有时候不小心配置了静默规则,或者静默时间设得太长,导致告警被静默了。解决方法:检查静默规则,确保没有误静默重要的错误。

我们排查了这些问题,调整了配置,告警就正常了。

经验:告警配置完之后,一定要测试验证,确保告警能正常、及时地发出来。定期检查告警规则和通知渠道,确保有效。如果发现告警延迟或者丢失,及时排查,从Sentry处理能力、告警规则配置、通知渠道、静默规则这几个方面排查。

五、性能监控踩坑

Sentry除了错误监控,还有性能监控(APM)功能,能监控页面加载时间、接口响应时间、用户操作耗时等,帮助发现性能问题。我们也开启了性能监控,踩了几个坑。

坑1:性能数据量太大,占用太多存储和费用

性能监控的数据量,比错误监控大得多,因为每个用户的每次页面访问、每个接口请求,都会产生性能事件,如果不控制,数据量会非常大,占用大量存储,或者云服务费用很高。

我们一开始开启性能监控的时候,没有配置采样率,所有性能事件都上报,结果一天就产生了几百万条性能事件,磁盘占用暴增,Sentry处理也变慢了。

后来我们配置了性能监控的采样率(tracesSampleRate),只采样10%的性能事件,数据量就大大减少了,同时也能反映整体的性能情况,足够用了。

经验:性能监控一定要配置采样率,不要全量上报,除非数据量很小。采样率根据项目的访问量和需求来设置,一般5%到20%就够了,既能反映整体性能,又不会产生太多数据。

坑2:前端路由的性能监控不准确

我们的项目是单页应用(SPA),用了前端路由。开启性能监控后,发现页面加载的性能数据不准确,只有第一次打开页面的时候有数据,路由切换的时候没有性能数据,或者数据不对。

查了文档,发现Sentry的性能监控,对于SPA的前端路由,需要配置路由监听,才能在路由切换的时候,记录新的页面加载性能。Sentry的React和Vue集成,都支持路由监听,但需要正确配置。

我们按照文档,配置了路由监听,路由切换的时候,就能正确记录页面加载性能了。

经验:如果是单页应用,一定要配置前端路由的性能监控,不然只有第一次打开页面有性能数据,路由切换的数据没有,性能监控就不完整。Sentry的主流框架集成都支持路由监听,按照文档配置就行。

坑3:接口性能数据和实际不符

性能监控里的接口响应时间,和我们实际感觉的不一样,有时候显示很快,但用户觉得慢。排查后发现,Sentry的接口性能监控,记录的是从请求发起到响应返回的时间,不包括DNS查询、TCP连接、TLS握手的时间,也不包括前端处理响应的时间,所以和用户实际感受到的时间有差异。

另外,如果接口是跨域的,没有配置CORS,浏览器的Performance API就拿不到详细的时序数据,接口性能数据也会不准确。

解决方法:一是理解Sentry性能数据的含义,它记录的是网络请求的时间,不是用户完整的体验时间;二是跨域接口配置CORS,让浏览器能拿到详细的时序数据;三是结合用户行为数据和自定义的性能指标,综合评估性能。

经验:性能监控的数据,要理解它的含义和局限,不要盲目相信。Sentry的性能数据,能帮助发现性能问题,但不能完全代表用户的真实体验,需要结合其他数据和实际感受,综合评估。

六、实战经验和最佳实践

除了上面的踩坑总结,我们在使用Sentry的过程中,也积累了一些实战经验和最佳实践,分享给大家。

1. 按环境和版本区分项目

Sentry里,建议按环境(开发、测试、生产)和版本来区分项目,或者用同一个项目但配置不同的environment和release。这样,不同环境的错误不会混在一起,生产环境的错误不会被开发测试环境的错误干扰,版本发布后,也能看每个版本的错误情况,方便定位是哪个版本引入的问题。

我们的做法是,同一个项目,用environment区分开发、测试、生产,用release区分版本(git commit hash),这样既能分开环境,又能跟踪版本,很方便。

2. 配置合理的保留策略,定期清理旧数据

Sentry会存储大量的错误和性能事件,如果不清理,磁盘占用会越来越大,最终撑爆磁盘。一定要配置合理的数据保留策略,定期清理旧数据。

Sentry支持配置事件保留时间,比如只保留30天或者90天的事件,超过的自动清理。对于错误,可以保留久一点,比如90天;对于性能数据,可以保留短一点,比如30天。另外,Sentry的清理任务(cleanup)要定期运行,一般每天运行一次,清理过期的数据。

我们的做法是,错误事件保留90天,性能事件保留30天,每天凌晨运行清理任务,磁盘占用就稳定在一个合理的范围,不会一直增长。

3. 建立错误处理流程,定期复盘

Sentry只是工具,真正重要的是建立错误处理流程,让错误能被及时发现、分配、处理、复盘。不然,错误上报了,但没人看,没人处理,监控就白做了。

我们的做法是:

  • 每天早上,前端负责人看一下Sentry的错误列表,把新的、严重的错误分配给对应的开发人员。
  • 开发人员收到分配的错误,及时排查和修复,修复后在Sentry里标记为已解决。
  • 每周,团队开一个短会,复盘本周的错误,分析原因,总结经验,避免类似问题再次发生。
  • 每个版本发布后,关注新版本的错误情况,如果有新的严重错误,及时回滚或者修复。

建立了错误处理流程,Sentry才能真正发挥作用,帮助团队提升代码质量和线上稳定性。

4. 和发布流程结合,发布后关注错误

Sentry的release功能,能和发布流程结合,每次发布新版本,在Sentry里创建一个release,并且关联本次发布的commit和变更。发布后,关注这个release的错误情况,如果有新的错误,能快速定位是本次发布引入的,及时处理。

我们的做法是,在CI/CD流程里,每次构建发布的时候,自动调用Sentry的API,创建release,上传sourcemap,并且关联git commit。发布后,在Sentry里看这个release的错误趋势,如果错误量突增,说明本次发布有问题,及时回滚或者修复。

和发布流程结合,能大大提升线上问题的响应速度,减少故障影响时间。

5. 利用用户反馈和面包屑,快速定位问题

Sentry的用户行为面包屑(Breadcrumbs)功能,能记录用户在错误发生前的一系列操作,比如页面跳转、点击、接口请求、控制台输出等,排查问题的时候,能还原用户的操作路径,知道用户是做了什么操作之后出的错,非常有用。

我们在关键的用户操作和业务节点,都用Sentry的addBreadcrumb方法记录了面包屑,比如用户登录、加入购物车、下单、支付等。出了错误,看面包屑,就能知道用户在错误前做了什么,快速复现和定位问题。

另外,Sentry还支持用户反馈功能,用户遇到错误的时候,可以弹出一个反馈框,让用户填写遇到的问题和联系方式,这些反馈会和错误事件关联起来,帮助开发者了解用户遇到的具体问题,也能和用户沟通,告知问题处理进度。

6. 定期升级Sentry版本,关注新功能

Sentry更新很快,经常有新功能和bug修复,建议定期升级Sentry版本,跟上社区的步伐,享受新功能,也避免老版本的bug。

升级的时候,注意看升级文档,有些大版本升级可能有不兼容的变化,需要调整配置。升级前,先备份数据,在测试环境验证没问题了,再升级生产环境。

我们的做法是,每季度升级一次Sentry,先在测试环境升级验证,没问题了再升级生产环境,一直保持比较新的版本,也能用到新功能。

七、写在最后

Sentry是一个非常优秀的监控平台,功能强大,社区活跃,能大大提升前端团队的线上问题排查效率和代码质量。但要真正用好Sentry,发挥它的价值,还是需要踩不少坑,积累不少经验。

我们团队在使用Sentry的过程中,从部署、接入、配置,到告警、性能监控、错误处理,每一步都踩了坑,也都学到了东西。总结下来,最重要的几点是:

  1. 部署配置要够:服务器配置、Docker版本、端口防火墙,这些基础的东西要先搞定,不然后面都是白搭。
  2. sourcemap要配好:这是前端接入最核心的配置,配错了,错误堆栈看不懂,监控就失去了意义。
  3. 框架插件要集成:用了Vue、React等框架,一定要集成对应的插件,不然框架内部的错误捕获不到。
  4. 错误量要控制:过滤、采样、限流,控制错误量,避免Sentry被打爆,也避免告警骚扰。
  5. 告警要精准:合理设置阈值、去重聚合、分级告警,只对真正重要的问题告警,才能发挥告警的作用。
  6. 用户上下文要设置:用户信息、页面信息、用户行为面包屑,这些上下文信息,是排查问题的关键。
  7. 错误处理流程要建立:工具只是工具,重要的是流程,让错误能被及时发现、处理、复盘,监控才有价值。
  8. 数据保留要合理:定期清理旧数据,避免磁盘被撑爆。

希望我们的踩坑总结和实战经验,能给正在用或者准备用Sentry的朋友一些参考,让你们少踩一些坑,更快地用好Sentry,提升团队的线上稳定性和开发效率。

最后,想说的是,监控是一个持续优化的过程,不是接入了就完事了,需要根据团队的实际情况,不断调整配置,优化流程,才能让监控真正发挥价值。愿大家都能搭建好自己的监控体系,线上问题越来越少,代码质量越来越高。