前端错误监控实战:用 Sentry 把线上报错从"用户反馈"变成"主动发现"
用户遇到白屏时的第一反应是关掉网页,而不是打开开发者工具复制报错发给你。
我上线过一个学生工具站,前两个月一直以为"没什么人反馈问题 = 没什么问题"。接了 Sentry 之后第一周就收到 47 条真实报错,其中一条白屏影响了 12% 的用户------只是他们全都默默走了。这篇文章讲清楚:免费版怎么搭、SDK 怎么配、噪音怎么降噪、告警怎么接,全套实操。
一、为什么是 Sentry(以及免费额度够不够)
前端监控的本质是把用户浏览器里的报错带上下文搬回来:什么错、哪个页面、哪行代码、什么浏览器、用户之前点了什么。Sentry 是这个领域事实上的标准,关键是免费额度对个人项目真的够:
| 套餐 | 价格 | 额度 | 对个人项目 |
|---|---|---|---|
| Developer | 免费 | 5K 错误/月 + 100 回放/月 + 1 会员 | 小站完全够用 |
| Team | $26/月 | 50K 错误/月 + 无限成员 | 小团队起步 |
自建也有开源替代(GlitchTip 完全兼容 Sentry SDK,可以直接把上报地址指过去)。如果在乎数据出境,自建 GlitchTip 或用国内 SaaS(如 Fundebug、Webfunny)都是选项,SDK 层面的接入方式几乎一样,本文思路通用。
二、接入:React/Vue 各一段代码的事
先建项目拿到 DSN,然后装 SDK:
bash
# React + Vite
npm i @sentry/react
# Vue
npm i @sentry/vue
React 入口:
ts
import * as Sentry from "@sentry/react";
Sentry.init({
dsn: "https://xxx@o0.ingest.sentry.io/0",
environment: import.meta.env.MODE, // production / development
release: "myapp@1.4.2", // 必填!否则你不知道哪个版本报的
tracesSampleRate: 0.1, // 性能追踪采样 10%
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: true, // 回放里遮蔽文本,防泄露隐私
blockAllMedia: true,
}),
],
});
三个配置决定你能不能用好它:
release必须传版本号(构建时注入 git sha 最省事)。不传的话,你只知道"有个报错",不知道"新版本是不是又引入了它"------Sentry 会按 release 对比新旧版本的问题增量,这是最值钱的功能。environment分开,开发环境的调试报错就不会污染生产面板。tracesSampleRate别开满,性能追踪量大,0.1 足够看出慢在哪。
Vue 的区别只在 Vue.createApp 之后用 Sentry.vueIntegration({ app }) 挂钩子,其他完全一致。
三、别只接 SDK:三类错误要主动上报
window.onerror 抓不到的东西,要手动喂给 Sentry:
ts
// 1. 接口报错:带上请求上下文
try {
await api.createOrder(payload);
} catch (e) {
Sentry.captureException(e, {
tags: { api: "/orders", method: "POST" },
extra: { payload, status: e.status },
});
throw e; // 继续抛给原有逻辑,上报不代替错误处理
}
// 2. 用户行为标记:报错发生前用户干了什么
Sentry.addBreadcrumb({ category: "ui", message: "点击了导出按钮" });
// 3. 关键业务埋点式报警:静默失败的业务逻辑
const ok = await saveDraft();
if (!ok) Sentry.captureMessage("草稿保存返回 false", "warning");
captureMessage 特别适合那些"不抛异常但业务已经不对"的场景------比如返回了空列表、状态码 200 但 body 异常。这类问题没有监控时是永远发现不了的。
四、降噪:监控项目死掉的头号原因
一周后你的面板会有几百条 issue,90% 是广告插件、浏览器兼容、第三方脚本报的。不清噪音,团队两周内就会不看面板,监控等于白搭。我的降噪三板斧:
ts
Sentry.init({
// 1. 屏蔽已知的无用来源
ignoreErrors: [
"ResizeObserver loop", // 浏览器内部噪音
"Non-Error promise rejection",
/chrome-extension/i,
],
// 2. 排除第三方脚本域名
allowUrls: [/myapp\.com/],
// 3. 采样:低价值错误降采样
sampleRate: 0.5,
});
再配合面板上的操作:同一个 issue 的重复出现会被自动聚合,把确认无害的 issue resolve 后选择"release 版本内不再提醒";用户个人环境的报错用 environment 隔离。坚持两周,面板里剩下的就都是真问题。
五、告警:让报错自己来找你
面板是"我去看",告警是"它来找你"。Sentry Alerts 免费版支持邮件和 webhook,推荐两条规则:
| 规则 | 条件 | 动作 |
|---|---|---|
| 新问题 | 任何 release 出现新 issue | 邮件(低优先级,攒着看) |
| 突增 | 5 分钟内同 issue > 20 次 | webhook → 企业微信/飞书群机器人(立刻看) |
webhook 直接指向企业微信群机器人的地址即可收到卡片消息;想要更精细的格式,中间垫一层 Serverless 函数转发。告警规则宁少勿多:超过 5 条规则、且每周响 10 次以上的告警,很快就会被习惯性忽略------告警的价值 = 触发次数 × 每次都值得看。
六、Source Map:让报错从 m...sed 变成可读
生产构建压缩后,面板里全是 a.b is not a function,必须上传 source map。以 Vite 为例:
bash
npm i -D @sentry/cli @sentry/vite-plugin
ts
// vite.config.ts
import { sentryVitePlugin } from "@sentry/vite-plugin";
export default defineConfig({
build: { sourcemap: true },
plugins: [
sentryVitePlugin({
org: "my-org", project: "myapp",
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
});
构建时自动上传并从产物中删除 map 文件(不能让用户下载到你的源码)。没做这一步的监控面板,可读性会劝退所有人。
七、一周用下来的真实收益
接完第一周我在面板里处理掉的典型问题:
- 一个只影响 Safari 的日期解析 bug(用户占比 8%,从没人反馈过);
- 图片上传在弱网下的超时静默失败,补了重试和提示;
- 一个第三方 CDN 脚本偶发加载失败导致的初始化报错,加了降级。
这些全都不是测试能测出来的,也全都不会有用户来反馈------他们只会离开。监控的本质是把"用户替你做测试"变成"你先于用户知道"。今晚花 20 分钟把 SDK 接上、release 传上,明早你的面板里就会开始出现那些一直存在、只是你从没看见的问题。