Skip to content

Commit 411aab2

Browse files
committed
feat(monitoring): 接入 Sentry 错误监控(免费 Developer tier)
为生产环境加错误捕获与 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 即生效。
1 parent 495d49a commit 411aab2

8 files changed

Lines changed: 1481 additions & 33 deletions

.env.sample

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ INTERN_KEY=
2929
# 智谱 AI 开放平台 API Key,聊天与建议接口的默认免费模型 GLM-4.6V-Flash
3030
# 在 https://open.bigmodel.cn/ 注册后获取
3131
ZHIPU_API_KEY=
32+
33+
# Sentry 错误监控(Developer plan 免费 5K errors / 10K perf units / 月)
34+
# NEXT_PUBLIC_SENTRY_DSN 是浏览器端需要的公开 DSN,暴露在前端 bundle 里属于设计,
35+
# SENTRY_AUTH_TOKEN 仅用于 next build 时上传 source map,私密。
36+
# SDK 只在 NODE_ENV=production 启用,本地 dev/preview 不会产生事件、不耗配额。
37+
# Vercel 端由 Sentry 集成自动注入;本地 dev 可不填。
38+
NEXT_PUBLIC_SENTRY_DSN=
39+
SENTRY_AUTH_TOKEN=
40+
SENTRY_ORG=involutionhell
41+
SENTRY_PROJECT=sentry-bole-notebook
3242
# Neon 项目 ID
3343
NEON_PROJECT_ID=
3444
# Neon 提供的 Postgres 连接。

instrumentation.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Next.js 15+ 约定的启动 hook:每个 runtime 启动时各自拉对应 Sentry 配置,
3+
* 避免在 edge runtime 错误加载 Node-only 代码。
4+
*
5+
* onRequestError 暴露给 Next.js 捕获服务端组件/路由层面的未捕获错误。
6+
*/
7+
import * as Sentry from "@sentry/nextjs";
8+
9+
export async function register() {
10+
if (process.env.NEXT_RUNTIME === "nodejs") {
11+
await import("./sentry.server.config");
12+
}
13+
if (process.env.NEXT_RUNTIME === "edge") {
14+
await import("./sentry.edge.config");
15+
}
16+
}
17+
18+
export const onRequestError = Sentry.captureRequestError;

next.config.mjs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// next.config.mjs
22
import { createMDX } from "fumadocs-mdx/next";
33
import createNextIntlPlugin from "next-intl/plugin";
4+
import { withSentryConfig } from "@sentry/nextjs";
45

56
/**
67
* IMPORTANT: remarkImage 配置已移至 source.config.ts 统一管理
@@ -131,4 +132,26 @@ const config = {
131132
},
132133
};
133134

134-
export default withNextIntl(withMDX(config));
135+
const finalConfig = withNextIntl(withMDX(config));
136+
137+
// Sentry 包裹:webpack 插件需要看到最终的 Next 配置才能上传 source map。
138+
// silent: !CI 让本地构建不刷日志,只在 Vercel CI 构建时打印。
139+
// widenClientFileUpload 扩大 source map 扫描范围,保证前端错误堆栈能解出来。
140+
// disableLogger 树摇掉 Sentry 自带 logger,减小 bundle 体积。
141+
//
142+
// 守门条件:只有在存在 SENTRY_AUTH_TOKEN 时才启用 withSentryConfig。
143+
// 贡献者 clone 仓库后没配 Sentry env 也能直接 `pnpm build` / `pnpm dev`,
144+
// 不会因为 webpack 插件缺凭据而构建失败。生产 Vercel 那边 env 齐全,正常上报。
145+
const enableSentry = Boolean(process.env.SENTRY_AUTH_TOKEN);
146+
147+
export default enableSentry
148+
? withSentryConfig(finalConfig, {
149+
org: process.env.SENTRY_ORG || "involutionhell",
150+
project: process.env.SENTRY_PROJECT || "sentry-bole-notebook",
151+
silent: !process.env.CI,
152+
widenClientFileUpload: true,
153+
disableLogger: true,
154+
// 不启用 tunnelRoute:需要加 /monitoring rewrite,和现有 rewrites 交互
155+
// 复杂;广告屏蔽对 docs 站影响小,后续真需要再打开。
156+
})
157+
: finalConfig;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@radix-ui/react-radio-group": "^1.3.8",
4646
"@radix-ui/react-slot": "^1.2.3",
4747
"@radix-ui/react-tooltip": "^1.2.8",
48+
"@sentry/nextjs": "^10.49.0",
4849
"@types/mdx": "^2.0.13",
4950
"@types/pg": "^8.16.0",
5051
"@vercel/speed-insights": "^1.2.0",

pnpm-lock.yaml

Lines changed: 1384 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sentry.client.config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Sentry 浏览器端初始化。
3+
*
4+
* 免费 tier 策略(Developer plan,5K errors/月 + 10K perf units/月):
5+
* - 只在 production 启用,避免本地 dev/preview 污染配额
6+
* - tracesSampleRate 0.1:10% 的页面 transaction 采样足够看性能趋势
7+
* - 关闭 Session Replay:它是另外的独立配额(小),开了容易炸
8+
* - 不启用 profiling(需要付费)
9+
*/
10+
import * as Sentry from "@sentry/nextjs";
11+
12+
Sentry.init({
13+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
14+
enabled: process.env.NODE_ENV === "production",
15+
tracesSampleRate: 0.1,
16+
replaysSessionSampleRate: 0,
17+
replaysOnErrorSampleRate: 0,
18+
// 线上开 false 省日志;排障时临时改 true
19+
debug: false,
20+
});

sentry.edge.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Sentry Edge runtime 初始化(Middleware / Edge routes)。
3+
* 当前项目未使用 edge runtime,保留配置以便未来迁移时无需补齐。
4+
*/
5+
import * as Sentry from "@sentry/nextjs";
6+
7+
Sentry.init({
8+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
9+
enabled: process.env.NODE_ENV === "production",
10+
tracesSampleRate: 0.1,
11+
debug: false,
12+
});

sentry.server.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Sentry Node.js runtime 初始化(Next.js API routes / Server Components / RSC)。
3+
* 与 client 同策略:仅 production 启用,traces 10%,无 replay/profiling。
4+
*/
5+
import * as Sentry from "@sentry/nextjs";
6+
7+
Sentry.init({
8+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
9+
enabled: process.env.NODE_ENV === "production",
10+
tracesSampleRate: 0.1,
11+
debug: false,
12+
});

0 commit comments

Comments
 (0)