关于 sentry-nestjs-sdk
面向 NestJS 项目的 Sentry 配置技能,会检查项目结构并逐步指导 SDK 接入。其内容覆盖 NestJS 初始化顺序、异常处理以及按需配置追踪、日志和定时任务监控。
主要功能
- 01检查 NestJS 版本及现有 Sentry 配置
- 02指导三文件初始化流程
- 03配置全局异常过滤器
- 04使用装饰器追踪方法和定时任务
- 05按项目需求配置日志与性能监控
适用场景
- 01为 NestJS 应用接入错误监控与追踪
- 02在已有全局过滤器中加入异常上报
- 03为定时任务或后台作业配置监控
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ getsentry/ sentry-for-ai --skill sentry-nestjs-sdk安装后在 Claude Code 中输入/sentry-nestjs-sdk确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ai-monitoring.mdcrons.mderror-monitoring.mdlogging.mdmetrics.mdprofiling.mdtracing.md详细介绍
Sentry NestJS SDK
这是一款具有明确约定的向导,可扫描 NestJS 项目并引导你完成 Sentry 的完整设置。
在以下情况下调用此技能
- 用户要求在 NestJS 应用中“添加 Sentry”或“设置 Sentry”
- 用户希望在 NestJS 中进行错误监控、追踪、性能分析、日志记录、指标监控或定时任务监控
- 用户提到
@sentry/nestjs或 Sentry + NestJS - 用户希望监控 NestJS 控制器、服务、守卫、微服务或后台作业
注意: 以下 SDK 版本和 API 适用于
@sentry/nestjs10.x(支持 NestJS 8–11)。 实施前,请务必对照 docs.sentry.io/platforms/node/guides/nestjs/ 进行验证。
阶段 1:检测
在提出建议前,运行以下命令以了解项目情况:
# Confirm NestJS project
grep -E '"@nestjs/core"' package.json 2>/dev/null
# Check NestJS version
node -e "console.log(require('./node_modules/@nestjs/core/package.json').version)" 2>/dev/null
# Check existing Sentry
grep -i sentry package.json 2>/dev/null
ls src/instrument.ts 2>/dev/null
grep -r "Sentry.init\|@sentry" src/main.ts src/instrument.ts 2>/dev/null
# Check for existing Sentry DI wrapper (common in enterprise NestJS)
grep -rE "SENTRY.*TOKEN|SentryProxy|SentryService" src/ libs/ 2>/dev/null
# Check for config-class-based init (vs env-var-based)
grep -rE "class SentryConfig|SentryConfig" src/ libs/ 2>/dev/null
# Check if SentryModule.forRoot() is already registered in a shared module
grep -rE "SentryModule\.forRoot|SentryProxyModule" src/ libs/ 2>/dev/null
# Detect HTTP adapter (default is Express)
grep -E "FastifyAdapter|@nestjs/platform-fastify" package.json src/main.ts 2>/dev/null
# Detect GraphQL
grep -E '"@nestjs/graphql"|"apollo-server"' package.json 2>/dev/null
# Detect microservices
grep '"@nestjs/microservices"' package.json 2>/dev/null
# Detect WebSockets
grep -E '"@nestjs/websockets"|"socket.io"' package.json 2>/dev/null
# Detect task queues / scheduled jobs
grep -E '"@nestjs/bull"|"@nestjs/bullmq"|"@nestjs/schedule"|"bullmq"|"bull"' package.json 2>/dev/null
# Detect databases
grep -E '"@prisma/client"|"typeorm"|"mongoose"|"pg"|"mysql2"' package.json 2>/dev/null
# Detect AI libraries
grep -E '"openai"|"@anthropic-ai"|"langchain"|"@langchain"|"@google/generative-ai"|"ai"' package.json 2>/dev/null
# Check for companion frontend
ls -d ../frontend ../web ../client ../ui 2>/dev/null
需要注意的事项:
- 是否已安装
@sentry/nestjs?如果已安装,请检查是否存在instrument.ts,以及是否调用了Sentry.init()——可能只需配置功能。 - 检测到 Sentry DI 包装器? → 项目通过 DI 令牌(例如
SENTRY_PROXY_TOKEN)封装 Sentry,以便进行测试。在所有运行时 Sentry 调用中(startSpan、captureException、withIsolationScope),请使用注入的代理,而不要在控制器、服务和处理器中直接导入@sentry/nestjs。只有instrument.ts应直接导入@sentry/nestjs。 - 检测到配置类? → 项目使用类型化配置类设置
Sentry.init()选项(例如从 YAML 或@nestjs/config加载)。任何新增的 SDK 选项都必须加入配置类型——不要对本应按环境配置的值进行硬编码。 - 是否已注册
SentryModule.forRoot()? → 如果它已在共享模块中(例如 Sentry 代理模块),请勿在AppModule中重复添加,否则会导致拦截器重复注册。 - 使用的是 Express(默认)还是 Fastify 适配器?Express 完全受支持;Fastify 可以使用,但存在已知边缘情况。
- 检测到 GraphQL?→
SentryGlobalFilter可原生处理。 - 检测到微服务?→ 建议使用 RPC 异常过滤器。
- 检测到任务队列 /
@nestjs/schedule?→ 建议使用定时任务监控。 - 检测到 AI 库?→ 会自动插桩,无需配置。
- 检测到 Prisma?→ 需要手动配置
prismaIntegration()。 - 是否配有前端项目?→ 会触发阶段 4 的交叉链接。
阶段 2:推荐
根据你的发现,提出具体方案。不要提出开放式问题——直接给出推荐:
始终推荐(核心覆盖):
- ✅ 错误监控 — 捕获 HTTP、GraphQL、RPC 和 WebSocket 上下文中的未处理异常
- ✅ 追踪 — 自动检测中间件、守卫、管道、拦截器、过滤器和路由处理程序
检测到以下情况时推荐:
- ✅ 性能分析 — CPU 性能至关重要的生产应用(
@sentry/profiling-node) - ✅ 日志记录 — 结构化 Sentry Logs + 可选的控制台捕获
- ✅ 定时任务 — 检测到
@nestjs/schedule、Bull 或 BullMQ - ✅ 指标 — 业务 KPI 或 SLO 跟踪
- ✅ AI 监控 — 检测到 OpenAI/Anthropic/LangChain 等(自动检测,无需配置)
推荐矩阵:
| 功能 | 推荐条件 | 参考资料 |
|---|---|---|
| 错误监控 | 始终 — 不可妥协的基础要求 | ${SKILL_ROOT}/references/error-monitoring.md |
| 追踪 | 始终 — NestJS 生命周期会自动检测 | ${SKILL_ROOT}/references/tracing.md |
| 性能分析 | 生产环境 + 对 CPU 敏感的工作负载 | ${SKILL_ROOT}/references/profiling.md |
| 日志记录 | 始终推荐;结构化日志聚合场景下效果更佳 | ${SKILL_ROOT}/references/logging.md |
| 指标 | 自定义业务 KPI 或 SLO 跟踪 | ${SKILL_ROOT}/references/metrics.md |
| 定时任务 | 检测到 @nestjs/schedule、Bull 或 BullMQ | ${SKILL_ROOT}/references/crons.md |
| AI 监控 | 检测到 OpenAI/Anthropic/LangChain 等 | ${SKILL_ROOT}/references/ai-monitoring.md |
提出建议:"我推荐错误监控 + 追踪 + 日志记录。还需要性能分析、定时任务或 AI 监控吗?"
阶段 3:引导
安装
# Core SDK (always required — includes @sentry/node)
npm install @sentry/nestjs
# With profiling support (optional)
npm install @sentry/nestjs @sentry/profiling-node
⚠️ 不要同时安装
@sentry/node和@sentry/nestjs—@sentry/nestjs会重新导出@sentry/node的所有内容。两者同时安装会导致重复注册。
三文件设置(必需)
NestJS 要求采用特定的三文件初始化模式,因为 Sentry SDK 必须在 NestJS 加载 Node.js 模块之前修补这些模块(通过 OpenTelemetry)。
创建新文件之前,请先检查阶段 1 的结果:
- 如果
instrument.ts已存在 → 修改该文件,不要新建。- 如果配置类负责调用
Sentry.init()→ 从配置中读取选项,而不是将环境变量写死。- 如果存在 Sentry DI 封装 → 运行时调用应使用该封装,而不是在服务/控制器中直接导入
@sentry/nestjs。
步骤 1:创建 src/instrument.ts
import * as Sentry from "@sentry/nestjs";
// Optional: add profiling
// import { nodeProfilingIntegration } from "@sentry/profiling-node";
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.SENTRY_ENVIRONMENT ?? "production",
release: process.env.SENTRY_RELEASE,
// Data collection (SDK ≥ 10.57.0 — replaces deprecated sendDefaultPii)
dataCollection: {
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
// https://docs.sentry.io/platforms/javascript/guides/nestjs/configuration/options/#dataCollection
// userInfo: false,
// httpBodies: [],
},
// Tracing — lower to 0.1–0.2 in high-traffic production
tracesSampleRate: 1.0,
// Profiling (requires @sentry/profiling-node)
// integrations: [nodeProfilingIntegration()],
// profileSessionSampleRate: 1.0,
// profileLifecycle: "trace",
// Structured logs (SDK ≥ 9.41.0)
enableLogs: true,
});
由配置驱动的 Sentry.init(): 如果阶段 1 发现了类型化配置类(例如 SentryConfig),请从中读取选项,而不是直接使用 process.env。使用 @nestjs/config 或自定义配置加载器的 NestJS 应用通常会采用这种方式:
import * as Sentry from "@sentry/nestjs";
import { loadConfiguration } from "./config";
const config = loadConfiguration();
Sentry.init({
dsn: config.sentry.dsn,
environment: config.sentry.environment ?? "production",
release: config.sentry.release,
dataCollection: config.sentry.dataCollection ?? {
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
// https://docs.sentry.io/platforms/javascript/guides/nestjs/configuration/options/#dataCollection
// userInfo: false,
// httpBodies: [],
},
tracesSampleRate: config.sentry.tracesSampleRate ?? 1.0,
profileSessionSampleRate: config.sentry.profilesSampleRate ?? 1.0,
profileLifecycle: "trace",
enableLogs: true,
});
添加新的 SDK 选项(例如 dataCollection、profileSessionSampleRate)时,请将其加入配置类型,以便按环境进行配置。
步骤 2:在 src/main.ts 中最先导入 instrument.ts
// instrument.ts MUST be the very first import — before NestJS or any other module
import "./instrument";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Enable graceful shutdown — flushes Sentry events on SIGTERM/SIGINT
app.enableShutdownHooks();
await app.listen(3000);
}
bootstrap();
为什么要最先导入? OpenTelemetry 必须在
http、express、数据库驱动程序和其他模块加载之前对其进行猴子补丁。任何在instrument.ts之前加载的模块都不会被自动检测。
步骤 3:在 src/app.module.ts 中注册 SentryModule 和 SentryGlobalFilter
import { Module } from "@nestjs/common";
import { APP_FILTER } from "@nestjs/core";
import { SentryModule, SentryGlobalFilter } from "@sentry/nestjs/setup";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
@Module({
imports: [
SentryModule.forRoot(), // Registers SentryTracingInterceptor globally
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_FILTER,
useClass: SentryGlobalFilter, // Captures all unhandled exceptions
},
],
})
export class AppModule {}
各部分的作用:
SentryModule.forRoot()— 将SentryTracingInterceptor注册为全局APP_INTERCEPTOR,以启用 HTTP 事务命名SentryGlobalFilter— 扩展BaseExceptionFilter;捕获 HTTP、GraphQL(重新抛出HttpException,不进行报告)和 RPC 上下文中的异常
⚠️ 不要重复注册
SentryModule.forRoot()。 如果阶段 1 发现它已在共享库模块(例如SentryProxyModule或AnalyticsModule)中导入,请勿在AppModule中再次添加。重复注册会导致每个 span 被拦截两次,使追踪数据膨胀。
⚠️ 两个入口点,导入内容不同:
@sentry/nestjs→ SDK 初始化、捕获 API、装饰器(SentryTraced、SentryCron、SentryExceptionCaptured)@sentry/nestjs/setup→ NestJS DI 构造(SentryModule、SentryGlobalFilter)切勿从
@sentry/nestjs(主入口点)导入SentryModule— 它会在 OpenTelemetry 修补前加载@nestjs/common,从而破坏自动插桩。
ESM 设置(Node ≥ 18.19.0)
对于 ESM 应用,请使用 --import,而不是文件导入:
// instrument.mjs
import * as Sentry from "@sentry/nestjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});
// package.json
{
"scripts": {
"start": "node --import ./instrument.mjs -r ts-node/register src/main.ts"
}
}
或者通过环境变量设置:
NODE_OPTIONS="--import ./instrument.mjs" npm run start
异常过滤器选项
选择适合现有架构的方案:
选项 A:没有现有的全局过滤器 — 使用 SentryGlobalFilter(推荐)
已在上面的步骤 3 中介绍。这是最简单的选项。
选项 B:已有自定义全局过滤器 — 添加 @SentryExceptionCaptured() 装饰器
import { Catch, ExceptionFilter, ArgumentsHost } from "@nestjs/common";
import { SentryExceptionCaptured } from "@sentry/nestjs";
@Catch()
export class YourExistingFilter implements ExceptionFilter {
@SentryExceptionCaptured() // Wraps catch() to auto-report exceptions
catch(exception: unknown, host: ArgumentsHost): void {
// Your existing error handling continues unchanged
}
}
选项 C:特定异常类型 — 手动捕获
import { ArgumentsHost, Catch } from "@nestjs/common";
import { BaseExceptionFilter } from "@nestjs/core";
import * as Sentry from "@sentry/nestjs";
@Catch(ExampleException)
export class ExampleExceptionFilter extends BaseExceptionFilter {
catch(exception: ExampleException, host: ArgumentsHost) {
Sentry.captureException(exception);
super.catch(exception, host);
}
}
选项 D:微服务 RPC 异常
import { Catch, RpcExceptionFilter, ArgumentsHost } from "@nestjs/common";
import { Observable, throwError } from "rxjs";
import { RpcException } from "@nestjs/microservices";
import * as Sentry from "@sentry/nestjs";
@Catch(RpcException)
export class SentryRpcFilter implements RpcExceptionFilter<RpcException> {
catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
Sentry.captureException(exception);
return throwError(() => exception.getError());
}
}
装饰器
@SentryTraced(op?) — 为任意方法插桩
import { Injectable } from "@nestjs/common";
import { SentryTraced } from "@sentry/nestjs";
@Injectable()
export class OrderService {
@SentryTraced("order.process")
async processOrder(orderId: string): Promise<void> {
// Automatically wrapped in a Sentry span
}
@SentryTraced() // Defaults to op: "function"
async fetchInventory() { ... }
}
@SentryCron(slug, config?) — 监控计划任务
import { Injectable } from "@nestjs/common";
import { Cron } from "@nestjs/schedule";
import { SentryCron } from "@sentry/nestjs";
@Injectable()
export class ReportService {
@Cron("0 * * * *")
@SentryCron("hourly-report", {
// @SentryCron must come AFTER @Cron
schedule: { type: "crontab", value: "0 * * * *" },
checkinMargin: 2, // Minutes before marking missed
maxRuntime: 10, // Max runtime in minutes
timezone: "UTC",
})
async generateReport() {
// Check-in sent automatically on start/success/failure
}
}
后台任务作用域隔离
后台任务共享默认隔离作用域 — 使用 Sentry.withIsolationScope() 包装,以防止相互污染:
import * as Sentry from "@sentry/nestjs";
import { Injectable } from "@nestjs/common";
import { Cron, CronExpression } from "@nestjs/schedule";
@Injectable()
export class JobService {
@Cron(CronExpression.EVERY_HOUR)
handleCron() {
Sentry.withIsolationScope(() => {
Sentry.setTag("job", "hourly-sync");
this.doWork();
});
}
}
将 withIsolationScope 应用于:@Cron()、@Interval()、@OnEvent()、@Processor(),以及请求生命周期之外的任何代码。
使用 Sentry DI 包装器
一些 NestJS 项目会通过依赖注入令牌(例如 SENTRY_PROXY_TOKEN)封装 Sentry,以提高可测试性并实现解耦。如果阶段 1 检测到此模式,所有运行时 Sentry 调用都应使用注入的服务 — 不要在控制器、服务或处理器中直接导入 @sentry/nestjs。
import { Controller, Inject } from "@nestjs/common";
import { SENTRY_PROXY_TOKEN, type SentryProxyService } from "./sentry-proxy";
@Controller("orders")
export class OrderController {
constructor(
@Inject(SENTRY_PROXY_TOKEN) private readonly sentry: SentryProxyService,
private readonly orderService: OrderService,
) {}
@Post()
async createOrder(@Body() dto: CreateOrderDto) {
return this.sentry.startSpan(
{ name: "createOrder", op: "http" },
async () => this.orderService.create(dto),
);
}
}
仍适合直接导入 @sentry/nestjs 的情况:
instrument.ts— 始终使用import * as Sentry from "@sentry/nestjs"来调用Sentry.init()- 在 DI 容器外运行的独立脚本和异常过滤器
验证
添加一个测试端点,以确认事件已到达 Sentry:
import { Controller, Get } from "@nestjs/common";
import * as Sentry from "@sentry/nestjs";
@Controller()
export class DebugController {
@Get("/debug-sentry")
triggerError() {
throw new Error("My first Sentry error from NestJS!");
}
@Get("/debug-sentry-span")
triggerSpan() {
return Sentry.startSpan({ op: "test", name: "NestJS Test Span" }, () => {
return { status: "span created" };
});
}
}
访问 GET /debug-sentry,并在几秒后检查 Sentry Issues 面板。
对每项约定的功能
逐项处理功能。加载参考文件,按其中的步骤操作,并在继续之前进行验证:
| 功能 | 参考文件 | 加载时机 |
|---|---|---|
| 错误监控 | ${SKILL_ROOT}/references/error-monitoring.md | 始终加载(基线) |
| 跟踪 | ${SKILL_ROOT}/references/tracing.md | 始终加载(NestJS 路由会自动跟踪) |
| 性能分析 | ${SKILL_ROOT}/references/profiling.md | CPU 密集型生产应用 |
| 日志记录 | ${SKILL_ROOT}/references/logging.md | 需要聚合结构化日志 |
| 指标 | ${SKILL_ROOT}/references/metrics.md | 自定义 KPI / SLO 跟踪 |
| 定时任务 | ${SKILL_ROOT}/references/crons.md | 定时作业或任务队列 |
| AI 监控 | ${SKILL_ROOT}/references/ai-monitoring.md | 检测到 OpenAI/Anthropic/LangChain |
对于每项功能:Read ${SKILL_ROOT}/references/<feature>.md,严格按照步骤操作,并验证其是否正常工作。
配置参考
Sentry.init() 的关键选项
| 选项 | 类型 | 默认值 | 用途 |
|---|---|---|---|
dsn | string | — | 为空时禁用 SDK;环境变量:SENTRY_DSN |
environment | string | "production" | 例如,"staging";环境变量:SENTRY_ENVIRONMENT |
release | string | — | 例如,"[email protected]";环境变量:SENTRY_RELEASE |
dataCollection | object | 见下文 | 控制 SDK 收集的数据(SDK ≥ 10.57.0) |
dataCollection.userInfo | boolean | true | 包含 IP 地址和用户上下文 |
dataCollection.httpHeaders | object | 见下文 | 捕获请求/响应的 HTTP 标头 |
dataCollection.cookies | boolean|object | true | 捕获 Cookie;使用 {allow: [...]} 或 {deny: [...]} 进行筛选 |
dataCollection.queryParams | boolean|object | true | 捕获 URL 查询参数;使用 {allow: [...]} 或 {deny: [...]} 进行筛选 |
dataCollection.genAI | object | 见下文 | 控制 AI 输入/输出记录 |
sendDefaultPii | boolean | false | 已弃用 — 请改用 dataCollection.userInfo |
tracesSampleRate | number | — | 事务采样率;undefined 会禁用追踪 |
tracesSampler | function | — | 自定义每笔事务的采样(优先于采样率) |
tracePropagationTargets | Array<string|RegExp> | — | 要向其传播 sentry-trace/baggage 标头的 URL |
profileSessionSampleRate | number | — | 连续性能分析会话采样率(SDK ≥ 10.27.0) |
profileLifecycle | "trace"|"manual" | "trace" | "trace" = 随跨度自动启动性能分析器;"manual" = 调用 startProfiler()/stopProfiler() |
enableLogs | boolean | false | 将结构化日志发送到 Sentry(SDK ≥ 9.41.0) |
ignoreErrors | Array<string|RegExp> | [] | 要忽略的错误消息模式 |
ignoreTransactions | Array<string|RegExp> | [] | 要忽略的事务名称模式 |
beforeSend | function | — | 用于修改或丢弃错误事件的钩子 |
beforeSendTransaction | function | — | 用于修改或丢弃事务事件的钩子 |
beforeSendLog | function | — | 用于修改或丢弃日志事件的钩子 |
debug | boolean | false | SDK 详细调试输出 |
maxBreadcrumbs | number | 100 | 每个事件的面包屑上限 |
dataCollection 默认值: |
httpHeaders: { request: true, response: true }httpBodies: ["incomingRequest", "outgoingRequest", "incomingResponse", "outgoingResponse"]userInfo: truegenAI: { inputs: true, outputs: true }
环境变量
| 变量 | 映射到 | 说明 |
|---|---|---|
SENTRY_DSN | dsn | 如果未向 init() 传入 dsn,则使用此值 |
SENTRY_RELEASE | release | 也会从 git SHA、Heroku、CircleCI 自动检测 |
SENTRY_ENVIRONMENT | environment | 默认回退到 "production" |
SENTRY_AUTH_TOKEN | CLI/source maps | 用于 npx @sentry/wizard@latest -i sourcemaps |
SENTRY_ORG | CLI/source maps | 组织标识 |
SENTRY_PROJECT | CLI/source maps | 项目标识 |
自动启用的集成
检测到相应软件包时,这些集成会自动激活——无需配置 integrations: [...]:
| 自动启用项 | 说明 |
|---|---|
httpIntegration | 通过 http/https/fetch 发出的 HTTP 请求 |
expressIntegration | Express 适配器(NestJS 默认) |
nestIntegration | NestJS 生命周期(中间件、守卫、管道、拦截器、处理程序) |
onUncaughtExceptionIntegration | 未捕获的异常 |
onUnhandledRejectionIntegration | 未处理的 Promise 拒绝 |
openAIIntegration | OpenAI SDK(已安装时) |
anthropicAIIntegration | Anthropic SDK(已安装时) |
langchainIntegration | LangChain(已安装时) |
graphqlIntegration | GraphQL(存在 graphql 软件包时) |
postgresIntegration | pg 驱动程序 |
mysqlIntegration | mysql / mysql2 |
mongoIntegration | MongoDB / Mongoose |
redisIntegration | ioredis / redis |
需要手动设置的集成
| 集成 | 添加条件 | 代码 |
|---|---|---|
nodeProfilingIntegration | 需要性能分析 | import { nodeProfilingIntegration } from "@sentry/profiling-node" |
prismaIntegration | 使用 Prisma ORM | integrations: [Sentry.prismaIntegration()] |
consoleLoggingIntegration | 捕获控制台输出 | integrations: [Sentry.consoleLoggingIntegration()] |
localVariablesIntegration | 在错误中捕获局部变量值 | integrations: [Sentry.localVariablesIntegration()] |
验证
测试 Sentry 是否正在接收事件:
// Add a test endpoint (remove before production)
@Get("/debug-sentry")
getError() {
throw new Error("My first Sentry error!");
}
或者发送一条测试消息,且不触发崩溃:
import * as Sentry from "@sentry/nestjs";
Sentry.captureMessage("NestJS Sentry SDK test");
如果没有任何内容显示:
- 在
Sentry.init()中设置debug: true— 将 SDK 内部信息打印到标准输出 - 确认运行中的进程已设置
SENTRY_DSN环境变量 - 检查
import "./instrument"是否是main.ts中的第一行 - 确认
AppModule中已导入SentryModule.forRoot() - 检查 DSN 格式:
https://<key>@o<org>.ingest.sentry.io/<project>
第 4 阶段:交叉链接
完成 NestJS 设置后,检查是否有尚未配置 Sentry 的配套前端:
ls -d ../frontend ../web ../client ../ui 2>/dev/null
cat ../frontend/package.json ../web/package.json 2>/dev/null \
| grep -E '"react"|"svelte"|"vue"|"next"|"nuxt"'
如果存在尚未配置 Sentry 的前端,建议使用匹配的技能:
| 检测到的前端 | 建议的技能 |
|---|---|
| Next.js | sentry-nextjs-sdk |
| React | sentry-react-sdk |
| Svelte / SvelteKit | sentry-svelte-sdk |
| Vue / Nuxt | 使用 @sentry/vue — 参见 docs.sentry.io/platforms/javascript/guides/vue/ |
| React Native / Expo | sentry-react-native-sdk |
故障排除
| 问题 | 解决方案 |
|---|---|
| 未显示事件 | 设置 debug: true,验证 SENTRY_DSN,检查是否首先导入了 instrument.ts |
| DSN 格式错误 | 格式:https://<key>@o<org>.ingest.sentry.io/<project> |
| 未捕获异常 | 确保通过 AppModule 中的 APP_FILTER 注册了 SentryGlobalFilter |
| 自动插桩不起作用 | instrument.ts 必须是 main.ts 中的第一个导入项,位于所有 NestJS 导入之前 |
| 未启动性能分析 | 需要 tracesSampleRate > 0、profileSessionSampleRate > 0,并已安装 @sentry/profiling-node |
enableLogs 不起作用 | 需要 SDK ≥ 9.41.0 |
| 未显示跟踪 | 验证已设置 tracesSampleRate(而不是 undefined) |
| 事务过多 | 降低 tracesSampleRate,或使用 tracesSampler 丢弃健康检查 |
| Fastify + GraphQL 问题 | 已知边缘情况——参见 GitHub #13388;GraphQL 建议使用 Express |
| 后台作业事件混杂 | 将作业主体包装在 Sentry.withIsolationScope(() => { ... }) 中 |
| 缺少 Prisma 跨度 | 将 integrations: [Sentry.prismaIntegration()] 添加到 Sentry.init() |
| ESM 语法错误 | 设置 registerEsmLoaderHooks: false(禁用 ESM 钩子;也会禁用 ESM 模块的自动插桩) |
SentryModule 破坏插桩 | 必须从 @sentry/nestjs/setup 导入,切勿从 @sentry/nestjs 导入 |
| 未捕获 RPC 异常 | 添加专用的 SentryRpcExceptionFilter(参见异常过滤器部分中的选项 D) |
| 未捕获 WebSocket 异常 | 在网关的 handleConnection/handleDisconnect 上使用 @SentryExceptionCaptured() |
@SentryCron 未触发 | 装饰器顺序很重要——@SentryCron 必须放在 @Cron 之后 |
| TypeScript 路径别名问题 | 确保已配置 tsconfig.json 中的 paths,使 instrument 能从 main.ts 所在位置解析 |
import * as Sentry ESLint 错误 | 许多项目禁止命名空间导入。请使用具名导入(import { startSpan, captureException } from "@sentry/nestjs"),或改用项目的 DI 代理 |
profilesSampleRate 与 profileSessionSampleRate | profilesSampleRate 在 SDK 10.x 中已弃用。请改用 profileSessionSampleRate + profileLifecycle: "trace" |
| 每个请求都出现重复跨度 | 在多个模块中注册了 SentryModule.forRoot()。请确保只调用一次——检查共享模块/库模块 |
instrument.ts 中无法识别配置属性 | 使用类型化配置类时,必须将新的 SDK 选项添加到配置类型定义中,并在 TypeScript 识别这些选项之前重新构建项目 |
版本要求
| 功能 | SDK 最低版本 |
|---|---|
@sentry/nestjs 包 | 8.0.0 |
@SentryTraced 装饰器 | 8.15.0 |
@SentryCron 装饰器 | 8.16.0 |
| Event Emitter 自动插桩 | 8.39.0 |
SentryGlobalFilter(统一版) | 8.40.0 |
Sentry.logger API(enableLogs) | 9.41.0 |
profileSessionSampleRate | 10.27.0 |
| Node.js 要求 | ≥ 18 |
ESM --import 所需的 Node.js 版本 | ≥ 18.19.0 |
| NestJS 兼容性 | 8.x – 11.x |