You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过Datadog Tracer将Zerolog日志(含错误)上报至Datadog?

解决方案:Zerolog 与 Datadog Tracer 结合日志上报

首先明确:Datadog Tracer 的核心定位是 APM 链路追踪,并非日志采集工具,因此不存在直接将 Zerolog 输出到 Tracer IO Writer 的方案。但可以通过以下两种方式满足你的需求——既遵循公司使用 Tracer 的要求,又实现错误/信息日志的上报与链路关联。

方案一:Zerolog 输出带追踪上下文的日志(推荐,适配所有应用类型)

通过让 Zerolog 日志携带 Tracer 生成的 Trace ID 和 Span ID,结合 Datadog Agent 自动关联日志与 APM 链路,这是 Datadog 官方推荐的日志-追踪联动方案,支持非 HTTP 服务。

实现步骤

  1. 启动 Tracer 时确保上下文传播正常;
  2. 在日志输出时,从当前活跃的 Span 中提取 Trace ID 和 Span ID,作为固定字段加入 Zerolog 日志;
  3. 保持原有 Zerolog 日志输出方式(如 stdout/file),由 Datadog Agent 收集日志并自动关联到对应追踪链路。

示例代码

import (
    "context"
    "github.com/rs/zerolog"
    "os"
    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

// 获取当前追踪上下文的字段(供 Zerolog 使用)
func getTraceFields(ctx context.Context) map[string]interface{} {
    fields := make(map[string]interface{})
    span, ok := tracer.SpanFromContext(ctx)
    if !ok {
        return fields
    }
    // 使用 Datadog 约定的字段名,Agent 会自动识别关联
    fields["dd.trace_id"] = span.Context().TraceID()
    fields["dd.span_id"] = span.Context().SpanID()
    return fields
}

func main() {
    // 初始化 Tracer
    tracer.Start(
        tracer.WithService("non-http-task-service"),
        tracer.WithEnv("Stage"),
        tracer.WithServiceVersion("2.0"),
    )
    defer tracer.Stop()

    // 初始化基础 Zerolog 实例
    baseLogger := zerolog.New(os.Stdout).With().
        Timestamp().
        Str("service", "non-http-task-service").
        Str("env", "Stage").
        Str("version", "2.0").
        Logger()

    // 示例:非 HTTP 场景下手动创建 Span
    ctx, span := tracer.StartSpanFromContext(context.Background(), "task.batch_process")
    defer span.Finish()

    // 绑定当前 Span 的追踪上下文到日志实例
    logger := baseLogger.With().Fields(getTraceFields(ctx)).Logger()

    // 业务逻辑与日志输出
    err := processBatchTask(ctx)
    if err != nil {
        logger.Error().Err(err).Msg("batch task processing failed")
        // 同时标记 Span 为错误状态(可选,增强 APM 链路可读性)
        span.SetTag("error", true)
        span.Log(tracer.LogError(err))
    } else {
        logger.Info().Msg("batch task processed successfully")
    }
}

func processBatchTask(ctx context.Context) error {
    // 子操作创建子 Span(可选)
    _, subSpan := tracer.StartSpanFromContext(ctx, "task.item_process")
    defer subSpan.Finish()

    // 子操作日志,自动继承父 Span 的追踪上下文
    logger := zerolog.Ctx(ctx).With().Fields(getTraceFields(ctx)).Logger()
    logger.Debug().Msg("processing single task item")

    // 模拟错误
    // return fmt.Errorf("item validation failed")
    return nil
}

方案二:通过 Tracer Span 上报错误事件(仅适用于链路绑定的错误)

如果不需要完整的日志集,仅需将错误与具体追踪链路绑定,可以直接使用 Tracer Span 的日志 API,将错误信息作为 Span 的事件上报,这些信息会出现在 Datadog APM 的 Span 详情页中。

示例代码

import (
    "context"
    "debug"
    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func main() {
    tracer.Start(
        tracer.WithService("job-scheduler"),
        tracer.WithEnv("Stage"),
        tracer.WithServiceVersion("2.0"),
    )
    defer tracer.Stop()

    ctx, span := tracer.StartSpanFromContext(context.Background(), "job.execute")
    defer span.Finish()

    err := executeJob(ctx)
    if err != nil {
        // 上报错误事件到 Span
        span.Log(map[string]interface{}{
            "event":       "error",
            "message":     err.Error(),
            "stacktrace":  string(debug.Stack()),
            "job_id":      "12345",
        })
        // 标记 Span 为错误状态,APM 中会高亮显示
        span.SetTag("error", true)
    }
}

关键说明

  • 非 HTTP 服务无需局限于 HTTP 请求的 Span 创建,可以手动通过 StartSpan 或 StartSpanFromContext 创建 Span,覆盖任务处理、定时调度等场景;
  • 方案一既保留了 Zerolog 的日志能力,又通过追踪上下文实现了日志与 APM 的联动,是最灵活的方案;
  • 无论哪种方案,都需要确保 Datadog Agent 已正确部署并配置日志采集,才能将日志同步到 Datadog 平台。

内容的提问来源于stack exchange,提问作者Anders Finn Jørgensen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 12:35:24