Skip to main content
skill CX Codex

sentry-node-sdk — Claude Code skill: Sentry for Node.js, Bun, Deno

A wizard skill that scans your backend project and walks you through Sentry setup for server-side JavaScript and TypeScript runtimes.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add getsentry/sentry-for-ai --skill sentry-node-sdk -a claude-code
Open on GitHub

What sentry-node-sdk does

The skill starts by inspecting the project instead of asking questions. It checks which runtime is present (node, bun, deno), greps package.json for @sentry/* packages, and looks for Express, Fastify, Koa, Hapi, Elysia, Hono, logging libraries like winston and pino, schedulers such as node-cron and Bull, and LLM clients. It also works out whether the project is ESM or CommonJS and whether an instrument.js or instrument.mjs file already exists — if one does, the skill merges into it rather than overwriting.

Then it leads with a proposal. Error monitoring and tracing are the baseline; everything else depends on what it found. Profiling is Node.js only, so on Bun and Deno it is off the table. If OpenTelemetry tracing is already in the project, the skill routes you to the OTLP path via otlpIntegration() and tells you not to set tracesSampleRate; native tracing and profiling are skipped in that case. NestJS and Next.js projects get pointed at sentry-nestjs-sdk and sentry-nextjs-sdk instead.

One thing to watch: the SDK versions referenced in the skill match Sentry docs at the time it was written, so verify them before implementing. ESM projects need --import ./instrument.mjs, Bun uses --preload, and Deno pulls the package in as npm:@sentry/deno. That is where setup usually breaks.

What it helps with

  • wire Sentry into a backend running on Node.js, Bun or Deno
  • decide whether to use the OTLP path when OpenTelemetry is already present
  • add error monitoring to an Express, Fastify, Koa or Hapi app
  • catch missed and failed scheduled jobs
  • ship logs from winston or pino with trace correlation

Example prompts for the agent

  • add Sentry to my Node.js app
  • set up @sentry/bun for this project
  • configure error monitoring and tracing for Fastify

How to install sentry-node-sdk

1Skills CLI (Vercel)

npx skills add getsentry/sentry-for-ai --skill sentry-node-sdk -a claude-code

2Manually: put the files in place

~/.claude/skills/sentry-node-sdk/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/sentry-node-sdk/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about sentry-node-sdk

How do I install sentry-node-sdk in Claude?

Run npx skills add getsentry/sentry-for-ai --skill sentry-node-sdk -a claude-code. The skill lands at ~/.claude/skills/sentry-node-sdk/SKILL.md.

What does sentry-node-sdk do?

It scans your project, identifies the runtime and framework, then guides you through Sentry setup: error monitoring, tracing, logging, profiling, metrics, crons and AI monitoring.

How is it different from sentry-nestjs-sdk and sentry-nextjs-sdk?

This one targets the Node.js, Bun and Deno server runtimes. NestJS projects need sentry-nestjs-sdk with its native decorators, and Next.js needs sentry-nextjs-sdk for the three-runtime architecture.

Source text

SKILL.md · Apache-2.0
---
name: sentry-node-sdk
description: Full Sentry SDK setup for Node.js, Bun, and Deno. Use when asked to "add Sentry to Node.js", "add Sentry to Bun", "add Sentry to Deno", "install @sentry/node", "@sentry/bun", or "@sentry/deno", or configure error monitoring, tracing, logging, profiling, metrics, crons, or AI monitoring for server-side JavaScript/TypeScript runtimes.
license: Apache-2.0
category: sdk-setup
parent: sentry-sdk-setup
disable-model-invocation: true
---

> [All Skills](../../SKILL_TREE.md) > [SDK Setup](../sentry-sdk-setup/SKILL.md) > Node.js / Bun / Deno SDK

# Sentry Node.js / Bun / Deno SDK

Opinionated wizard that scans your project and guides you through complete Sentry setup for server-side JavaScript and TypeScript runtimes: Node.js, Bun, and Deno.

## Invoke This Skill When

- User asks to "add Sentry to Node.js", "Bun", or "Deno"
- User wants to install or configure `@sentry/node`, `@sentry/bun`, or `@sentry/deno`
- User wants error monitoring, tracing, logging, profiling, crons, metrics, or AI monitoring for a backend JS/TS app
- User asks about `instrument.js`, `--import ./instrument.mjs`, `bun --preload`, or `npm:@sentry/deno`
- User wants to monitor Express, Fastify, Koa, Hapi, Connect, Bun.serve(), or Deno.serve()

> **NestJS?** Use [`sentry-nestjs-sdk`](../sentry-nestjs-sdk/SKILL.md) instead — it uses `@sentry/nestjs` with NestJS-native decorators and filters.
> **Next.js?** Use [`sentry-nextjs-sdk`](../sentry-nextjs-sdk/SKILL.md) instead — it handles the three-runtime architecture (browser, server, edge).

> **Note:** SDK versions below reflect current Sentry docs at time of writing (`@sentry/node` ≥10.42.0, `@sentry/bun` ≥10.42.0, `@sentry/deno` ≥10.42.0).
> Always verify against [docs.sentry.io/platforms/javascript/guides/node/](https://docs.sentry.io/platforms/javascript/guides/node/) before implementing.

---

## Phase 1: Detect

Run these commands to identify the runtime, framework, and existing Sentry setup:

```bash
# Detect runtime
bun --version 2>/dev/null && echo "Bun detected"
deno --version 2>/dev/null && echo "Deno detected"
node --version 2>/dev/null && echo "Node.js detected"

# Detect existing Sentry packages
cat package.json 2>/dev/null | grep -E '"@sentry/'
cat deno.json deno.jsonc 2>/dev/null | grep -i sentry

# Detect Node.js framework
cat package.json 2>/dev/null | grep -E '"express"|"fastify"|"@hapi/hapi"|"koa"|"@nestjs/core"|"connect"'

# Detect Bun-specific frameworks
cat package.json 2>/dev/null | grep -E '"elysia"|"hono"'

# Detect Deno frameworks (deno.json imports)
cat deno.json deno.jsonc 2>/dev/null | grep -E '"oak"|"hono"|"fresh"'

# Detect module system (Node.js)
cat package.json 2>/dev/null | grep '"type"'
ls *.mjs *.cjs 2>/dev/null | head -5

# Detect existing instrument file
ls instrument.js instrument.mjs instrument.ts instrument.cjs 2>/dev/null

# Detect logging libraries
cat package.json 2>/dev/null | grep -E '"winston"|"pino"|"bunyan"'

# Detect cron / scheduling
cat package.json 2>/dev/null | grep -E '"node-cron"|"cron"|"agenda"|"bull"|"bullmq"'

# Detect AI / LLM usage
cat package.json 2>/dev/null | grep -E '"openai"|"@anthropic-ai"|"@langchain"|"@vercel/ai"|"@google/generative-ai"'

# Detect OpenTelemetry tracing
cat package.json 2>/dev/null | grep -E '"@opentelemetry/sdk-node"|"@opentelemetry/sdk-trace-node"|"@opentelemetry/sdk-trace-base"'
grep -rn "NodeTracerProvider\|trace\.getTracer\|startActiveSpan" \
  --include="*.ts" --include="*.js" --include="*.mjs" 2>/dev/null | head -5

# Check for companion frontend
ls frontend/ web/ client/ ui/ 2>/dev/null
cat package.json 2>/dev/null | grep -E '"react"|"vue"|"svelte"|"next"'
```

**What to determine:**

| Question | Impact |
|----------|--------|
| Which runtime? (Node.js / Bun / Deno) | Determines package, init pattern, and preload flag |
| Node.js: ESM or CJS? | ESM requires `--import ./instrument.mjs`; CJS uses `require("./instrument")` |
| Framework detected? | Determines which error handler to register |
| `@sentry/*` already installed? | Skip install, go straight to feature config |
| `instrument.js` / `instrument.mjs` already exists? | Merge into it rather than overwrite |
| Logging library detected? | Recommend Sentry Logs |
| Cron / job scheduler detected? | Recommend Crons monitoring |
| AI library detected? | Recommend AI Monitoring |
| OpenTelemetry tracing detected? | Use OTLP path instead of native tracing |
| Companion frontend found? | Trigger Phase 4 cross-link |

---

## Phase 2: Recommend

Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal:

**Route from OTel detection:**
- **OTel tracing detected** (`@opentelemetry/sdk-node` or `@opentelemetry/sdk-trace-node` in `package.json`, or `NodeTracerProvider` in source) → use OTLP path: `otlpIntegration()` via `@sentry/node-core/light`; do **not** set `tracesSampleRate`; Sentry links errors to OTel traces automatically

**Recommended (core coverage):**
- ✅ **Error Monitoring** — always; captures unhandled exceptions, promise rejections, and framework errors
- ✅ **Tracing** — automatic HTTP, DB, and queue instrumentation via OpenTelemetry

**Optional (enhanced observability):**
- ⚡ **Logging** — structured logs via `Sentry.logger.*`; recommend when `winston`/`pino`/`bunyan` or log search is needed
- ⚡ **Profiling** — continuous CPU profiling (Node.js only; not available on Bun or Deno); **not available with OTLP path**
- ⚡ **AI Monitoring** — OpenAI, Anthropic, LangChain, Vercel AI SDK; recommend when AI/LLM calls detected
- ⚡ **Crons** — detect missed or failed scheduled jobs; recommend when node-cron, Bull, or Agenda is detected
- ⚡ **Metrics** — custom counters, gauges, distributions; recommend when custom KPIs needed
- ⚡ **Runtime Metrics** — automatic collection of memory, CPU, and event loop metrics; `nodeRuntimeMetricsIntegration()` (Node.js) / `bunRuntimeMetricsIntegration()` (Bun)

**Recommendation logic:**

| Feature | Recommend when... |
|---------|------------------|
| Error Monitoring | **Always** — non-negotiable baseline |
| OTLP Integration | OTel tracing detected — **replaces** native Tracing |
| Tracing | **Always for server apps** — HTTP spans + DB spans are high-value; **skip if OTel tracing detected** |
| Logging | App uses winston, pino, bunyan, or needs log-to-trace correlation |
| Profiling | **Node.js only** — performance-critical service; native addon compatible; **skip if OTel tracing detected** (requires `tracesSampleRate`, incompatible with OTLP) |
| AI Monitoring | App calls OpenAI, Anthropic, LangChain, Vercel AI, or Google GenAI |
| Crons | App uses node-cron, Bull, BullMQ, Agenda, or any scheduled task pattern |
| Metrics | App needs custom counters, gauges, or histograms |
| Runtime Metrics | Any Node.js or Bun service wanting automatic memory/CPU/event-loop visibility |

**OTel tracing detected:** *"I see OpenTelemetry tracing in the project. I recommend Sentry's OTLP integration for tracing (via your existing OTel setup) + Error Monitoring + Sentry Logging [+ Metrics/Crons/AI Monitoring if applicable]. Shall I proceed?"*

**No OTel:** *"I recommend setting up Error Monitoring + Tracing. Want me to also add Logging or Profiling?"*

---

## Phase 3: Guide

### Runtime: Node.js

#### Option 1: Wizard (Recommended for Node.js)

> **You need to run this yourself** — the wizard opens a browser for login and requires interactive input that the agent can't handle. Copy-paste into your terminal:
>
> ```
> npx @sentry/wizard@latest -i node
> ```
>
> It handles login, org/project selection, SDK installation, `instrument.js` creation, and package.json script updates.
>
> **Once it finishes, come back and skip to [Verification](#verification).**

If the user skips the wizard, proceed with Option 2 (Manual Setup) below.

---

#### Option 2: Manual Setup — Node.js

##### Install

```bash
npm install @sentry/node --save
# or
yarn add @sentry/node
# or
pnpm add @sentry/node
```

##### Create the Instrument File

**CommonJS (`instrument.js`):**

```javascript
// instrument.js — must be loaded before all other modules
const Sentry = require("@sentry/node");

Sentry.init({
  dsn: process.env.SENTRY_DSN ?? "___DSN___",

  dataCollection: {
    // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
    // https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/#dataCollection
    // userInfo: false,
    // httpBodies: [],
  },

  // 100% in dev, lower in production
  tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,

  // Capture local variable values in stack frames
  includeLocalVariables: true,

  enableLogs: true,
});
```

**ESM (`instrument.mjs`):**

```javascript
// instrument.mjs — loaded via --import flag before any other module
import * as Sentry from "@sentry/node";

Sentry.init({
  dsn: process.env.SENTRY_DSN ?? "___DSN___",

  dataCollection: {
    // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
    // https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/#dataCollection
    // userInfo: false,
    // httpBodies: [],
  },
  tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
  includeLocalVariables: true,
  enableLogs: true,
});
```

##### Start Your App with Sentry Loaded First

**CommonJS** — add `require("./instrument")` as the very first line of your entry file:

```javascript
// app.js
require("./instrument"); // must be first

const express = require("express");
// ... rest of your app
```

**ESM** — use the `--import` flag so Sentry loads before all other modules (Node.js 18.19.0+ required):

```bash
node --import ./instrument.mjs app.mjs
```

Add to `package.json` scripts:

```json
{
  "scripts": {
    "start": "node --import ./instrument.mjs server.mjs",
    "dev": "node --import ./instrument.mjs --watch server.mjs"
  }
}
```

Or via environment variable (useful for wrapping existing start commands):

```bash
NODE_OPTIONS="--import ./instrument.mjs" npm start
```

##### Framework Error Handlers

Register the Sentry error handler **after all routes** so it can capture framework errors:

**Express:**

```javascript
const express = require("express");
const Sentry = require("@sentry/node");

const app = express();

// ... your routes

// Add AFTER all routes — captures 5xx errors by default
Sentry.setupExpressErrorHandler(app);

// Optional: capture 4xx errors too
// Sentry.setupExpressErrorHandler(app, {
//   shouldHandleError(error) { return error.status >= 400; },
// });

app.listen(3000);
```

**Fastify:**

```javascript
const Fastify = require("fastify");
const Sentry = require("@sentry/node");

const fastify = Fastify();

// Add BEFORE routes (unlike Express!)
Sentry.setupFastifyErrorHandler(fastify);

// ... your routes

await fastify.listen({ port: 3000 });
```

**Koa:**

```javascript
const Koa = require("koa");
const Sentry = require("@sentry/node");

const app = new Koa();

// Add as FIRST middleware (catches errors thrown by later middleware)
Sentry.setupKoaErrorHandler(app);

// ... your other middleware and routes

app.listen(3000);
```

**Hapi (async — must await):**

```javascript
const Hapi = require("@hapi/hapi");
const Sentry = require("@sentry/node");

const server = Hapi.server({ port: 3000 });

// ... your routes

// Must await — Hapi registration is async
await Sentry.setupHapiErrorHandler(server);

await server.start();
```

**Connect:**

```javascript
const connect = require("connect");
const Sentry = require("@sentry/node");

const app = connect();

// Add BEFORE routes (like Fastify and Koa)
Sentry.setupConnectErrorHandler(app);

// ... your middleware and routes

require("http").createServer(app).listen(3000);
```

**NestJS** — has its own dedicated skill with full coverage:

> **Use the [`sentry-nestjs-sdk`](../sentry-nestjs-sdk/SKILL.md) skill instead.**
> NestJS uses a separate package (`@sentry/nestjs`) with NestJS-native constructs:
> `SentryModule.forRoot()`, `SentryGlobalFilter`, `@SentryTraced`, `@SentryCron` decorators,
> and GraphQL/Microservices support. Load that skill for complete NestJS setup.

**Vanilla Node.js `http` module** — wrap request handler manually:

```javascript
const http = require("http");
const Sentry = require("@sentry/node");

const server = http.createServer((req, res) => {
  Sentry.withIsolationScope(() => {
    try {
      // your handler
      res.end("OK");
    } catch (err) {
      Sentry.captureException(err);
      res.writeHead(500);
      res.end("Internal Server Error");
    }
  });
});

server.listen(3000);
```

**Framework error handler summary:**

| Framework | Function | Placement | Async? |
|-----------|----------|-----------|--------|
| Express | `setupExpressErrorHandler(app)` | **After** all routes | No |
| Fastify | `setupFastifyErrorHandler(fastify)` | **Before** routes | No |
| Koa | `setupKoaErrorHandler(app)` | **First** middleware | No |
| Hapi | `setupHapiErrorHandler(server)` | Before `server.start()` | **Yes** |
| Connect | `setupConnectErrorHandler(app)` | **Before** routes | No |
| NestJS | → Use [`sentry-nestjs-sdk`](../sentry-nestjs-sdk/SKILL.md) | Dedicated skill | — |

---

### Runtime: Bun

> **No wizard available for Bun.** Manual setup only.

#### Install

```bash
bun add @sentry/bun
```

#### Create `instrument.ts` (or `instrument.js`)

```typescript
// instrument.ts
import * as Sentry from "@sentry/bun";

Sentry.init({
  dsn: process.env.SENTRY_DSN ?? "___DSN___",

  dataCollection: {
    // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
    // https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/#dataCollection
    // userInfo: false,
    // httpBodies: [],
  },
  tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
  enableLogs: true,
});
```

#### Start Your App with `--preload`

```bash
bun --preload ./instrument.ts server.ts
```

Add to `package.json`:

```json
{
  "scripts": {
    "start": "bun --preload ./instrument.ts server.ts",
    "dev": "bun --watch --preload ./instrument.ts server.ts"
  }
}
```

#### Bun.serve() — Auto-Instrumentation

`@sentry/bun` automatically instruments `Bun.serve()` via JavaScript Proxy. No extra setup is required — just initialize with `--preload` and your `Bun.serve()` calls are traced:

```typescript
// server.ts
const server = Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response("Hello from Bun!");
  },
});
```

#### Framework Error Handlers on Bun

Bun can run Express, Fastify, Hono, and Elysia. Use the same `@sentry/bun` import and the `@sentry/node` error handler functions (re-exported by `@sentry/bun`):

```typescript
import * as Sentry from "@sentry/bun";
import express from "express";

const app = express();
// ... routes
Sentry.setupExpressErrorHandler(app);
app.listen(3000);
```

#### Bun Feature Support

| Feature | Bun Support | Notes |
|---------|-------------|-------|
| Error Monitoring | ✅ Full | Same API as Node |
| Tracing | ✅ Via `@sentry/node` OTel | Most auto-instrumentations work |
| Logging | ✅ Full | `enableLogs: true` + `Sentry.logger.*` |
| Profiling | ❌ Not available | `@sentry/profiling-node` uses native addons incompatible with Bun |
| Metrics | ✅ Full | `Sentry.metrics.*` |
| Runtime Metrics | ✅ Full | `bunRuntimeMetricsIntegration()` — memory, CPU, event loop (no event loop delay percentiles) |
| Crons | ✅ Full | `Sentry.withMonitor()` |
| AI Monitoring | ✅ Full | OpenAI, Anthropic integrations work |

---

### Runtime: Deno

> **No wizard available for Deno.** Manual setup only.
> **Requires Deno 2.0+.** Deno 1.x is not supported.
> **Use `npm:` specifier.** The `deno.land/x/sentry` registry is deprecated.

#### Install via `deno.json` (Recommended)

```json
{
  "imports": {
    "@sentry/deno": "npm:@sentry/[email protected]"
  }
}
```

Or import directly with the `npm:` specifier:

```typescript
import * as Sentry from "npm:@sentry/deno";
```

#### Initialize — Add to Entry File

```typescript
// main.ts — Sentry.init() must be called before any other code
import * as Sentry from "@sentry/deno";

Sentry.init({
  dsn: Deno.env.get("SENTRY_DSN") ?? "___DSN___",

  dataCollection: {
    // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
    // https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/#dataCollection
    // userInfo: false,
    // httpBodies: [],
  },
  tracesSampleRate: Deno.env.get("DENO_ENV") === "development" ? 1.0 : 0.1,
  enableLogs: true,
});

// Your application code follows
Deno.serve({ port: 8000 }, (req) => {
  return new Response("Hello from Deno!");
});
```

> Unlike Node.js and Bun, Deno does not have a `--preload` or `--import` flag. Sentry must be the first `import` in your entry file.

#### Required Deno Permissions

The SDK requires network access to reach your Sentry ingest domain:

```bash
deno run \
  --allow-net=o<ORG_ID>.ingest.sentry.io \
  --allow-read=./src \
  --allow-env=SENTRY_DSN,SENTRY_RELEASE \
  main.ts
```

For development, `--allow-all` works but is not recommended for production.

#### Deno Cron Integration

Deno provides native cron scheduling. Use `denoCronIntegration` for automatic monitoring:

```typescript
import * as Sentry from "@sentry/deno";
import { denoCronIntegration } from "@sentry/deno";

Sentry.init({
  dsn: Deno.env.get("SENTRY_DSN") ?? "___DSN___",
  integrations: [denoCronIntegration()],
});

// Cron is automatically monitored
Deno.cron("daily-cleanup", "0 0 * * *", () => {
  // cleanup logic
});
```

#### Deno Feature Support

| Feature | Deno Support | Notes |
|---------|-------------|-------|
| Error Monitoring | ✅ Full | Unhandled exceptions + `captureException` |
| Tracing | ✅ Custom OTel | Automatic spans for `Deno.serve()` and `fetch` |
| Logging | ✅ Full | `enableLogs: true` + `Sentry.logger.*` |
| Profiling | ❌ Not available | No profiling addon for Deno |
| Metrics | ✅ Full | `Sentry.metrics.*` |
| Runtime Metrics | ❌ Not available | No runtime metrics integration for Deno |
| Crons | ✅ Full | `denoCronIntegration()` + `Sentry.withMonitor()` |
| AI Monitoring | ✅ Partial | Vercel AI SDK integration works; OpenAI/Anthropic via `npm:` |

---

### OTLP Integration (OTel-First Projects — Node.js Only)

> Use this path **only when OpenTelemetry tracing was detected** in Phase 1
> (e.g., `@opentelemetry/sdk-node` or `@opentelemetry/sdk-trace-node` in `package.json`).
> For projects without an existing OTel setup, use the standard `@sentry/node` path above.

The OTLP integration uses `@sentry/node-core/light` — a lightweight Sentry SDK that does not bundle its own OpenTelemetry. Instead, it hooks into the user's existing OTel `TracerProvider` and exports spans to Sentry via OTLP.

#### When to Use

| Scenario | Recommended path |
|----------|-----------------|
| New project, no existing OTel | Standard `@sentry/node` (above) — includes built-in OTel |
| Existing OTel setup, want Sentry tracing | `@sentry/node-core/light` + `otlpIntegration()` |
| Existing OTel setup, sending to own Collector | `@sentry/node-core/light` + `otlpIntegration({ collectorUrl })` |

#### Install

```bash
npm install @sentry/node-core @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base
# or
yarn add @sentry/node-core @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base
# or
pnpm add @sentry/node-core @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base
```

> The `@opentelemetry/*` packages are peer dependencies. If the project already has them installed, skip duplicates.

#### Initialize

```javascript
// instrument.mjs — load via --import flag before any other module
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import * as Sentry from '@sentry/node-core/light';
import { otlpIntegration } from '@sentry/node-core/light/otlp';

// Register the user's OTel TracerProvider first
const provider = new NodeTracerProvider();
provider.register();

Sentry.init({
  dsn: process.env.SENTRY_DSN ?? '___DSN___',

  dataCollection: {
    // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
    // https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/#dataCollection
    // userInfo: false,
    // httpBodies: [],
  },
  enableLogs: true,

  // Do NOT set tracesSampleRate — OTel controls sampling
  integrations: [
    otlpIntegration({
      // Export OTel spans to Sentry via OTLP (default: true)
      setupOtlpTracesExporter: true,
    }),
  ],
});
```

**With a custom Collector endpoint:**

```javascript
Sentry.init({
  dsn: process.env.SENTRY_DSN ?? '___DSN___',
  integrations: [
    otlpIntegration({
      collectorUrl: 'http://localhost:4318/v1/traces',
    }),
  ],
});
```

#### Start Your App

Same `--import` pattern as the standard Node.js setup:

```bash
node --import ./instrument.mjs app.mjs
```

#### Key Differences from Standard `@sentry/node`

| Aspect | `@sentry/node` (standard) | `@sentry/node-core/light` (OTLP) |
|--------|--------------------------|----------------------------------|
| OTel bundled | ✅ Yes — built-in TracerProvider | ❌ No — uses your existing provider |
| Tracing control | `tracesSampleRate` in `Sentry.init()` | OTel SDK controls sampling |
| Auto-instrumentation | ✅ Built-in (HTTP, DB, etc.) | ❌ You manage OTel instrumentations |
| Profiling | ✅ Available | ❌ Not compatible |
| Error ↔ trace linking | ✅ Automatic | ✅ Automatic (via `otlpIntegration`) |
| Package size | Larger (includes OTel) | Smaller (light mode) |

---

### For Each Agreed Feature

Load the corresponding reference file and follow its steps:

| Feature | Reference file | Load when... |
|---------|---------------|-------------|
| Error Monitoring | `references/error-monitoring.md` | Always (baseline) — captures, scopes, enrichment, beforeSend |
| OTLP Integration | See [OTLP Integration](#otlp-integration-otel-first-projects--nodejs-only) above | OTel tracing detected — **replaces** native Tracing |
| Tracing | `references/tracing.md` | OTel auto-instrumentation, custom spans, distributed tracing, sampling; **skip if OTel tracing detected** |
| Logging | `references/logging.md` | Structured logs, `Sentry.logger.*`, log-to-trace correlation |
| Profiling | `references/profiling.md` | Node.js only — CPU profiling, Bun/Deno gaps documented; **skip if OTel tracing detected** |
| Metrics | `references/metrics.md` | Custom counters, gauges, distributions |
| Runtime Metrics | See inline below | Automatic memory, CPU, and event loop metrics for Node.js and Bun |
| Crons | `references/crons.md` | Scheduled job monitoring, node-cron, Bull, Agenda, Deno.cron |
| AI Monitoring | Load `sentry-setup-ai-monitoring` skill | OpenAI, Anthropic, LangChain, Vercel AI, Google GenAI |

For each feature: read the reference file, follow its steps exactly, and verify before moving on.

### Runtime Metrics

Automatically collect Node.js and Bun runtime health metrics (memory, CPU utilization, event loop delay/utilization, uptime) at a configurable interval. Metrics appear in Sentry's Metrics product under the `node.runtime.*` / `bun.runtime.*` namespace.

**Node.js** — add `nodeRuntimeMetricsIntegration()` to your `instrument.js`:

```javascript
const Sentry = require("@sentry/node");

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [
    Sentry.nodeRuntimeMetricsIntegration(),
    // Optional: change collection interval (default 30 000 ms)
    // Sentry.nodeRuntimeMetricsIntegration({ collectionIntervalMs: 60_000 }),
  ],
});
```

Metrics collected by default: `node.runtime.mem.rss`, `node.runtime.mem.heap_used`, `node.runtime.mem.heap_total`, `node.runtime.cpu.utilization`, `node.runtime.event_loop.delay.p50`, `node.runtime.event_loop.delay.p99`, `node.runtime.event_loop.utilization`, `node.runtime.process.uptime`.

**Bun** — add `bunRuntimeMetricsIntegration()` to your `instrument.ts`:

```typescript
import * as Sentry from "@sentry/bun";
import { bunRuntimeMetricsIntegration } from "@sentry/bun";

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [
    bunRuntimeMetricsIntegration(),
    // Optional: change collection interval (default 30 000 ms)
    // bunRuntimeMetricsIntegration({ collectionIntervalMs: 60_000 }),
  ],
});
```

Metrics collected: same as Node.js except no event loop delay percentiles (unavailable in Bun). Prefixed with `bun.runtime.*`.

---

## Configuration Reference

### `Sentry.init()` Core Options

| Option | Type | Default | Notes |
|--------|------|---------|-------|
| `dsn` | `string` | — | Required. Also from `SENTRY_DSN` env var |
| `tracesSampleRate` | `number` | — | 0–1; required to enable tracing; **do not set when using OTLP path** |
| `dataCollection` | `object` | conservative unless set | Fine-grained control over auto-collected categories (`userInfo`, `cookies`, `httpHeaders`, `httpBodies`, `queryParams`, `genAI`). When omitted, the SDK falls back to `sendDefaultPii` (default `false`). Passing the object — even `{}` — flips unset categories to their permissive defaults; opt out per category. |
| `includeLocalVariables` | `boolean` | `false` | Add local variable values to stack frames (Node.js) |
| `enableLogs` | `boolean` | `false` | Enable Sentry Logs product (v9.41.0+) |
| `environment` | `string` | `"production"` | Also from `SENTRY_ENVIRONMENT` env var |
| `release` | `string` | — | Also from `SENTRY_RELEASE` env var |
| `debug` | `boolean` | `false` | Log SDK activity to console |
| `enabled` | `boolean` | `true` | Set `false` in tests to disable sending |
| `sampleRate` | `number` | `1.0` | Fraction of error events to send (0–1) |
| `shutdownTimeout` | `number` | `2000` | Milliseconds to flush events before process exit |

### `nativeNodeFetchIntegration()` Options

Configures outgoing `fetch`/`undici` span capture. Since `@opentelemetry/[email protected]`, response headers like `content-length` are no longer captured automatically — use `headersToSpanAttributes` to opt in:

```javascript
Sentry.init({
  integrations: [
    Sentry.nativeNodeFetchIntegration({
      headersToSpanAttributes: {
        requestHeaders: ["x-request-id"],
        responseHeaders: ["content-length", "content-type"],
      },
    }),
  ],
});
```

| Option | Type | Default | Notes |
|--------|------|---------|-------|
| `breadcrumbs` | `boolean` | `true` | Record breadcrumbs for outgoing fetch requests |
| `headersToSpanAttributes.requestHeaders` | `string[]` | — | Request header names to capture as span attributes |
| `headersToSpanAttributes.responseHeaders` | `string[]` | — | Response header names to capture as span attributes |

### `otlpIntegration()` Options (`@sentry/node-core/light/otlp`)

For OTel-first projects using `@sentry/node-core/light`. Import: `import { otlpIntegration } from '@sentry/node-core/light/otlp'`.

| Option | Type | Default | Purpose |
|--------|------|---------|---------|
| `setupOtlpTracesExporter` | `boolean` | `true` | Auto-configure OTLP exporter to send spans to Sentry; set `false` if you already export to your own Collector |
| `collectorUrl` | `string` | `undefined` | OTLP HTTP endpoint of an OTel Collector (e.g., `http://localhost:4318/v1/traces`); when set, spans are sent to the collector instead of the DSN-derived Sentry endpoint |

### Graceful Shutdown

Flush buffered events before process exit — important for short-lived scripts and serverless:

```javascript
process.on("SIGTERM", async () => {
  await Sentry.close(2000); // flush with 2s timeout
  process.exit(0);
});
```

### Environment Variables

| Variable | Purpose | Runtime |
|----------|---------|---------|
| `SENTRY_DSN` | DSN (alternative to hardcoding in `init()`) | All |
| `SENTRY_ENVIRONMENT` | Deployment environment | All |
| `SENTRY_RELEASE` | Release version string (auto-detected from git) | All |
| `SENTRY_AUTH_TOKEN` | Source map upload token | Build time |
| `SENTRY_ORG` | Org slug for source map upload | Build time |
| `SENTRY_PROJECT` | Project slug for source map upload | Build time |
| `NODE_OPTIONS` | Set `--import ./instrument.mjs` for ESM | Node.js |

### Source Maps (Node.js)

Readable stack traces in production require uploading source maps with `@sentry/cli` or the webpack/esbuild/rollup plugins — for example, an inject + upload step in your build:

```json
{
  "scripts": {
    "build": "tsc && sentry-cli sourcemaps inject ./dist && sentry-cli sourcemaps upload ./dist"
  }
}
```

Upload needs a `SENTRY_AUTH_TOKEN` (a build-time secret). For creating the token and wiring it into CI, see [`sentry-source-maps`](../sentry-source-maps/SKILL.md).

---

## Verification

After setup, verify Sentry is receiving events:

```javascript
// Add temporarily to your entry file or a test route, then remove
import * as Sentry from "@sentry/node"; // or @sentry/bun / @sentry/deno

Sentry.captureException(new Error("Sentry test error — delete me"));
```

Or trigger an unhandled exception:

```javascript
// In a route handler or startup — will be captured automatically
throw new Error("Sentry test error — delete me");
```

Then check your [Sentry Issues dashboard](https://sentry.io/issues/) — the error should appear within ~30 seconds.

**Verification checklist:**

| Check | How |
|-------|-----|
| Error captured | Throw in a handler, verify in Sentry Issues |
| Tracing working | Check Performance tab — should show HTTP spans |
| `includeLocalVariables` working | Stack frame in Sentry should show variable values |
| Source maps working | Stack trace shows readable file names, not minified |

---

## Phase 4: Cross-Link

After completing backend setup, check for companion services:

```bash
# Frontend companion
ls frontend/ web/ client/ ui/ 2>/dev/null
cat package.json 2>/dev/null | grep -E...

© getsentry · Apache-2.0 · getsentry/sentry-for-ai

Similar skills

Everything for Backend and APIs →

From the same set31

sentry-react-native-sdk A skill that walks your agent through Sentry setup in React Native and Expo: it scans the project, proposes a feature set and guides the install steps. CX Codex +1 4,100installs sentry-sdk-setup Reads your project files, picks the matching Sentry SDK skill, and walks through error monitoring, tracing and session replay. CX Codex +1 3,600installs sentry-nextjs-sdk This skill inspects your Next.js project and guides Sentry setup across browser, Node.js, and Edge runtimes. It helps configure error tracking, tracing, and session replays. CX Codex +1 3,600installs sentry-cocoa-sdk This skill walks you through a full Sentry setup for iOS, macOS, tvOS, watchOS and visionOS: it scans the project, proposes a feature set and guides the install. CX Codex +1 3,400installs sentry-sdk-upgrade This skill guides major version upgrades for the Sentry JavaScript SDK, like migrating from v7 to v8 or v9. It finds deprecated APIs, updates imports, and verifies the build. CX Codex +1 3,100installs sentry-react-sdk Walks a React project through full Sentry setup: it scans your dependencies, proposes a feature set, and writes the config. Useful when you want error monitoring wired up without reading the docs end to end. CX Codex +1 3,100installs sentry-setup-ai-monitoring Configures Sentry AI monitoring for LLM calls, agent runs, and token metrics. Inspects project dependencies across Node.js, Python, or Laravel to wire up integrations. CX Codex +1 3,000installs sentry-browser-sdk Walks the agent through Sentry setup for browser JavaScript: checks the project for frameworks, picks an install path, then configures error monitoring, tracing and replay. CX Codex +1 2,900installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor