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

如何在Quarkus中结合请求上下文及DataDog Trace ID记录日志

在Quarkus服务中为日志添加DataDog Trace ID(来自请求头)

推荐方案:使用MDC+JAX-RS拦截器(通用无侵入)

这种方式能自动为每个请求注入Trace ID,业务代码无需修改即可在日志中带上追踪ID。

1. 编写请求拦截器,从请求头获取Trace ID并放入MDC

MDC(Mapped Diagnostic Context)是SLF4J提供的线程绑定上下文,用于存储请求级别的日志变量。

import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import org.slf4j.MDC;

@Provider
public class TraceIdFilter implements ContainerRequestFilter, ContainerResponseFilter {

    // DataDog默认的Trace ID请求头
    private static final String DATADOG_TRACE_ID_HEADER = "x-datadog-trace-id";
    // MDC中存储Trace ID的键名
    private static final String MDC_TRACE_KEY = "traceId";

    @Override
    public void filter(ContainerRequestContext requestContext) {
        // 从请求头提取Trace ID
        String traceId = requestContext.getHeaderString(DATADOG_TRACE_ID_HEADER);
        if (traceId != null && !traceId.isBlank()) {
            MDC.put(MDC_TRACE_KEY, traceId);
        }
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        // 请求结束后清理MDC,避免线程复用导致的ID串问题
        MDC.remove(MDC_TRACE_KEY);
    }
}

2. 配置日志格式,输出MDC中的Trace ID

在application.properties中修改日志格式,加入%X{traceId}占位符(对应MDC中的键名):

# Logback/Log4j2通用配置
quarkus.log.console.format=%d{HH:mm:ss} %-5level [%thread] %logger{36} [%X{traceId}] - %msg%n

# 若需要输出到文件,同样修改文件日志格式
quarkus.log.file.format=%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} [%X{traceId}] - %msg%n

3. 业务代码无需修改,正常打日志即可

原有的Logger使用方式完全不变,日志会自动带上当前请求的Trace ID:

@ApplicationScoped
public class FooServiceImpl implements FooService {

  private static final Logger LOG = LoggerFactory.getLogger(FooServiceImpl.class);

  public void doBusinessLogic() {
      // 日志会自动包含traceId,示例输出:14:35:22 ERROR [executor-thread-0] c.e.s.FooServiceImpl [123456789] - 发生错误时
      LOG.error("发生错误时");
  }
}

备选方案:手动注入HttpHeaders(适合简单场景)

如果不想用拦截器,也可以在业务Bean中直接注入HttpHeaders,手动提取Trace ID并放入MDC:

import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import org.slf4j.MDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ApplicationScoped
public class FooServiceImpl implements FooService {

  private static final Logger LOG = LoggerFactory.getLogger(FooServiceImpl.class);
  
  @Context
  HttpHeaders httpHeaders;

  public void doSomething() {
      String traceId = httpHeaders.getHeaderString("x-datadog-trace-id");
      MDC.put("traceId", traceId);
      try {
          LOG.error("发生错误时");
      } finally {
          // 必须手动清理,避免污染后续请求
          MDC.remove("traceId");
      }
  }
}

注意事项

  • 确认请求头名称:若你的DataDog Trace ID使用自定义请求头,需同步修改代码中的DATADOG_TRACE_ID_HEADER值
  • 异步场景:Quarkus默认会自动传递MDC上下文到异步线程,无需额外配置
  • 空值处理:若请求头中无Trace ID,日志中[%X{traceId}]会显示为[],可根据需求添加默认值(比如MDC.put(MDC_TRACE_KEY, traceId != null ? traceId : "unknown"))

内容的提问来源于stack exchange,提问作者GeauxEric

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:55:07