Spring Boot 2.7集成OpenTelemetry追踪:TraceId与SpanId全为0问题
核心问题分析
你遇到的TraceId/SpanId全0问题,主要源于依赖配置不匹配、Sleuth与OTel Java Agent冲突或者日志上下文未正确绑定这几个方面。以下是针对性的解决方案:
1. 确保依赖配置完全正确
正确排除Brave并引入OTel整合依赖
在pom.xml中,必须彻底排除Spring Cloud Sleuth默认的Brave实现,同时引入Sleuth-OTel自动配置依赖:
<dependencies> <!-- Spring Cloud Sleuth 核心依赖,排除Brave --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-brave</artifactId> </exclusion> </exclusions> </dependency> <!-- Sleuth 与 OpenTelemetry 整合依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-otel-autoconfigure</artifactId> </dependency> </dependencies>
匹配正确的版本依赖管理
Spring Boot 2.7对应Spring Cloud 2021.0.x(Jubilee版本),必须在dependencyManagement中导入对应版本的Sleuth-OTel BOM,避免版本冲突:
<dependencyManagement> <dependencies> <!-- Spring Cloud 版本 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.5</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Sleuth-OTel 版本 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-otel-dependencies</artifactId> <version>1.1.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2. 处理OTel Java Agent与Sleuth的冲突
你同时使用了opentelemetry-javaagent和Sleuth-OTel依赖,这两者会存在上下文传递冲突:
- Sleuth-OTel是基于OTel SDK的上层封装,通过Spring自动配置实现追踪;
- OTel Java Agent是字节码增强实现,直接修改应用类加载逻辑生成追踪。
二选一方案:
方案A:仅使用Sleuth-OTel(无Java Agent)
移除opentelemetry-javaagent启动参数,依赖Sleuth-OTel的自动配置完成追踪。此时日志中使用Sleuth的MDC变量:
<!-- Logback 配置示例 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %X{traceId:-} %X{spanId:-}%n</pattern> </encoder> </appender>
方案B:仅使用OTel Java Agent(移除Sleuth依赖)
删除所有Spring Cloud Sleuth相关依赖,仅通过Java Agent实现追踪。启动时添加以下参数:
java -javaagent:opentelemetry-javaagent-1.22.0.jar \ -Dotel.resource.attributes=service.name=your-rest-api \ -Dotel.traces.exporter=otlp \ # 根据你的后端配置调整,比如zipkin -jar your-app.jar
此时日志中需要使用OTel原生的MDC变量(下划线命名):
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %X{trace_id:-} %X{span_id:-}%n</pattern>
3. 验证日志上下文绑定
确保你的日志框架(Logback/Log4j2)正确配置了MDC变量,并且Sleuth-OTel的上下文拦截器已被Spring加载。可以通过打印MDC内容验证:
@GetMapping("/test") public String test() { Map<String, String> mdcMap = MDC.getCopyOfContextMap(); System.out.println("MDC Context: " + mdcMap); return "Hello World"; }
如果输出中没有traceId/trace_id和spanId/span_id,说明上下文未正确绑定,需要检查Spring是否自动配置了OtelTraceAutoConfiguration类。
4. 排查自定义配置干扰
如果你有自定义的WebMvcConfigurer或过滤器,确保没有覆盖Sleuth的拦截器。Sleuth-OTel会自动注册TraceInterceptor,如果你的配置中使用了@EnableWebMvc,需要手动引入Sleuth的拦截器:
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private TraceInterceptor traceInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(traceInterceptor); // 其他自定义拦截器 } }
内容的提问来源于stack exchange,提问作者vigamage

