如何在Sleuth日志中添加X-B3-TraceId请求头信息
解决Spring Boot Sleuth日志中添加X-B3-TraceId请求头的问题
方案1:基于MDC自定义日志格式(推荐)
通过MDC(映射诊断上下文)存储请求头信息,再修改日志格式将其输出,是最直接的实现方式。
步骤1:编写请求头拦截器
创建拦截器提取X-B3-TraceId并放入MDC,请求结束后清理:
import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class RequestTraceIdInterceptor implements HandlerInterceptor { private static final String REQUEST_TRACE_ID_KEY = "requestTraceId"; private static final String X_B3_TRACE_ID_HEADER = "X-B3-TraceId"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String traceIdHeader = request.getHeader(X_B3_TRACE_ID_HEADER); if (traceIdHeader != null) { MDC.put(REQUEST_TRACE_ID_KEY, traceIdHeader); } return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { MDC.remove(REQUEST_TRACE_ID_KEY); } }
步骤2:注册拦截器
将拦截器加入Spring MVC的拦截器链,覆盖所有API路径:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { private final RequestTraceIdInterceptor traceIdInterceptor; public WebMvcConfig(RequestTraceIdInterceptor traceIdInterceptor) { this.traceIdInterceptor = traceIdInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**"); } }
步骤3:修改日志格式配置
在application.properties或application.yml中更新日志格式,引入MDC中的requestTraceId:
# application.properties logging.pattern.level=%5p [%X{spring.application.name},%X{traceId},%X{spanId},%X{requestTraceId:-null}]
YAML格式:
# application.yml logging: pattern: level: "%5p [%X{spring.application.name},%X{traceId},%X{spanId},%X{requestTraceId:-null}]"
最终日志输出示例:
2022-11-02 17:45:16.176 INFO [app-name,c9f95e8f223dca74,c9f95e8f223dca74,abc123456789] 35436 - ...
方案2:自定义Sleuth Span日志逻辑
如果需要和Sleuth Span深度绑定,可以自定义SpanLogger实现:
步骤1:给Span添加请求头标签
在拦截器中把X-B3-TraceId作为Span的标签存储:
// 在RequestTraceIdInterceptor的preHandle方法中添加 import org.springframework.cloud.sleuth.Tracer; // 注入Tracer private final Tracer tracer; // ... if (traceIdHeader != null) { tracer.currentSpan().tag(X_B3_TRACE_ID_HEADER, traceIdHeader); }
步骤2:自定义SpanLogger
实现Sleuth的SpanLogger接口,在日志中输出请求头信息:
import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.log.SpanLogger; import org.springframework.stereotype.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component public class CustomSpanLogger implements SpanLogger { private static final Logger log = LoggerFactory.getLogger(CustomSpanLogger.class); private static final String X_B3_TRACE_ID_HEADER = "X-B3-TraceId"; @Override public void logStartedSpan(Span span) { String requestTraceId = span.tag(X_B3_TRACE_ID_HEADER); log.info("Span started | app: {}, traceId: {}, spanId: {}, requestTraceId: {}", span.serviceName(), span.traceId(), span.spanId(), requestTraceId); } // 按需实现logStoppedSpan、logAbortedSpan等方法 }
注意事项
- 若请求中无
X-B3-TraceId头,可通过%X{requestTraceId:-null}设置默认值避免空值 - Sleuth 3.1.x已与Micrometer Tracing整合,代码需适配对应版本的API
- 拦截器需覆盖所有需要追踪的API路径,确保请求头能被正确提取
内容的提问来源于stack exchange,提问作者Viraj Dhamal
相关产品推荐
相关产品推荐

