Spring Cloud Sleuth与OpenTelemetry兼容问题:Spring Boot 2.x版本冲突
问题背景
使用Spring Boot 2.7.3结合Spring Cloud Sleuth与OpenTelemetry手动埋点实现可观测性时,遇到版本依赖冲突:opentelemetry-logback-appender-1.0要求opentelemetry-instrumentation-api-semconv版本≥1.29.0,但spring-cloud-sleuth-otel-autoconfigure:1.1.2仅兼容≤1.22.0-alpha的semconv版本,导致循环依赖问题。
现有依赖配置、自定义Bean以及观测栈Docker Compose配置如下:
已添加的OpenTelemetry依赖
<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-logback-appender-1.0</artifactId> <version>1.31.0-alpha</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> <version>1.31.0</version> </dependency> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-instrumentation-api-semconv</artifactId> <version>1.31.0-alpha</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp-common</artifactId> <version>1.31.0</version> </dependency>
项目原有依赖
<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> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> <version>1.23.1</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-otel-autoconfigure</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-metrics</artifactId> <version>1.22.0</version> </dependency> <!-- Micrometer Core --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-core</artifactId> </dependency> <!-- Micrometer Prometheus Registry --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> <!-- Spring Boot Actuator for exposing metrics --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
自定义OpenTelemetry Bean配置
@Bean public Tracer tracer(OpenTelemetry openTelemetry) { return openTelemetry.getTracer("service-name"); } @Bean OpenTelemetry openTelemetry(SdkLoggerProvider sdkLoggerProvider, SdkTracerProvider sdkTracerProvider, ContextPropagators contextPropagators) { OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder() .setLoggerProvider(sdkLoggerProvider) .setTracerProvider(sdkTracerProvider) .setPropagators(contextPropagators) .build(); OpenTelemetryAppender.install(openTelemetrySdk); return openTelemetrySdk; } @Bean SdkLoggerProvider otelSdkLoggerProvider(Environment environment, ObjectProvider logRecordProcessors) { String applicationName = environment.getProperty("spring.application.name", "application"); Resource springResource = Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)); SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder() .setResource(Resource.getDefault().merge(springResource)); logRecordProcessors.orderedStream().forEach(builder::addLogRecordProcessor); return builder.build(); } @Bean LogRecordProcessor otelLogRecordProcessor() { return BatchLogRecordProcessor .builder( OtlpGrpcLogRecordExporter.builder() .setEndpoint("http://localhost:4317") .build()) .build(); }
观测栈Docker Compose配置
version: "4.32" services: collector: image: otel/opentelemetry-collector:0.72.0 command: [ "--config=/etc/otel-config.yml" ] volumes: - ./otel-collector/otel-config.yml:/etc/otel-config.yml ports: - "4317:4317" # OTLP gRPC endpoint - "55681:55681" # OTLP HTTP endpoint - "8889:8889" # Prometheus exporter metrics depends_on: - jaeger-service prometheus: container_name: prometheus image: prom/prometheus command: - --config.file=/etc/prometheus/prometheus.yml - --enable-feature=exemplar-storage - --web.enable-remote-write-receiver volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml restart: always ports: - '9090:9090' depends_on: - collector jaeger-service: image: jaegertracing/all-in-one:latest container_name: jaeger_service_container ports: - "5775:5775" - "5778:5778" - "14250:14250" # gRPC endpoint for OTLP - "14268:14268" # HTTP endpoint for OTLP - "16686:16686" # Jaeger UI - "14250:14250" # Jaeger gRPC endpoint environment: - COLLECTOR_OTLP_ENABLED=true grafana: container_name: grafana image: grafana/grafana volumes: - ./grafana/grafana.yml:/etc/grafana/provisioning/datasources/datasources.yml restart: always ports: - "3000:3000" depends_on: - prometheus - jaeger-service
最佳实践与冲突解决
1. 统一OpenTelemetry版本,匹配Sleuth OTEL兼容范围
Spring Cloud Sleuth OTEL版本与OpenTelemetry核心版本强绑定,spring-cloud-sleuth-otel-autoconfigure:1.1.2基于OpenTelemetry 1.22.x构建,需统一所有OpenTelemetry相关依赖到1.22.x版本:
- 将
opentelemetry-logback-appender降级到1.22.0-alpha - 同步
opentelemetry-instrumentation-api-semconv到1.22.0-alpha - 调整
opentelemetry-sdk、opentelemetry-exporter-otlp、opentelemetry-sdk-metrics到1.22.0
调整后的核心依赖示例:
<!-- OpenTelemetry核心与导出器 --> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> <version>1.22.0</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> <version>1.22.0</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-metrics</artifactId> <version>1.22.0</version> </dependency> <!-- OpenTelemetry Instrumentation与日志Appender --> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-logback-appender-1.0</artifactId> <version>1.22.0-alpha</version> </dependency> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-instrumentation-api-semconv</artifactId> <version>1.22.0-alpha</version> </dependency>
2. 利用Sleuth OTEL自动配置,减少自定义Bean
Spring Cloud Sleuth OTEL已提供大部分OpenTelemetry核心组件的自动配置,无需手动构建OpenTelemetry、SdkLoggerProvider等Bean,仅保留业务所需的Tracer Bean即可:
@Bean public Tracer tracer(OpenTelemetry openTelemetry) { return openTelemetry.getTracer("service-name"); }
通过配置文件完成端点、服务名配置,避免硬编码:
spring.application.name=your-service-name otel.exporter.otlp.endpoint=http://localhost:4317 otel.resource.attributes=service.name=${spring.application.name}
3. 升级Sleuth OTEL版本(推荐)
若需使用更高版本的OpenTelemetry,可升级spring-cloud-sleuth-otel-autoconfigure到对应兼容分支:
- Sleuth OTEL 1.2.x兼容OpenTelemetry 1.28.x
- 确认版本映射关系后,同步所有OTEL依赖版本与Sleuth OTEL版本匹配
4. 观测栈版本适配
当前otel/opentelemetry-collector:0.72.0兼容OpenTelemetry 1.22.x,若升级OTEL版本,需同步升级Collector版本(Collector版本与OTEL核心版本保持一致)。
内容的提问来源于stack exchange,提问作者Rizwan Shakoor

