|
| 1 | +--- |
| 2 | +title: Sentry Adapter |
| 3 | +description: Send structured logs to Sentry Logs for high-cardinality querying and debugging. Zero-config setup with environment variables. |
| 4 | +navigation: |
| 5 | + title: Sentry |
| 6 | + icon: i-simple-icons-sentry |
| 7 | +links: |
| 8 | + - label: Sentry Dashboard |
| 9 | + icon: i-lucide-external-link |
| 10 | + to: https://sentry.io |
| 11 | + target: _blank |
| 12 | + color: neutral |
| 13 | + variant: subtle |
| 14 | + - label: OTLP Adapter |
| 15 | + icon: i-simple-icons-opentelemetry |
| 16 | + to: /adapters/otlp |
| 17 | + color: neutral |
| 18 | + variant: subtle |
| 19 | +--- |
| 20 | + |
| 21 | +[Sentry](https://sentry.io) is an error tracking and performance monitoring platform. The evlog Sentry adapter sends your wide events as **Sentry Structured Logs**, visible in **Explore > Logs** in the Sentry dashboard with high-cardinality searchable attributes. |
| 22 | + |
| 23 | +## Installation |
| 24 | + |
| 25 | +The Sentry adapter comes bundled with evlog: |
| 26 | + |
| 27 | +```typescript [server/plugins/evlog-drain.ts] |
| 28 | +import { createSentryDrain } from 'evlog/sentry' |
| 29 | +``` |
| 30 | + |
| 31 | +## Quick Start |
| 32 | + |
| 33 | +### 1. Get your Sentry DSN |
| 34 | + |
| 35 | +1. Create a [Sentry account](https://sentry.io) |
| 36 | +2. Create a new project (Node.js or JavaScript) |
| 37 | +3. Find your DSN in **Settings > Projects > [Your Project] > Client Keys (DSN)** |
| 38 | + |
| 39 | +### 2. Set environment variables |
| 40 | + |
| 41 | +```bash [.env] |
| 42 | +NUXT_SENTRY_DSN=https://your-public-key@o0.ingest.sentry.io/your-project-id |
| 43 | +``` |
| 44 | + |
| 45 | +### 3. Create the drain plugin |
| 46 | + |
| 47 | +```typescript [server/plugins/evlog-drain.ts] |
| 48 | +import { createSentryDrain } from 'evlog/sentry' |
| 49 | + |
| 50 | +export default defineNitroPlugin((nitroApp) => { |
| 51 | + nitroApp.hooks.hook('evlog:drain', createSentryDrain()) |
| 52 | +}) |
| 53 | +``` |
| 54 | + |
| 55 | +That's it! Your logs will now appear in **Explore > Logs** in Sentry. |
| 56 | + |
| 57 | +## Configuration |
| 58 | + |
| 59 | +The adapter reads configuration from multiple sources (highest priority first): |
| 60 | + |
| 61 | +1. **Overrides** passed to `createSentryDrain()` |
| 62 | +2. **Runtime config** at `runtimeConfig.evlog.sentry` |
| 63 | +3. **Runtime config** at `runtimeConfig.sentry` |
| 64 | +4. **Environment variables** (`NUXT_SENTRY_*` or `SENTRY_*`) |
| 65 | + |
| 66 | +### Environment Variables |
| 67 | + |
| 68 | +| Variable | Description | |
| 69 | +|----------|-------------| |
| 70 | +| `NUXT_SENTRY_DSN` | Sentry DSN (required) | |
| 71 | +| `NUXT_SENTRY_ENVIRONMENT` | Environment name override | |
| 72 | +| `NUXT_SENTRY_RELEASE` | Release version override | |
| 73 | + |
| 74 | +You can also use `SENTRY_DSN`, `SENTRY_ENVIRONMENT`, and `SENTRY_RELEASE` as fallbacks. |
| 75 | + |
| 76 | +### Runtime Config |
| 77 | + |
| 78 | +Configure via `nuxt.config.ts` for type-safe configuration: |
| 79 | + |
| 80 | +```typescript [nuxt.config.ts] |
| 81 | +export default defineNuxtConfig({ |
| 82 | + modules: ['evlog/nuxt'], |
| 83 | + evlog: { |
| 84 | + sentry: { |
| 85 | + dsn: '', // Set via NUXT_SENTRY_DSN |
| 86 | + environment: 'production', |
| 87 | + release: '1.0.0', |
| 88 | + }, |
| 89 | + }, |
| 90 | +}) |
| 91 | +``` |
| 92 | + |
| 93 | +### Override Options |
| 94 | + |
| 95 | +Pass options directly to override any configuration: |
| 96 | + |
| 97 | +```typescript [server/plugins/evlog-drain.ts] |
| 98 | +import { createSentryDrain } from 'evlog/sentry' |
| 99 | + |
| 100 | +export default defineNitroPlugin((nitroApp) => { |
| 101 | + nitroApp.hooks.hook('evlog:drain', createSentryDrain({ |
| 102 | + dsn: 'https://key@o0.ingest.sentry.io/123', |
| 103 | + tags: { team: 'backend' }, |
| 104 | + timeout: 10000, // 10 seconds |
| 105 | + })) |
| 106 | +}) |
| 107 | +``` |
| 108 | + |
| 109 | +### Full Configuration Reference |
| 110 | + |
| 111 | +| Option | Type | Default | Description | |
| 112 | +|--------|------|---------|-------------| |
| 113 | +| `dsn` | `string` | - | Sentry DSN (required) | |
| 114 | +| `environment` | `string` | Event environment | Environment name | |
| 115 | +| `release` | `string` | Event version | Release version | |
| 116 | +| `tags` | `Record<string, string>` | - | Additional attributes to attach | |
| 117 | +| `timeout` | `number` | `5000` | Request timeout in milliseconds | |
| 118 | + |
| 119 | +## Log Transformation |
| 120 | + |
| 121 | +evlog wide events are converted to Sentry Logs using `toSentryLog()`: |
| 122 | + |
| 123 | +- **Level mapping**: evlog levels map directly (`debug`, `info`, `warn`, `error`) |
| 124 | +- **Severity numbers**: Follow the OpenTelemetry spec (`debug=5`, `info=9`, `warn=13`, `error=17`) |
| 125 | +- **Body**: Derived from the event's `message`, `action`, or `path` fields (first available) |
| 126 | +- **Attributes**: All wide event fields are sent as typed attributes (string, integer, double, boolean). Complex objects are serialized to JSON strings. |
| 127 | +- **Sentry attributes**: `sentry.environment` and `sentry.release` are set automatically |
| 128 | +- **Trace ID**: Uses `event.traceId` if available, otherwise generates a random one |
| 129 | + |
| 130 | +## Querying Logs in Sentry |
| 131 | + |
| 132 | +evlog sends wide events as structured logs. In the Sentry dashboard: |
| 133 | + |
| 134 | +- **Explore > Logs**: View all evlog wide events with full attribute search |
| 135 | +- **Filter by attributes**: `service:my-app`, `level:error`, or any wide event field |
| 136 | +- **Trace correlation**: Logs are linked to traces via `trace_id` for cross-referencing |
| 137 | + |
| 138 | +::callout{icon="i-lucide-info" color="info"} |
| 139 | +Sentry Structured Logs support high-cardinality attributes, making them a great fit for evlog's wide events. Every field in your wide event becomes a searchable attribute in Sentry. |
| 140 | +:: |
| 141 | + |
| 142 | +## Troubleshooting |
| 143 | + |
| 144 | +### Missing DSN error |
| 145 | + |
| 146 | +``` |
| 147 | +[evlog/sentry] Missing DSN. Set NUXT_SENTRY_DSN/SENTRY_DSN env var or pass to createSentryDrain() |
| 148 | +``` |
| 149 | + |
| 150 | +Make sure your environment variable is set and the server was restarted after adding it. |
| 151 | + |
| 152 | +### Invalid DSN |
| 153 | + |
| 154 | +If the DSN is malformed (missing public key or project ID), the adapter will throw an error. Verify your DSN format: |
| 155 | + |
| 156 | +``` |
| 157 | +https://<public-key>@<host>/<project-id> |
| 158 | +``` |
| 159 | + |
| 160 | +### 401 Unauthorized |
| 161 | + |
| 162 | +Your DSN may be revoked or invalid. Generate a new DSN in **Settings > Projects > Client Keys (DSN)**. |
| 163 | + |
| 164 | +## Direct API Usage |
| 165 | + |
| 166 | +For advanced use cases, you can use the lower-level functions: |
| 167 | + |
| 168 | +```typescript [server/utils/sentry.ts] |
| 169 | +import { sendToSentry, sendBatchToSentry } from 'evlog/sentry' |
| 170 | + |
| 171 | +// Send a single event as a Sentry log |
| 172 | +await sendToSentry(event, { |
| 173 | + dsn: process.env.SENTRY_DSN!, |
| 174 | +}) |
| 175 | + |
| 176 | +// Send multiple events in one request |
| 177 | +await sendBatchToSentry(events, { |
| 178 | + dsn: process.env.SENTRY_DSN!, |
| 179 | +}) |
| 180 | +``` |
| 181 | + |
| 182 | +## Next Steps |
| 183 | + |
| 184 | +- [Axiom Adapter](/adapters/axiom) - Send logs to Axiom for querying and dashboards |
| 185 | +- [OTLP Adapter](/adapters/otlp) - Send logs via OpenTelemetry Protocol |
| 186 | +- [PostHog Adapter](/adapters/posthog) - Send logs to PostHog |
| 187 | +- [Custom Adapters](/adapters/custom) - Build your own adapter |
0 commit comments