Loading...
Loading...
Compare original and translation side by side
All Skills > SDK Setup > NestJS SDK
所有技能 > SDK设置 > NestJS SDK
@sentry/nestjsNote: SDK versions and APIs below reflect10.x (NestJS 8–11 supported). Always verify against docs.sentry.io/platforms/node/guides/nestjs/ before implementing.@sentry/nestjs
@sentry/nestjs注意: 下方的SDK版本和API对应10.x(支持NestJS 8–11)。 实现前请务必查阅docs.sentry.io/platforms/node/guides/nestjs/确认最新内容。@sentry/nestjs
undefinedundefined
**What to note:**
- Is `@sentry/nestjs` already installed? If yes, check if `instrument.ts` exists and `Sentry.init()` is called — may just need feature config.
- **Sentry DI wrapper detected?** → The project wraps Sentry behind a DI token (e.g. `SENTRY_PROXY_TOKEN`) for testability. Use the injected proxy for all runtime Sentry calls (`startSpan`, `captureException`, `withIsolationScope`) instead of importing `@sentry/nestjs` directly in controllers, services, and processors. Only `instrument.ts` should import `@sentry/nestjs` directly.
- **Config class detected?** → The project uses a typed config class for `Sentry.init()` options (e.g. loaded from YAML or `@nestjs/config`). Any new SDK options must be added to the config type — do not hardcode values that should be configurable per environment.
- **`SentryModule.forRoot()` already registered?** → If it's in a shared module (e.g. a Sentry proxy module), do not add it again in `AppModule` — this causes duplicate interceptor registration.
- Express (default) or Fastify adapter? Express is fully supported; Fastify works but has known edge cases.
- GraphQL detected? → `SentryGlobalFilter` handles it natively.
- Microservices detected? → Recommend RPC exception filter.
- Task queues / `@nestjs/schedule`? → Recommend crons.
- AI libraries? → Auto-instrumented, zero config.
- Prisma? → Requires manual `prismaIntegration()`.
- Companion frontend? → Triggers Phase 4 cross-link.
---
**需要注意的要点:**
- 是否已安装`@sentry/nestjs`?如果已安装,检查是否存在`instrument.ts`以及是否调用了`Sentry.init()`——可能只需要配置功能即可。
- **检测到Sentry DI封装?** → 项目通过DI token(例如`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的交叉推荐。
---@sentry/profiling-node@nestjs/schedule| Feature | Recommend when... | Reference |
|---|---|---|
| Error Monitoring | Always — non-negotiable baseline | |
| Tracing | Always — NestJS lifecycle is auto-instrumented | |
| Profiling | Production + CPU-sensitive workloads | |
| Logging | Always; enhanced for structured log aggregation | |
| Metrics | Custom business KPIs or SLO tracking | |
| Crons | | |
| AI Monitoring | OpenAI/Anthropic/LangChain/etc. detected | |
@sentry/profiling-node@nestjs/schedule| 功能 | 推荐场景 | 参考文档 |
|---|---|---|
| 错误监控 | 始终推荐——必备基础能力 | |
| 链路追踪 | 始终推荐——NestJS生命周期自动埋点 | |
| 性能分析 | 生产环境+CPU敏感型工作负载 | |
| 日志记录 | 始终推荐;增强结构化日志聚合能力 | |
| 指标监控 | 自定义业务KPI或SLO追踪 | |
| 定时任务监控 | 检测到 | |
| AI监控 | 检测到OpenAI/Anthropic/LangChain等时 | |
undefinedundefined
> ⚠️ **Do NOT install `@sentry/node` alongside `@sentry/nestjs`** — `@sentry/nestjs` re-exports everything from `@sentry/node`. Installing both causes duplicate registration.
> ⚠️ **不要同时安装`@sentry/node`和`@sentry/nestjs`**——`@sentry/nestjs`已经重导出了`@sentry/node`的所有内容。同时安装会导致重复注册。Before creating new files, check Phase 1 results:
- If
already exists → modify it, don't create a new one.instrument.ts- If a config class drives
→ read options from the config instead of hardcoding env vars.Sentry.init()- If a Sentry DI wrapper exists → use it for runtime calls instead of importing
directly in services/controllers.@sentry/nestjs
创建新文件前,查看阶段1的检测结果:
- 如果
已存在→修改它,不要新建。instrument.ts- 如果存在配置类驱动
→从配置读取选项,不要硬编码环境变量。Sentry.init()- 如果存在Sentry DI封装→运行时调用使用封装实例,不要在服务/控制器中直接导入
。@sentry/nestjs
src/instrument.tssrc/instrument.tsimport * 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,
sendDefaultPii: true,
// 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()SentryConfigprocess.env@nestjs/configimport * 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,
sendDefaultPii: config.sentry.sendDefaultPii ?? true,
tracesSampleRate: config.sentry.tracesSampleRate ?? 1.0,
profileSessionSampleRate: config.sentry.profilesSampleRate ?? 1.0,
profileLifecycle: "trace",
enableLogs: true,
});sendDefaultPiiprofileSessionSampleRateimport * 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,
sendDefaultPii: true,
// 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()SentryConfigprocess.env@nestjs/configimport * 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,
sendDefaultPii: config.sentry.sendDefaultPii ?? true,
tracesSampleRate: config.sentry.tracesSampleRate ?? 1.0,
profileSessionSampleRate: config.sentry.profilesSampleRate ?? 1.0,
profileLifecycle: "trace",
enableLogs: true,
});sendDefaultPiiprofileSessionSampleRateinstrument.tssrc/main.tssrc/main.tsinstrument.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();Why first? OpenTelemetry must monkey-patch,http, database drivers, and other modules before they load. Any module that loads beforeexpresswill not be auto-instrumented.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
SentryModuleSentryGlobalFiltersrc/app.module.tssrc/app.module.tsSentryModuleSentryGlobalFilterimport { 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()SentryTracingInterceptorAPP_INTERCEPTORSentryGlobalFilterBaseExceptionFilterHttpException⚠️ Do NOT registertwice. If Phase 1 found it already imported in a shared library module (e.g. aSentryModule.forRoot()orSentryProxyModule), do not add it again inAnalyticsModule. Duplicate registration causes every span to be intercepted twice, bloating trace data.AppModule
⚠️ Two entrypoints, different imports:
→ SDK init, capture APIs, decorators (@sentry/nestjs,SentryTraced,SentryCron)SentryExceptionCaptured → NestJS DI constructs (@sentry/nestjs/setup,SentryModule)SentryGlobalFilterNever importfromSentryModule(main entrypoint) — it loads@sentry/nestjsbefore OpenTelemetry patches it, breaking auto-instrumentation.@nestjs/common
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()SentryTracingInterceptorAPP_INTERCEPTORSentryGlobalFilterBaseExceptionFilterHttpException⚠️ 不要重复注册。 如果阶段1检测到它已经在共享库模块(例如SentryModule.forRoot()或SentryProxyModule)中导入,不要在AnalyticsModule中再次添加。重复注册会导致每个span被拦截两次,导致 trace 数据冗余。AppModule
⚠️ 两个入口点,不同导入方式:
→ SDK初始化、捕获API、装饰器(@sentry/nestjs、SentryTraced、SentryCron)SentryExceptionCaptured → NestJS DI 构造(@sentry/nestjs/setup、SentryModule)SentryGlobalFilter永远不要从(主入口)导入@sentry/nestjs——它会在OpenTelemetry补丁前加载SentryModule,导致自动埋点失效。@nestjs/common
--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--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 startSentryGlobalFilterSentryGlobalFilter@SentryExceptionCaptured()@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
}
}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
}
}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);
}
}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);
}
}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());
}
}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?)@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() { ... }
}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?)@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
}
}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.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_PROXY_TOKEN@sentry/nestjsimport { 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/nestjsinstrument.tsimport * as Sentry from "@sentry/nestjs"Sentry.init()SENTRY_PROXY_TOKEN@sentry/nestjsimport { 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/nestjsinstrument.tsimport * as Sentry from "@sentry/nestjs"Sentry.init()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-sentryimport { 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| Feature | Reference file | Load when... |
|---|---|---|
| Error Monitoring | | Always (baseline) |
| Tracing | | Always (NestJS routes are auto-traced) |
| Profiling | | CPU-intensive production apps |
| Logging | | Structured log aggregation needed |
| Metrics | | Custom KPIs / SLO tracking |
| Crons | | Scheduled jobs or task queues |
| AI Monitoring | | OpenAI/Anthropic/LangChain detected |
Read ${SKILL_ROOT}/references/<feature>.md| 功能 | 参考文件 | 加载时机 |
|---|---|---|
| 错误监控 | | 始终(基础能力) |
| 链路追踪 | | 始终(NestJS路由自动追踪) |
| 性能分析 | | CPU密集型生产应用 |
| 日志记录 | | 需要结构化日志聚合 |
| 指标监控 | | 自定义KPI / SLO追踪 |
| 定时任务监控 | | 定时任务或任务队列场景 |
| AI监控 | | 检测到OpenAI/Anthropic/LangChain时 |
阅读${SKILL_ROOT}/references/<feature>.mdSentry.init()Sentry.init()| Option | Type | Default | Purpose |
|---|---|---|---|
| | — | SDK disabled if empty; env: |
| | | e.g., |
| | — | e.g., |
| | | Include IP addresses and request headers |
| | — | Transaction sample rate; |
| | — | Custom per-transaction sampling (overrides rate) |
| | — | URLs to propagate |
| | — | Continuous profiling session rate (SDK ≥ 10.27.0) |
| | | |
| | | Send structured logs to Sentry (SDK ≥ 9.41.0) |
| | | Error message patterns to suppress |
| | | Transaction name patterns to suppress |
| | — | Hook to mutate or drop error events |
| | — | Hook to mutate or drop transaction events |
| | — | Hook to mutate or drop log events |
| | | Verbose SDK debug output |
| | | Max breadcrumbs per event |
| 选项 | 类型 | 默认值 | 用途 |
|---|---|---|---|
| | — | 为空时SDK禁用;环境变量: |
| | | 例如 |
| | — | 例如 |
| | | 是否包含IP地址和请求头 |
| | — | 事务采样率; |
| | — | 自定义按事务采样(覆盖采样率) |
| `Array<string\ | RegExp>` | — |
| | — | 持续性能分析会话采样率(SDK ≥ 10.27.0) |
| `"trace"\ | "manual"` | |
| | | 发送结构化日志到Sentry(SDK ≥ 9.41.0) |
| `Array<string\ | RegExp>` | |
| `Array<string\ | RegExp>` | |
| | — | 修改或丢弃错误事件的钩子 |
| | — | 修改或丢弃事务事件的钩子 |
| | — | 修改或丢弃日志事件的钩子 |
| | | 输出SDK详细调试日志 |
| | | 每个事件的最大面包屑数量 |
| Variable | Maps to | Notes |
|---|---|---|
| | Used if |
| | Also auto-detected from git SHA, Heroku, CircleCI |
| | Falls back to |
| CLI/source maps | For |
| CLI/source maps | Organization slug |
| CLI/source maps | Project slug |
| 变量名 | 对应配置项 | 说明 |
|---|---|---|
| | 未向 |
| | 也会自动从git SHA、Heroku、CircleCI检测 |
| | 兜底值为 |
| CLI/源码映射 | 用于 |
| CLI/源码映射 | 组织slug |
| CLI/源码映射 | 项目slug |
integrations: [...]| Auto-enabled | Notes |
|---|---|
| Outgoing HTTP calls via |
| Express adapter (default NestJS) |
| NestJS lifecycle (middleware, guards, pipes, interceptors, handlers) |
| Uncaught exceptions |
| Unhandled promise rejections |
| OpenAI SDK (when installed) |
| Anthropic SDK (when installed) |
| LangChain (when installed) |
| GraphQL (when |
| |
| |
| MongoDB / Mongoose |
| |
integrations: [...]| 自动集成名 | 说明 |
|---|---|
| 通过 |
| Express适配器(NestJS默认) |
| NestJS生命周期(中间件、守卫、管道、拦截器、处理函数) |
| 未捕获异常 |
| 未处理Promise拒绝 |
| OpenAI SDK(安装时自动激活) |
| Anthropic SDK(安装时自动激活) |
| LangChain(安装时自动激活) |
| GraphQL(存在 |
| |
| |
| MongoDB / Mongoose |
| |
| Integration | When to add | Code |
|---|---|---|
| Profiling desired | |
| Prisma ORM used | |
| Capture console output | |
| Capture local var values in errors | |
| 集成名 | 添加场景 | 代码 |
|---|---|---|
| 需要性能分析 | |
| 使用Prisma ORM | |
| 捕获控制台输出 | |
| 捕获错误中的局部变量值 | |
// 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");debug: trueSentry.init()SENTRY_DSNimport "./instrument"main.tsSentryModule.forRoot()AppModulehttps://<key>@o<org>.ingest.sentry.io/<project>// 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: trueSENTRY_DSNimport "./instrument"main.tsSentryModule.forRoot()AppModulehttps://<key>@o<org>.ingest.sentry.io/<project>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"'| Frontend detected | Suggest skill |
|---|---|
| Next.js | |
| React | |
| Svelte / SvelteKit | |
| Vue / Nuxt | Use |
| React Native / Expo | |
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"'| 检测到的前端 | 推荐技能 |
|---|---|
| Next.js | |
| React | |
| Svelte / SvelteKit | |
| Vue / Nuxt | 使用 |
| React Native / Expo | |
| Issue | Solution |
|---|---|
| Events not appearing | Set |
| Malformed DSN error | Format: |
| Exceptions not captured | Ensure |
| Auto-instrumentation not working | |
| Profiling not starting | Requires |
| Requires SDK ≥ 9.41.0 |
| No traces appearing | Verify |
| Too many transactions | Lower |
| Fastify + GraphQL issues | Known edge cases — see GitHub #13388; prefer Express for GraphQL |
| Background job events mixed | Wrap job body in |
| Prisma spans missing | Add |
| ESM syntax errors | Set |
| Must import from |
| RPC exceptions not captured | Add dedicated |
| WebSocket exceptions not captured | Use |
| Decorator order matters — |
| TypeScript path alias issues | Ensure |
| Many projects ban namespace imports. Use named imports ( |
| |
| Duplicate spans on every request | |
Config property not recognized in | When using a typed config class, new SDK options must be added to the config type definition and the project rebuilt before TypeScript recognizes them |
| 问题 | 解决方案 |
|---|---|
| 没有收到事件 | 设置 |
| DSN格式错误 | 格式要求: |
| 异常未捕获 | 确保 |
| 自动埋点不生效 | |
| 性能分析未启动 | 需要 |
| 需要SDK ≥ 9.41.0 |
| 没有trace数据 | 验证 |
| 事务数量过多 | 降低 |
| Fastify + GraphQL问题 | 已知边缘问题——参见GitHub #13388;GraphQL场景优先使用Express |
| 后台任务事件混杂 | 使用 |
| Prisma span缺失 | 在 |
| ESM语法错误 | 设置 |
| 必须从 |
| RPC异常未捕获 | 添加专用 |
| WebSocket异常未捕获 | 在网关 |
| 装饰器顺序很重要—— |
| TypeScript路径别名问题 | 确保 |
| 很多项目禁止命名空间导入。使用命名导入( |
| |
| 每个请求都有重复span | |
| 使用类型化配置类时,新的SDK选项必须添加到配置类型定义中,项目重建后TypeScript才能识别它们 |
| Feature | Minimum SDK Version |
|---|---|
| 8.0.0 |
| 8.15.0 |
| 8.16.0 |
| Event Emitter auto-instrumentation | 8.39.0 |
| 8.40.0 |
| 9.41.0 |
| 10.27.0 |
| Node.js requirement | ≥ 18 |
Node.js for ESM | ≥ 18.19.0 |
| NestJS compatibility | 8.x – 11.x |
| 功能 | 最低SDK版本 |
|---|---|
| 8.0.0 |
| 8.15.0 |
| 8.16.0 |
| Event Emitter自动埋点 | 8.39.0 |
| 8.40.0 |
| 9.41.0 |
| 10.27.0 |
| Node.js版本要求 | ≥ 18 |
ESM | ≥ 18.19.0 |
| NestJS兼容性 | 8.x – 11.x |
| ", |