适配器
使用 evlog 适配器将日志发送到外部服务。内置对流行可观测性平台和自定义目标的支持。

适配器允许您将日志发送到外部可观测性平台。evlog 提供内置适配器以支持流行的服务,并且您可以为任何目标创建自定义适配器。

drain pipeline
0/5 delivered
wide event
{
  level:    "info",
  method:   "POST",
  path:     "/checkout",
  duration: 234,
  user:     {...},
  cart:     {...}
}
BUILDING
  1. axiom
    pending
  2. otlp
    pending
  3. sentry
    pending
  4. nuxthub
    pending
  5. fs
    pending
fire-and-forget retry with backoff one failure ≠ blocked response ✓ all destinations resolved

适配器如何工作

适配器在每次请求完成后接收一个 DrainContext,并将数据发送到外部服务。排水过程在 fire-and-forget 模式下运行,这意味着它永远不会阻塞 HTTP 响应。

如何连接适配器取决于您使用的框架:

// server/plugins/evlog-drain.ts
import { createAxiomDrain } from 'evlog/axiom'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain())
})
Serverless 支持: 在 Cloudflare Workers 和 Vercel Edge 上,evlog 会自动使用 waitUntil() 来确保在运行时终止前排水完成。无需额外配置。

可用适配器

Axiom

将日志发送到 Axiom 以进行强大的查询和仪表板展示。

OTLP

用于 Grafana、Datadog、Honeycomb 等的 OpenTelemetry 协议。

HyperDX

使用其文档化的摄取端点和 API 密钥,通过 OTLP/HTTP 将日志发送到 HyperDX。

PostHog

将日志发送到 PostHog Logs 以进行结构化日志记录和可观测性。

Sentry

将结构化日志发送到 Sentry Logs 以进行高基数查询。

Better Stack

将日志发送到 Better Stack 以进行日志管理和告警。

Datadog

通过本地 HTTP 摄入 API 将日志发送到 Datadog Logs。

文件系统

将日志写入本地 NDJSON 文件用于调试和 AI 代理集成。

NuxtHub

在您的 NuxtHub 数据库中进行自托管日志存储,并带有自动保留策略。

内存

适用于任何运行时的内存环形缓冲区,包括 Cloudflare Workers。

自定义

为任何目标构建您自己的适配器。

HTTP

在不耦合框架的情况下将客户端日志发送到您的服务器。

管道

批量处理事件、失败重试并处理缓冲区溢出。

独立使用

在纯 TypeScript 或 Bun 脚本(无 HTTP 框架)中使用 initLogger 中的 drain 选项。每个发出的事件都会自动被排出。

index.ts
import type { DrainContext } from 'evlog'
import { initLogger, log, createRequestLogger } from 'evlog'
import { createAxiomDrain } from 'evlog/axiom'
import { createDrainPipeline } from 'evlog/pipeline'

const pipeline = createDrainPipeline<DrainContext>()
const drain = pipeline(createAxiomDrain())

initLogger({
  env: { service: 'my-script' },
  drain,
})

log.info({ action: 'job_started' }) // 自动排出

const reqLog = createRequestLogger({ method: 'POST', path: '/process' })
reqLog.set({ processed: 42 })
reqLog.emit() // 自动排出

await drain.flush()
请参阅完整的 bun-script 示例,了解一个实际的批处理脚本。

多目标发送

通过组合排水器同时将日志发送到多个服务:

src/index.ts
import { createAxiomDrain } from 'evlog/axiom'
import { createOTLPDrain } from 'evlog/otlp'

const axiom = createAxiomDrain()
const otlp = createOTLPDrain()

const drain = async (ctx) => {
  await Promise.allSettled([axiom(ctx), otlp(ctx)])
}

然后将 drain 传递给您的框架:

// server/plugins/evlog-drain.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', drain)
})

排出上下文

每个适配器都会接收一个带有以下内容的 DrainContext

字段类型描述
eventWideEvent包含所有累积上下文的完整日志事件
requestobject请求元数据(methodpathrequestId
headersobject安全的 HTTP 头(敏感头会被过滤)
安全性: 敏感头信息(如 authorizationcookiex-api-key 等)会自动被过滤,不会传递给适配器。

零配置设置

所有适配器都支持通过环境变量自动配置,无需更改代码即可在不同环境中部署。

每个适配器读取以 NUXT_* 为前缀的变量(适用于 Nuxt/Nitro 的 runtimeConfig)和无前缀的备用变量(适用于任何框架):

.env
# Axiom (NUXT_AXIOM_* 或 AXIOM_*)
AXIOM_API_KEY=xaat-xxx
AXIOM_DATASET=my-logs

# OTLP (NUXT_OTLP_* 或 OTEL_*)
OTLP_ENDPOINT=https://otlp.example.com

# HyperDX (NUXT_HYPERDX_* 或 HYPERDX_*)
HYPERDX_API_KEY=<YOUR_HYPERDX_API_KEY_HERE>

# PostHog (NUXT_POSTHOG_* 或 POSTHOG_*)
POSTHOG_API_KEY=phc_xxx

# Sentry (NUXT_SENTRY_* 或 SENTRY_*)
SENTRY_DSN=https://key@o0.ingest.sentry.io/123

# Better Stack (NUXT_BETTER_STACK_* 或 BETTER_STACK_*)
BETTER_STACK_API_KEY=your-source-token

# Datadog (NUXT_DATADOG_* 或 DATADOG_* 或 DD_*)
DD_API_KEY=your-api-key
DD_SITE=datadoghq.eu

适配器会自动从这些变量中读取,因此只需不带任何参数地调用 createXDrain() 即可。

缺少凭据

行为取决于您调用的是哪个 API:

API缺少凭据
create*Drain()(工厂方法)console.error + 排水器变为无操作 —— HTTP 响应绝不会被阻塞
sendTo* / sendBatchTo*(直接调用)如果缺少必需凭据则抛出错误 —— 调用方必须传入完整配置

这种拆分是有意为之:排水器在每个请求后以 fire-and-forget 方式运行;直接发送辅助函数则用于脚本和测试,在这些场景中,静默失败会掩盖配置错误。