Micrometer Tracing:MDC中32位traceId含spanId,如何改为16位?
问题背景
按预期写入MDC的spanId和traceId应为16位字符串,但实际应用中发现spanId是32位traceId的一部分,日志示例如下:
2023-10-31, [[[traceId=6540ee3f2997f144f45483631005208e, spanId=f45483631005208e]]] [http-nio-8085-exec-1] INFO com.example.trace.Controller - Inside Hi
使用技术栈:Micrometer-tracing v1.1.6,底层依赖Brave v5.15.1,application.properties配置如下:
server.port=8085 spring.application.name=exampleApp logging.pattern.console=%d{yyyy-MM-dd }, [[[%mdc]]] [%thread] %-5level %logger{36} - %msg%n management.tracing.sampling.probability=0.0 management.tracing.propagation.type=B3_MULTI logging.level.root=info
调试时定位到Brave生成traceId的核心方法:
static String toTraceIdString(long traceIdHigh, long traceId) { if (traceIdHigh != 0) { char[] result = RecyclableBuffers.parseBuffer(); writeHexLong(result, 0, traceIdHigh); writeHexLong(result, 16, traceId); return new String(result, 0, 32); } return toLowerHex(traceId); }
需要实现让MDC中写入16位traceId,而非包含spanId的32位traceId。
解决方案
1. 自定义TraceId转换器
Brave支持通过TraceIdConverter接口自定义traceId的输出格式,我们实现一个仅返回16位traceId的转换器:
import brave.TraceIdConverter; import brave.internal.HexCodec; public class ShortTraceIdConverter implements TraceIdConverter { @Override public String convert(long traceIdHigh, long traceId) { // 忽略traceIdHigh,只返回traceId对应的16位十六进制字符串 return HexCodec.toLowerHex(traceId); } }
2. 注册自定义转换器到Brave上下文
通过Spring配置类将自定义转换器注入Brave的Tracing实例,确保MDC使用该格式输出:
import brave.Tracing; import brave.context.slf4j.MDCScopeDecorator; import brave.propagation.B3Propagation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TracingConfig { @Bean public Tracing tracing() { return Tracing.newBuilder() .traceIdConverter(new ShortTraceIdConverter()) // 绑定自定义转换器 .propagationFactory(B3Propagation.newFactoryBuilder() .injectFormat(B3Propagation.Format.MULTI) // 匹配B3_MULTI传播配置 .build()) .scopeDecorator(MDCScopeDecorator.create()) // 保证MDC上下文同步 .build(); } }
3. 验证效果
重启应用后,日志中的traceId将变为16位,示例如下:
2023-10-31, [[[traceId=f45483631005208e, spanId=f45483631005208e]]] [http-nio-8085-exec-1] INFO com.example.trace.Controller - Inside Hi
原理说明
Brave默认在traceIdHigh非0时,将traceIdHigh(64位)和traceId(64位)拼接生成32位traceId。通过自定义TraceIdConverter,我们强制只返回traceId对应的16位十六进制字符串,从而让MDC输出符合预期的16位traceId。
内容的提问来源于stack exchange,提问作者Arun Gowda

