Skip to content

feat(monitoring): 接入 Sentry 错误监控#296

Merged
longsizhuo merged 1 commit intomainfrom
feat/sentry-integration
Apr 17, 2026
Merged

feat(monitoring): 接入 Sentry 错误监控#296
longsizhuo merged 1 commit intomainfrom
feat/sentry-integration

Conversation

@longsizhuo
Copy link
Copy Markdown
Member

动机

PR #295 在服务端加了防刷护甲,但站点 crash / 后端 5xx / 前端白屏等生产事故目前完全看不见。接入 Sentry 最低成本(免费 Developer tier)补监控。

白嫖计算

项目 免费额度 我们的估算用量 余量
Errors 5K / 月 健康站点 ~100/月 充足
Performance units 10K / 月 每 transaction = 1 unit, 10% 采样 × 5K 页面 PV/月 = 500 充足
Session Replay 50/月 关闭(改天流量大再开)

改动

  • @sentry/nextjs
  • sentry.{client,server,edge}.config.ts:三个 runtime 各自初始化,同策略
  • instrumentation.ts:Next 15+ 的启动 hook,按 runtime 动态 import 对应配置
  • next.config.mjswithSentryConfig 包一层,自动上传 source map + tree-shake 掉 Sentry logger 省 bundle

配额保护(自己给自己加锁)

策略 代码 理由
本地 dev 完全不发 enabled: NODE_ENV === 'production' 避免开发期污染配额 / 制造假警报
Trace 只采 10% tracesSampleRate: 0.1 够看 P75 趋势,不爆配额
关闭 Session Replay replaysSessionSampleRate: 0 Replay 是独立配额类,关掉省心
关闭 Profiling 不启用 SDK Profiling 是付费

贡献者友好

不是所有贡献者都有 Sentry 账号,所以:

```js
const enableSentry = Boolean(process.env.SENTRY_AUTH_TOKEN);
export default enableSentry ? withSentryConfig(finalConfig, {...}) : finalConfig;
```

  • 没配 Sentry env 的贡献者 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 两种场景都通过
  • Redeploy 后手动触发一次错误(随便在某个 page 里 throw new Error("sentry-smoke-test") 然后访问),确认 Sentry Dashboard 收到

不在本 PR 范围(单独跟进)

  1. Java 后端绕过 Upstash 限流的漏洞:登录用户 curl /openai/responses/stream 可直烧 OpenAI 付费额度,应该在 Java 层加 per-user rate-limit 或 Caddy 层加请求签名
  2. Sentry 深度集成:User feedback widget / Release tracking / Performance alerts,按需再加

为生产环境加错误捕获与 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 即生效。
@longsizhuo longsizhuo requested review from Crokily and Copilot April 16, 2026 20:38
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
involutionhell-github-io Ready Ready Preview, Comment Apr 16, 2026 9:16pm
website-preview Ready Ready Preview, Comment Apr 16, 2026 9:16pm

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 为当前 Next.js(部署在 Vercel)的站点接入 Sentry,用于补齐生产环境的错误可观测性(前端白屏、服务端异常、5xx 等)。

Changes:

  • 引入 @sentry/nextjs 依赖并更新 lockfile
  • 新增 sentry.{client,server,edge}.config.tsinstrumentation.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.

Comment thread next.config.mjs
Comment on lines +142 to +150
// 守门条件:只有在存在 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",
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enableSentry 只检查 SENTRY_AUTH_TOKEN,但 org/project 采用硬编码 fallback。这样在本地/CI 里只要误设置了 token(但没设 org/project)就可能把 sourcemap 上传到默认项目,产生混淆或污染错误归因。建议把启用条件改为同时要求 SENTRY_AUTH_TOKEN && SENTRY_ORG && SENTRY_PROJECT,或去掉 fallback 并在缺失时显式失败/跳过上传。

Suggested change
// 守门条件:只有在存在 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,

Copilot uses AI. Check for mistakes.
Comment thread .env.sample
Comment on lines +36 to +37
# SDK 只在 NODE_ENV=production 启用,本地 dev/preview 不会产生事件、不耗配额。
# Vercel 端由 Sentry 集成自动注入;本地 dev 可不填。
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.env.sample 里写“本地 dev/preview 不会产生事件”,但当前实现只用 NODE_ENV === "production" 控制;在 Vercel Preview 部署中 NODE_ENV 同样是 production,实际上仍可能上报事件并消耗配额。建议在示例说明里补充真实条件(例如结合 VERCEL_ENV),或同步调整代码使其与文档一致。

Suggested change
# SDK 只在 NODE_ENV=production 启用,本地 dev/preview 不会产生事件、不耗配额。
# Vercel 端由 Sentry 集成自动注入;本地 dev 可不填。
# 当前是否上报事件取决于代码中的启用条件;若仅判断 NODE_ENV=production,
# 则 Vercel Preview(其 NODE_ENV 通常也是 production)也可能上报并消耗配额。
# 如需仅在正式生产环境上报,代码中应额外结合 VERCEL_ENV=production 等条件。
# Vercel 端可由 Sentry 集成自动注入;本地 dev 可不填。

Copilot uses AI. Check for mistakes.
Comment thread sentry.client.config.ts
Comment on lines +12 to +14
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
enabled: process.env.NODE_ENV === "production",
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabled 目前只依赖 NODE_ENV === "production",但在 Vercel Preview/本地 next build 场景里 NODE_ENV 也可能是 production,导致预览环境也会上报并消耗配额。建议把启用条件改成同时校验部署环境(例如 process.env.VERCEL_ENV === "production")并且 DSN 存在(!!process.env.NEXT_PUBLIC_SENTRY_DSN),以避免误上报/SDK 初始化告警。

Suggested change
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,

Copilot uses AI. Check for mistakes.
Comment thread sentry.server.config.ts
Comment on lines +7 to +9
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
enabled: process.env.NODE_ENV === "production",
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里同样建议在 enabled 上额外校验 DSN 是否存在(避免 production 下 DSN 漏配时 SDK 初始化产生告警/无意义开销),并结合实际部署环境(如 Vercel 的 VERCEL_ENV)区分 production vs preview,避免预览环境也上报占用配额。

Suggested change
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,

Copilot uses AI. Check for mistakes.
Comment thread sentry.edge.config.ts
Comment on lines +3 to +9
* 当前项目未使用 edge runtime,保留配置以便未来迁移时无需补齐。
*/
import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
enabled: process.env.NODE_ENV === "production",
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

文件头注释说“当前项目未使用 edge runtime”,但仓库里已有 middleware.ts(默认运行在 Edge runtime),因此这段说明不准确且可能误导后续维护。建议更新注释,说明该配置用于 middleware/edge routes,并明确启用策略(例如是否仅 production + DSN 存在时启用)。

Suggested change
* 当前项目未使用 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),

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants