Datadog 适配器
Datadog 是一个监控和安全平台。evlog Datadog 适配器使用 HTTP 日志摄入 API (v2) 和 DD-API-KEY 标头,将你的广泛事件发送到 Datadog 日志。
如果要改用基于 OpenTelemetry 的摄入方式,请参阅 OTLP 适配器。
添加 Datadog 排水适配器
安装
Datadog 适配器与 evlog 捆绑提供:
import { createDatadogDrain } from 'evlog/datadog'
快速开始
1. 获取 API 密钥
- 打开 Datadog 组织设置 → API 密钥
- 创建或复制一个具有提交日志权限的 API 密钥
2. 设置环境变量
DD_API_KEY=your-api-key
# 可选 — 默认为 datadoghq.com (US1)
DD_SITE=datadoghq.eu
3. 将排水集成到框架中
// server/plugins/evlog-drain.ts
import { createDatadogDrain } from 'evlog/datadog'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', createDatadogDrain())
})
// lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createDatadogDrain } from 'evlog/datadog'
export const { withEvlog, useLogger, log, createError } = createEvlog({
service: 'my-app',
drain: createDatadogDrain(),
})
import { createDatadogDrain } from 'evlog/datadog'
app.use(evlog({ drain: createDatadogDrain() }))
import { createDatadogDrain } from 'evlog/datadog'
app.use(evlog({ drain: createDatadogDrain() }))
import { createDatadogDrain } from 'evlog/datadog'
await app.register(evlog, { drain: createDatadogDrain() })
import { createDatadogDrain } from 'evlog/datadog'
app.use(evlog({ drain: createDatadogDrain() }))
import { createDatadogDrain } from 'evlog/datadog'
EvlogModule.forRoot({ drain: createDatadogDrain() })
import { createDatadogDrain } from 'evlog/datadog'
initLogger({ drain: createDatadogDrain() })
广泛事件将显示在 日志 → 资源管理器 中。适配器将 ddsource 设置为 evlog,并将 message 设置为完整广泛事件的 JSON 字符串,以便在管道中轻松解析 JSON。
配置
适配器从多个来源读取配置(优先级从高到低):
- 传递给
createDatadogDrain()的覆盖选项 runtimeConfig.datadog或runtimeConfig.evlog.datadog中的运行时配置(Nuxt/Nitro)- 环境变量:请参阅下表
环境变量
| 变量 | 描述 |
|---|---|
DD_API_KEY | Datadog API 密钥(必填)。另见:DATADOG_API_KEY |
DD_SITE | 站点主机名(例如 datadoghq.com、datadoghq.eu、us3.datadoghq.com)。另见:DATADOG_SITE |
DATADOG_LOGS_URL | 完整接入 URL — 会覆盖从 site 派生的 URL |
运行时配置(仅限 Nuxt)
export default defineNuxtConfig({
runtimeConfig: {
datadog: {
apiKey: '', // 通过 DD_API_KEY 或 DATADOG_API_KEY 设置
site: 'datadoghq.eu',
},
},
})
覆盖选项
const drain = createDatadogDrain({
apiKey: '***',
site: 'us5.datadoghq.com',
timeout: 10000,
})
完整配置参考
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
apiKey | string | — | Datadog API 密钥(必需) |
site | string | datadoghq.com | 摄入主机使用的站点,格式为 http-intake.logs.${site} |
intakeUrl | string | 从 site 推导 | /api/v2/logs 的完整 POST URL |
timeout | number | 5000 | 请求超时时间(毫秒) |
retries | number | 2 | 在暂时性失败时的重试次数 |
日志结构
每个广泛事件都会转换为一条 Datadog 日志,包含以下字段:
message:列表视图中的简短单行摘要(例如ERROR GET /api/checkout (400)),通过formatDatadogMessageLine构建。在 Live Tail 中比完整的 JSON 数据块更易于浏览evlog:完整的广泛事件,作为 JSON 对象(而非字符串)。树中任何位置的数字 HTTPstatus字段都会重命名为httpStatusCode,因此不会与 Datadog 保留的严重性status冲突dd:当事件携带链路上下文时为{ trace_id, span_id }。请参阅链路关联service、status(Datadog 严重性,用于决定 Live Tail 颜色)、ddsource:evlog、ddtags:env:…和可选的version:…timestamp:来自WideEvent.timestamp的 Unix 毫秒时间戳
摄入根级别的严重性(status) 由适配器根据广泛事件的 level 和 HTTP status 计算得出(参见 evlog/datadog 中的 resolveDatadogLogStatus)。HTTP 200 对应的业务字段仍为 info,除非显式调用 log.error()。
如需高级用法,sanitizeWideEventForDatadog(event) 返回的即为要存储在 evlog 下的清洗后对象。
链路关联
Datadog 通过负载根级别的保留属性 dd.trace_id / dd.span_id 将日志关联到链路。嵌套副本(@evlog.traceId)可供搜索,但不会自行建立关联。这需要在 Datadog 日志管道中使用 Trace Id Remapper,其配置位于代码库之外。适配器会将 event.traceId 和 event.spanId 提升到根级别的 dd 块中,因此无需设置管道即可实现关联:
{
"message": "ERROR GET /api/checkout (400)",
"evlog": { "traceId": "4bf92f35…", "spanId": "00f067aa…", "…": "full wide event" },
"dd": { "trace_id": "4bf92f35…", "span_id": "00f067aa…" },
"service": "my-app",
"status": "error",
"ddsource": "evlog"
}
evlog 下的嵌套副本会保留,因此现有的 @evlog.* facets 和仪表板仍可继续使用。只有非空字符串才会被提升,因此空值或非字符串的 traceId / spanId 会被跳过,而不会作为 Datadog 无法解析的 id 发送;当两个 id 都未通过检查时,则不会存在 dd 键。
这些字段由 createTraceContextEnricher 填充,该函数包含在 createDefaultEnrichers() 中,会将传入的 W3C traceparent 标头解析为 event.traceId / event.spanId:
import { createDefaultEnrichers } from 'evlog/enrichers'
const enrich = createDefaultEnrichers()
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:enrich', enrich)
})
如果你的 id 来自其他地方(例如 tracer SDK 或供应商标头),可以自行设置 event.traceId / event.spanId,适配器会以相同方式获取它们:
log.set({ traceId: tracer.scope().active()?.context().toTraceId() })
如果你需要在自定义 drain 中使用相同的映射,可以从 evlog/datadog 导出 resolveDatadogTraceContext(event)。
在 Datadog 中查询
- 日志资源管理器:
source:evlog、service:your-app、status:error - Facets:优先使用
@evlog.path、@evlog.requestId、@evlog.level等。核心字段位于evlog下,而不是message中的 JSON 字符串 - 指标:基于
@evlog.*属性创建日志指标 - 管道:如果你之前解析了
message中的完整 JSON 字符串,请将这些 facets 改为使用@evlog.*。message字段现在仅包含简短的摘要行
简单日志与广泛事件
实时追踪中的纯文本行(例如 “Form field is empty”)通常来自 log.info('tag', 'msg'),而非通过 emit() 发送的广泛事件。这些行输出到控制台(以及任何基于 Agent 的日志流),而 Datadog 排水器会为每个广泛事件发送一条结构化日志,来源为 source:evlog。
故障排除
缺少 API 密钥
[evlog/datadog] Missing API key. Set DATADOG_API_KEY, DD_API_KEY...
设置 DD_API_KEY(或无前缀的 DATADOG_API_KEY)并重启进程。
403 禁止访问
API 密钥可能缺少日志写入权限或属于错误的组织。请在 Datadog 中验证密钥并尝试使用新密钥。
区域/站点错误
如果日志始终没有出现,请确认 DD_SITE 与你的 Datadog 账户匹配(例如,EU:datadoghq.eu)。对于自定义接收端 URL,请设置 DATADOG_LOGS_URL。
直接 API 使用
import { sendToDatadog, sendBatchToDatadog } from 'evlog/datadog'
await sendToDatadog(event, {
apiKey: process.env.DD_API_KEY!,
site: process.env.DD_SITE,
})
await sendBatchToDatadog(events, {
apiKey: process.env.DD_API_KEY!,
})