Sentry集成实战:从配置到错误监控的完整指南

Top丶璟春 优化 阅读 566
赞 14 收藏
二维码
手机扫码查看
反馈

先上核心代码,跑起来再说

别整那些虚的,Sentry 集成说白了就三步:装包、初始化、上报。我之前在项目里折腾了半天,最后发现最简单的方案反而最稳。直接看代码:

Sentry集成实战:从配置到错误监控的完整指南

// main.js 或 app.js 入口文件
import * as Sentry from '@sentry/vue';
import { Integrations } from '@sentry/tracing';

Sentry.init({
  app,
  dsn: 'https://your-dsn@o123456.ingest.sentry.io/987654',
  integrations: [
    new Integrations.BrowserTracing(),
  ],
  tracesSampleRate: 0.2, // 别开太高,不然流量吃不消
  environment: process.env.NODE_ENV, // 这个一定要加!
});

注意,如果你用的是 Vue 3,上面的写法没问题;Vue 2 的话,把 app 换成 Vue 构造函数就行。亲测有效,上线后第二天就抓到两个隐藏很深的异步错误。

手动捕获?别傻了,自动上报更香

很多人一上来就写 try...catch + Sentry.captureException,其实大可不必。Sentry 默认会自动捕获未处理的 promise rejection、全局 error、Vue 组件错误(通过 app.config.errorHandler 自动注入)。我之前手动包了一堆,结果发现重复上报,还污染了错误堆栈。

但有些场景确实需要手动上报,比如用户操作触发的业务逻辑错误:

async function submitOrder() {
  try {
    await api.post('/order');
  } catch (err) {
    // 只上报非用户预期的错误,比如网络超时、服务器崩了
    if (err.code !== 'USER_CANCELLED') {
      Sentry.captureException(err, {
        tags: { feature: 'checkout' },
        user: { id: currentUser.id }
      });
    }
    showUserFriendlyMessage(err);
  }
}

这里注意:**不要把所有 catch 都上报**。像“密码错误”这种用户行为导致的,上报了也是噪音。我一开始没过滤,Sentry 后台一天几万条,差点被运维骂死。

踩坑提醒:这三点一定注意

我踩过好几次坑,血泪教训总结如下:

  • DSN 别硬编码在前端:虽然 Sentry 官方说 DSN 是公开的,但最好还是通过环境变量注入。万一哪天要轮换 DSN,或者做多租户隔离,硬编码会让你哭。
  • source map 上传时机要对:很多人 build 完才上传,结果线上报错还是压缩后的代码。建议在 CI/CD 流程里,build 之后、部署之前上传。用 @sentry/cli 脚本:
# .gitlab-ci.yml 或 GitHub Actions 示例
- npm run build
- npx sentry-cli releases files $RELEASE_NAME upload-sourcemaps dist/ --url-prefix '~/'

记得配置 RELEASE_NAME,通常用 git commit hash 或 version。否则 Sentry 不知道哪个 source map 对应哪个版本。

  • 别忘了关掉本地开发的上报:我有次在本地疯狂调试,不小心触发了个循环错误,Sentry 一分钟收了 2000 条,直接把 quota 跑满了。现在我的 init 里都加了判断:
if (process.env.NODE_ENV === 'production') {
  Sentry.init({ /* ... */ });
}

这个场景最好用:自定义错误分组

默认情况下,Sentry 会根据错误消息和堆栈自动分组。但有时候,不同原因的错误被归到一起,或者同一个错误因为动态参数被拆成多个 issue。这时候就得用 fingerprint 手动干预。

比如我们有个接口 /api/user/{id},id 不存在时后端返回 404,但前端统一处理成 UserNotFoundError。如果不干预,每个 id 都会生成一个新 issue。加上 fingerprint 就清爽了:

Sentry.captureException(err, {
  fingerprint: ['user-not-found'] // 所有这类错误归为一组
});

反过来,如果一个错误可能有多种原因(比如“网络请求失败”可能是超时、断网、证书错误),你也可以用更细的 fingerprint 区分:

fingerprint: ['network-error', err.code || 'unknown']

高级技巧:带上用户上下文,排查快十倍

光知道哪里报错还不够,得知道是谁、在什么状态下出的问题。Sentry 的 setUsersetContext 是神器:

// 用户登录后
Sentry.setUser({
  id: user.id,
  email: user.email,
  // 别传敏感信息!比如密码、token
});

// 进入某个页面时
Sentry.setContext('page_state', {
  route: '/dashboard',
  role: 'admin',
  last_action: 'clicked_export_button'
});

这样在 Sentry 后台点开一个 issue,就能看到完整的用户路径和状态。上周我靠这个快速定位了一个只在“iOS 15 + Safari + 某个特定分辨率”下出现的布局崩溃问题。

不过要注意:**别传太多数据**。一是隐私合规问题,二是 payload 太大会被 Sentry 截断。我一般只传用户 ID、角色、当前页面关键参数。

还有一点:别信默认的 release 设置

Sentry 默认用 URL 作为 release,这在 SPA 里完全没用。一定要显式设置:

Sentry.init({
  // ...
  release: 'my-app@1.2.3', // 或者用 git short hash
});

配合 source map 上传,才能精准对应到代码版本。我之前没设,线上出了 bug 根本不知道是哪个版本引入的,只能靠猜。

结尾:这东西真能救命

说实话,集成 Sentry 之前,我们很多线上问题都是靠用户截图+描述来复现,效率极低。现在只要用户一操作,错误自动上报,带上下文、带堆栈、带用户信息,排查时间从几小时缩短到几分钟。虽然要花点 quota,但比起人肉 debug 的成本,太值了。

以上是我踩坑后的总结,希望对你有帮助。这个技术的拓展用法还有很多(比如自定义 alert 规则、performance tracing、integration with Slack),后续会继续分享这类博客。有更优的实现方式欢迎评论区交流。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论