---
title: "Sentry 适配器"
description: "将结构化日志发送到 Sentry 日志，以支持高基数查询和调试。通过环境变量即可实现零配置设置。"
canonical_url: "https://evlog.zhcndoc.com/integrate/adapters/cloud/sentry"
---
# Sentry 适配器

> 将结构化日志发送到 Sentry 日志，以支持高基数查询和调试。通过环境变量即可实现零配置设置。

[Sentry](https://sentry.io) 是一个错误追踪与性能监控平台。evlog Sentry 适配器会将你的宽事件以 **Sentry 结构化日志** 的形式发送，在 Sentry 控制台的 **探索 > 日志** 中可见，并支持高基数可搜索属性。

<prompt :actions="["copy","cursor","claude"]" description="添加 Sentry 排水器适配器" icon="i-simple-icons-sentry">

添加 Sentry 排水器适配器，将 evlog 宽事件发送到 Sentry 日志。

1. 确定我正在使用的框架并遵循其 evlog 集成模式
2. 如果尚未安装 evlog，请安装它
3. 从 'evlog/sentry' 导入 createSentryDrain
4. 将 createSentryDrain() 连接到我的框架的排水配置
5. 设置 SENTRY_DSN 环境变量
6. 通过触发请求进行测试，并在 Sentry > 探索 > 日志 中检查

适配器文档：[https://www.evlog.dev/integrate/adapters/cloud/sentry](https://www.evlog.dev/integrate/adapters/cloud/sentry)
框架设置：[https://www.evlog.dev/integrate/frameworks/overview](https://www.evlog.dev/integrate/frameworks/overview)

</prompt>

## 安装

Sentry 适配器已与 evlog 捆绑提供：

```typescript [src/index.ts]
import { createSentryDrain } from 'evlog/sentry'
```

## 快速开始

### 1. 获取你的 Sentry DSN

1. 创建一个 [Sentry 账户](https://sentry.io)
2. 创建一个新的项目（Node.js 或 JavaScript）
3. 在 **设置 > 项目 > 你的项目 > 客户端密钥（DSN）** 中找到你的 DSN

### 2. 设置环境变量

```bash [.env]
SENTRY_DSN=https://your-public-key@o0.ingest.sentry.io/your-project-id
```

### 3. 将排水器连接到你的框架

<framework-tabs>

```typescript [Nuxt]server/plugins/evlog-drain.ts
import { createSentryDrain } from 'evlog/sentry'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain())
})
```

```typescript [Nitro]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createSentryDrain } from 'evlog/sentry'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain())
})
```

```typescript [Next.js]lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createSentryDrain } from 'evlog/sentry'

export const { withEvlog, useLogger, log, createError } = createEvlog({
  service: 'my-app',
  drain: createSentryDrain(),
})
```

```typescript [SvelteKit]src/hooks.server.ts
import { createEvlogHooks } from 'evlog/sveltekit'
import { createSentryDrain } from 'evlog/sentry'

export const { handle, handleError } = createEvlogHooks({ drain: createSentryDrain() })
```

```typescript [TanStack Start]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createSentryDrain } from 'evlog/sentry'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain())
})
```

```typescript [React Router]app/root.tsx
import { evlog } from 'evlog/react-router'
import { createSentryDrain } from 'evlog/sentry'

export const middleware: Route.MiddlewareFunction[] = [
  evlog({ drain: createSentryDrain() }),
]
```

```typescript [Hono]src/index.ts
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({ drain: createSentryDrain() }))
```

```typescript [Express]src/index.ts
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({ drain: createSentryDrain() }))
```

```typescript [Fastify]src/index.ts
import { createSentryDrain } from 'evlog/sentry'

await app.register(evlog, { drain: createSentryDrain() })
```

```typescript [Elysia]src/index.ts
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({ drain: createSentryDrain() }))
```

```typescript [NestJS]src/app.module.ts
import { createSentryDrain } from 'evlog/sentry'

EvlogModule.forRoot({ drain: createSentryDrain() })
```

```typescript [oRPC]server/orpc.ts
import { withEvlog } from 'evlog/orpc'
import { createSentryDrain } from 'evlog/sentry'

const handler = withEvlog(new RPCHandler(router), { drain: createSentryDrain() })
```

```typescript [Cloudflare Workers]src/worker.ts
import { withEvlog } from 'evlog/workers'
import { createSentryDrain } from 'evlog/sentry'

export default withEvlog(handler, { drain: createSentryDrain() })
```

```typescript [Standalone]
import { createSentryDrain } from 'evlog/sentry'

initLogger({ drain: createSentryDrain() })
```

</framework-tabs>

就这样！你的日志现在会出现在 Sentry 的 **探索 > 日志** 中。

## 配置

适配器按照优先级顺序从多个来源读取配置（优先级从高到低）：

1. **覆盖项** 传递给 `createSentryDrain()`
2. **运行时配置** 位于 `runtimeConfig.sentry`（仅限 Nuxt/Nitro）
3. **环境变量**（`SENTRY_*`）

### 环境变量

<table>
<thead>
  <tr>
    <th>
      变量
    </th>
    
    <th>
      描述
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        SENTRY_DSN
      </code>
    </td>
    
    <td>
      Sentry DSN（必需）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        SENTRY_ENVIRONMENT
      </code>
    </td>
    
    <td>
      环境名称覆盖项
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        SENTRY_RELEASE
      </code>
    </td>
    
    <td>
      发布版本覆盖项
    </td>
  </tr>
</tbody>
</table>

### 运行时配置（仅限 Nuxt）

通过在 `nuxt.config.ts` 中配置，实现类型安全的配置：

```typescript [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    sentry: {
      dsn: '', // 通过 SENTRY_DSN 设置
      environment: 'production',
      release: '1.0.0',
    },
  },
})
```

### 覆盖选项

直接传递选项以覆盖任何配置：

<framework-tabs>

```typescript [Nuxt]server/plugins/evlog-drain.ts
import { createSentryDrain } from 'evlog/sentry'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }))
})
```

```typescript [Nitro]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createSentryDrain } from 'evlog/sentry'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }))
})
```

```typescript [Next.js]lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createSentryDrain } from 'evlog/sentry'

export const { withEvlog, useLogger, log, createError } = createEvlog({
  service: 'my-app',
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [SvelteKit]src/hooks.server.ts
import { createEvlogHooks } from 'evlog/sveltekit'
import { createSentryDrain } from 'evlog/sentry'

export const { handle, handleError } = createEvlogHooks({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [TanStack Start]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createSentryDrain } from 'evlog/sentry'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }))
})
```

```typescript [React Router]app/root.tsx
import { evlog } from 'evlog/react-router'
import { createSentryDrain } from 'evlog/sentry'

export const middleware: Route.MiddlewareFunction[] = [
  evlog({
      drain: createSentryDrain({
        dsn: 'https://key@o0.ingest.sentry.io/123',
        tags: { team: 'backend' },
        timeout: 10000,
      }),
    }),
]
```

```typescript [Hono]src/index.ts
import { evlog } from 'evlog/hono'
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
}))
```

```typescript [Express]src/index.ts
import { evlog } from 'evlog/express'
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
}))
```

```typescript [Fastify]src/index.ts
import { evlog } from 'evlog/fastify'
import { createSentryDrain } from 'evlog/sentry'

await app.register(evlog, {
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [Elysia]src/index.ts
import { evlog } from 'evlog/elysia'
import { createSentryDrain } from 'evlog/sentry'

app.use(evlog({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
}))
```

```typescript [NestJS]src/app.module.ts
import { EvlogModule } from 'evlog/nestjs'
import { createSentryDrain } from 'evlog/sentry'

EvlogModule.forRoot({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [oRPC]server/orpc.ts
import { withEvlog } from 'evlog/orpc'
import { createSentryDrain } from 'evlog/sentry'

const handler = withEvlog(new RPCHandler(router), {
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [Cloudflare Workers]src/worker.ts
import { withEvlog } from 'evlog/workers'
import { createSentryDrain } from 'evlog/sentry'

export default withEvlog(handler, {
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

```typescript [Standalone]src/index.ts
import { initLogger } from 'evlog'
import { createSentryDrain } from 'evlog/sentry'

initLogger({
  drain: createSentryDrain({
    dsn: 'https://key@o0.ingest.sentry.io/123',
    tags: { team: 'backend' },
    timeout: 10000,
  }),
})
```

</framework-tabs>

### 完整配置参考

<table>
<thead>
  <tr>
    <th>
      选项
    </th>
    
    <th>
      类型
    </th>
    
    <th>
      默认值
    </th>
    
    <th>
      描述
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        dsn
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      Sentry DSN（必需）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        environment
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      事件环境
    </td>
    
    <td>
      环境名称
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        release
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      事件版本
    </td>
    
    <td>
      发布版本
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tags
      </code>
    </td>
    
    <td>
      <code>
        Record<string, string>
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      要附加的其他属性
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        timeout
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        5000
      </code>
    </td>
    
    <td>
      请求超时时间（毫秒）
    </td>
  </tr>
</tbody>
</table>

## 日志转换

evlog 宽事件通过 `toSentryLog()` 转换为 Sentry 日志：

- **等级映射**：evlog 等级直接映射（`debug`、`info`、`warn`、`error`）
- **严重性数字**：遵循 OpenTelemetry 规范（`debug=5`、`info=9`、`warn=13`、`error=17`）
- **正文**：来自事件的 `message`、`action` 或 `path` 字段（按可用性优先）
- **属性**：所有宽事件字段作为类型化属性发送（字符串、整数、浮点数、布尔值）。复杂对象会被序列化为 JSON 字符串。
- **Sentry 属性**：自动设置 `sentry.environment` 和 `sentry.release`
- **跟踪 ID**：如果存在 `event.traceId` 则使用，否则生成随机值。

## 在 Sentry 中查询日志

evlog 以结构化日志形式发送宽事件。在 Sentry 控制台中：

- **Explore > 日志**：查看所有 evlog 宽事件，并支持完整属性搜索
- **按属性过滤**：如 `service:my-app`、`level:error` 或任意宽事件字段
- **跟踪关联**：日志通过 `trace_id` 与跟踪关联，便于交叉引用

<callout color="info" icon="i-lucide-info">

Sentry 结构化日志支持高基数属性，非常适合 evlog 的宽事件。你的宽事件中的每个字段都会成为 Sentry 中可搜索的属性。

</callout>

## 故障排除

### 缺少 DSN 错误

```text [控制台]
[evlog/sentry] 缺少 DSN。请设置 SENTRY_DSN 环境变量或在 createSentryDrain() 中传递
```

请确保已设置环境变量，并在添加后重启服务器。

### 无效的 DSN

如果 DSN 格式错误（缺少公钥或项目 ID），适配器会抛出错误。请验证 DSN 格式：

```text [Sentry DSN 格式]
https://<公钥>@<主机>/<项目ID>
```

### 401 未授权

你的 DSN 可能被吊销或无效。请在 **设置 > 项目 > 客户端密钥（DSN）** 中生成新的 DSN。

## 直接 API 用法

对于高级用例，你可以使用底层函数：

```typescript [server/utils/sentry.ts]
import { sendToSentry, sendBatchToSentry } from 'evlog/sentry'

// 将单个事件发送为 Sentry 日志
await sendToSentry(event, {
  dsn: process.env.SENTRY_DSN!,
})

// 批量发送多个事件
await sendBatchToSentry(events, {
  dsn: process.env.SENTRY_DSN!,
})
```

## 下一步

- [Axiom 适配器](https://evlog.zhcndoc.com/integrate/adapters/cloud/axiom) - 将日志发送到 Axiom，以便查询和创建仪表板
- [OTLP 适配器](https://evlog.zhcndoc.com/integrate/adapters/hybrid/otlp) - 通过 OpenTelemetry 协议发送日志
- [PostHog 适配器](https://evlog.zhcndoc.com/integrate/adapters/cloud/posthog) - 将日志发送到 PostHog
- [自定义适配器](https://evlog.zhcndoc.com/extend/custom-drains) - 构建您自己的适配器

---

- [Sentry 控制台](https://sentry.io)
- [OTLP 适配器](https://evlog.zhcndoc.com/integrate/adapters/hybrid/otlp)


## Sitemap

See the full [sitemap](https://evlog.zhcndoc.com/sitemap.md) for all pages.
