feat(monitoring): 接入 Sentry 错误监控#296
Conversation
为生产环境加错误捕获与 10% 性能采样。免费 tier 5K errors/月 + 10K perf
units/月,以社区站当前流量用不到上限。
**安装内容**
- @sentry/nextjs
- sentry.{client,server,edge}.config.ts:按 runtime 初始化,共享同一策略
- instrumentation.ts:Next 15+ 约定的启动 hook + onRequestError
- next.config.mjs:withSentryConfig 包一层,source map 上传 + bundle 瘦身
**配额安全策略**
- enabled: NODE_ENV === "production":本地 dev / preview 完全不发事件
- tracesSampleRate: 0.1:10% 采样,足够看 P75 趋势而不爆配额
- replay / profiling 全关:属于另外的付费配额类目
**贡献者友好**
- enableSentry = Boolean(SENTRY_AUTH_TOKEN):没配 Sentry env 的贡献者
`pnpm dev` / `pnpm build` 完全不触发 Sentry webpack 插件,零报错
- .env.sample 说明 DSN 是公开的,AUTH_TOKEN 是私密的
**部署须知**
Vercel 集成已把 4 个 env 自动注入三环境(NEXT_PUBLIC_SENTRY_DSN /
SENTRY_AUTH_TOKEN / SENTRY_ORG / SENTRY_PROJECT),Redeploy 即生效。
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
该 PR 为当前 Next.js(部署在 Vercel)的站点接入 Sentry,用于补齐生产环境的错误可观测性(前端白屏、服务端异常、5xx 等)。
Changes:
- 引入
@sentry/nextjs依赖并更新 lockfile - 新增
sentry.{client,server,edge}.config.ts与instrumentation.ts,按 runtime 初始化 Sentry next.config.mjs增加withSentryConfig包装以支持 sourcemap 上传与 logger tree-shaking,并在.env.sample补充相关变量说明
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| sentry.client.config.ts | 浏览器端 Sentry 初始化与采样策略配置 |
| sentry.server.config.ts | Node.js runtime(API/RSC)Sentry 初始化配置 |
| sentry.edge.config.ts | Edge runtime(如 Middleware)Sentry 初始化配置 |
| instrumentation.ts | Next instrumentation hook:按 runtime 动态加载对应配置并导出 onRequestError |
| next.config.mjs | 条件启用 withSentryConfig 上传 sourcemap/关闭 logger |
| .env.sample | 增补 Sentry 相关环境变量与说明 |
| package.json | 新增 @sentry/nextjs 依赖 |
| pnpm-lock.yaml | 锁定新增依赖及其传递依赖版本 |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 守门条件:只有在存在 SENTRY_AUTH_TOKEN 时才启用 withSentryConfig。 | ||
| // 贡献者 clone 仓库后没配 Sentry env 也能直接 `pnpm build` / `pnpm dev`, | ||
| // 不会因为 webpack 插件缺凭据而构建失败。生产 Vercel 那边 env 齐全,正常上报。 | ||
| const enableSentry = Boolean(process.env.SENTRY_AUTH_TOKEN); | ||
|
|
||
| export default enableSentry | ||
| ? withSentryConfig(finalConfig, { | ||
| org: process.env.SENTRY_ORG || "involutionhell", | ||
| project: process.env.SENTRY_PROJECT || "sentry-bole-notebook", |
There was a problem hiding this comment.
enableSentry 只检查 SENTRY_AUTH_TOKEN,但 org/project 采用硬编码 fallback。这样在本地/CI 里只要误设置了 token(但没设 org/project)就可能把 sourcemap 上传到默认项目,产生混淆或污染错误归因。建议把启用条件改为同时要求 SENTRY_AUTH_TOKEN && SENTRY_ORG && SENTRY_PROJECT,或去掉 fallback 并在缺失时显式失败/跳过上传。
| // 守门条件:只有在存在 SENTRY_AUTH_TOKEN 时才启用 withSentryConfig。 | |
| // 贡献者 clone 仓库后没配 Sentry env 也能直接 `pnpm build` / `pnpm dev`, | |
| // 不会因为 webpack 插件缺凭据而构建失败。生产 Vercel 那边 env 齐全,正常上报。 | |
| const enableSentry = Boolean(process.env.SENTRY_AUTH_TOKEN); | |
| export default enableSentry | |
| ? withSentryConfig(finalConfig, { | |
| org: process.env.SENTRY_ORG || "involutionhell", | |
| project: process.env.SENTRY_PROJECT || "sentry-bole-notebook", | |
| // 守门条件:只有在存在完整的 Sentry env 时才启用 withSentryConfig。 | |
| // 贡献者 clone 仓库后没配 Sentry env 也能直接 `pnpm build` / `pnpm dev`, | |
| // 不会因为 webpack 插件缺凭据而构建失败。生产 Vercel 那边 env 齐全,正常上报。 | |
| const enableSentry = Boolean( | |
| process.env.SENTRY_AUTH_TOKEN && | |
| process.env.SENTRY_ORG && | |
| process.env.SENTRY_PROJECT, | |
| ); | |
| export default enableSentry | |
| ? withSentryConfig(finalConfig, { | |
| org: process.env.SENTRY_ORG, | |
| project: process.env.SENTRY_PROJECT, |
| # SDK 只在 NODE_ENV=production 启用,本地 dev/preview 不会产生事件、不耗配额。 | ||
| # Vercel 端由 Sentry 集成自动注入;本地 dev 可不填。 |
There was a problem hiding this comment.
.env.sample 里写“本地 dev/preview 不会产生事件”,但当前实现只用 NODE_ENV === "production" 控制;在 Vercel Preview 部署中 NODE_ENV 同样是 production,实际上仍可能上报事件并消耗配额。建议在示例说明里补充真实条件(例如结合 VERCEL_ENV),或同步调整代码使其与文档一致。
| # SDK 只在 NODE_ENV=production 启用,本地 dev/preview 不会产生事件、不耗配额。 | |
| # Vercel 端由 Sentry 集成自动注入;本地 dev 可不填。 | |
| # 当前是否上报事件取决于代码中的启用条件;若仅判断 NODE_ENV=production, | |
| # 则 Vercel Preview(其 NODE_ENV 通常也是 production)也可能上报并消耗配额。 | |
| # 如需仅在正式生产环境上报,代码中应额外结合 VERCEL_ENV=production 等条件。 | |
| # Vercel 端可由 Sentry 集成自动注入;本地 dev 可不填。 |
| Sentry.init({ | ||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||
| enabled: process.env.NODE_ENV === "production", |
There was a problem hiding this comment.
enabled 目前只依赖 NODE_ENV === "production",但在 Vercel Preview/本地 next build 场景里 NODE_ENV 也可能是 production,导致预览环境也会上报并消耗配额。建议把启用条件改成同时校验部署环境(例如 process.env.VERCEL_ENV === "production")并且 DSN 存在(!!process.env.NEXT_PUBLIC_SENTRY_DSN),以避免误上报/SDK 初始化告警。
| Sentry.init({ | |
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | |
| enabled: process.env.NODE_ENV === "production", | |
| const isSentryEnabled = | |
| process.env.NODE_ENV === "production" && | |
| process.env.VERCEL_ENV === "production" && | |
| !!process.env.NEXT_PUBLIC_SENTRY_DSN; | |
| Sentry.init({ | |
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | |
| enabled: isSentryEnabled, |
| Sentry.init({ | ||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||
| enabled: process.env.NODE_ENV === "production", |
There was a problem hiding this comment.
这里同样建议在 enabled 上额外校验 DSN 是否存在(避免 production 下 DSN 漏配时 SDK 初始化产生告警/无意义开销),并结合实际部署环境(如 Vercel 的 VERCEL_ENV)区分 production vs preview,避免预览环境也上报占用配额。
| Sentry.init({ | |
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | |
| enabled: process.env.NODE_ENV === "production", | |
| const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; | |
| const isProductionDeployment = | |
| process.env.VERCEL_ENV != null | |
| ? process.env.VERCEL_ENV === "production" | |
| : process.env.NODE_ENV === "production"; | |
| Sentry.init({ | |
| dsn, | |
| enabled: Boolean(dsn) && isProductionDeployment, |
| * 当前项目未使用 edge runtime,保留配置以便未来迁移时无需补齐。 | ||
| */ | ||
| import * as Sentry from "@sentry/nextjs"; | ||
|
|
||
| Sentry.init({ | ||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||
| enabled: process.env.NODE_ENV === "production", |
There was a problem hiding this comment.
文件头注释说“当前项目未使用 edge runtime”,但仓库里已有 middleware.ts(默认运行在 Edge runtime),因此这段说明不准确且可能误导后续维护。建议更新注释,说明该配置用于 middleware/edge routes,并明确启用策略(例如是否仅 production + DSN 存在时启用)。
| * 当前项目未使用 edge runtime,保留配置以便未来迁移时无需补齐。 | |
| */ | |
| import * as Sentry from "@sentry/nextjs"; | |
| Sentry.init({ | |
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | |
| enabled: process.env.NODE_ENV === "production", | |
| * 当前配置用于 Next.js 的 middleware 及其他 Edge runtime 入口。 | |
| * 仅在 production 且已配置 NEXT_PUBLIC_SENTRY_DSN 时启用,避免本地/未配置环境误报。 | |
| */ | |
| import * as Sentry from "@sentry/nextjs"; | |
| Sentry.init({ | |
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | |
| enabled: | |
| process.env.NODE_ENV === "production" && | |
| Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN), |
动机
PR #295 在服务端加了防刷护甲,但站点 crash / 后端 5xx / 前端白屏等生产事故目前完全看不见。接入 Sentry 最低成本(免费 Developer tier)补监控。
白嫖计算
改动
@sentry/nextjssentry.{client,server,edge}.config.ts:三个 runtime 各自初始化,同策略instrumentation.ts:Next 15+ 的启动 hook,按 runtime 动态 import 对应配置next.config.mjs:withSentryConfig包一层,自动上传 source map + tree-shake 掉 Sentry logger 省 bundle配额保护(自己给自己加锁)
enabled: NODE_ENV === 'production'tracesSampleRate: 0.1replaysSessionSampleRate: 0贡献者友好
不是所有贡献者都有 Sentry 账号,所以:
```js
const enableSentry = Boolean(process.env.SENTRY_AUTH_TOKEN);
export default enableSentry ? withSentryConfig(finalConfig, {...}) : finalConfig;
```
pnpm dev/pnpm build完全不触发 webpack 插件,零报错env -u SENTRY_* pnpm build验证通过部署须知
Vercel 集成已自动注入 4 个 env(
NEXT_PUBLIC_SENTRY_DSN/SENTRY_AUTH_TOKEN/SENTRY_ORG/SENTRY_PROJECT),最新一条 Deployment → Redeploy 后生效。验证计划
pnpm typecheck通过pnpm build有 / 无 Sentry env 两种场景都通过throw new Error("sentry-smoke-test")然后访问),确认 Sentry Dashboard 收到不在本 PR 范围(单独跟进)
/openai/responses/stream可直烧 OpenAI 付费额度,应该在 Java 层加 per-user rate-limit 或 Caddy 层加请求签名