Spring Boot 3迁移后日志中TraceId与SpanId缺失问题排查
可能遗漏的配置及修复步骤
1. 统一依赖版本,避免冲突
你使用了latest.release的BOM,建议明确指定与Spring Boot 3.x匹配的固定版本,防止版本兼容问题。例如Spring Boot 3.2.x对应micrometer-tracing-bom的1.2.x版本,可修改BOM依赖:
implementation platform('io.micrometer:micrometer-tracing-bom:1.2.4')
2. 确认自动配置生效
确保项目入口类使用了@SpringBootApplication(已包含@EnableAutoConfiguration),micrometer tracing的自动配置类才会正常加载。如果自定义了配置类,检查是否误排除了相关自动配置组件。
3. 日志格式配置适配日志框架
如果使用Spring Boot默认的Logback,除了application.yml中的配置,也可以直接在logback-spring.xml里明确配置PatternLayout,确保MDC中的traceId/spanId被正确读取:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %5p [${spring.application.name:-},%X{traceId:-},%X{spanId:-}] [%thread] %logger{36} - %msg%n</pattern> </encoder> </appender>
若使用Log4j2,需对应调整日志格式配置,确保%X{traceId}和%X{spanId}能被正确解析。
4. 验证追踪上下文是否初始化
在Controller中手动打印MDC内容,确认traceId/spanId是否存在:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { private static final Logger log = LoggerFactory.getLogger(TestController.class); @GetMapping("/test") public String testTrace() { log.info("测试追踪ID"); log.info("MDC traceId: {}", MDC.get("traceId")); log.info("MDC spanId: {}", MDC.get("spanId")); return "OK"; } }
如果这里能获取到值,说明追踪上下文正常,问题出在日志格式配置;如果拿不到,说明追踪未初始化,需重新检查依赖和自动配置。
5. 排查自定义MDC组件冲突
若项目中有自定义的MDC拦截器、过滤器,可能会清除或覆盖micrometer注入的traceId/spanId,需要排查这类代码,确保不会干扰micrometer的MDC逻辑。
6. 非Web场景手动创建追踪上下文
micrometer tracing默认对Web请求自动创建trace和span,但后台任务(如@Scheduled)需要手动初始化追踪上下文:
import io.micrometer.tracing.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class ScheduledTask { private final Tracer tracer; private static final Logger log = LoggerFactory.getLogger(ScheduledTask.class); public ScheduledTask(Tracer tracer) { this.tracer = tracer; } @Scheduled(fixedRate = 5000) public void runTask() { try (Tracer.SpanInScope span = tracer.startScopedSpan("scheduled-task")) { log.info("定时任务执行中"); } } }
内容的提问来源于stack exchange,提问作者htmoia

