Search code examples
spring-bootkotlinmicrometerjaeger

Micrometer Tracing, Spring Boot 3.0, OTLP exporter class not found error


I have Spring Boot 3.0 based project, Kotlin and Micrometer Tracing (which superseded Spring Cloud Sleuth) Trying to connect Micrometer tracing to OTLP collector, which is part of Jaeger.

The configuration class:

@Configuration
class OpenTelemetryConfiguration(
    @Value("\${otel.exporter.otlp.traces.endpoint:http://localhost:4317}")
    private val tracesEndpoint: String
) {
    @Bean
    fun spanExporter(): SpanExporter =
        OtlpGrpcSpanExporter.builder().setEndpoint(tracesEndpoint).build()

    @Bean
    fun jaegerPropagator(): TextMapPropagator =
        JaegerPropagator.getInstance()

}

Dependencies in gradle:

implementation("io.micrometer:micrometer-core:1.11.0")
implementation("io.micrometer:micrometer-tracing:1.1.1")
implementation("io.micrometer:micrometer-registry-prometheus:1.10.5")
implementation("io.micrometer:micrometer-tracing-bridge-otel:1.1.1")
implementation("io.opentelemetry:opentelemetry-sdk:1.26.0")
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.26.0")
implementation("io.opentelemetry:opentelemetry-exporter-common:1.26.0")
implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.26.0")

The error when application starts:

Failed to instantiate [io.opentelemetry.sdk.trace.export.SpanExporter]: Factory method 'spanExporter' threw exception with message: io/opentelemetry/exporter/internal/otlp/OtlpUserAgent
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:171)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
    ... 170 common frames omitted
Caused by: java.lang.NoClassDefFoundError: io/opentelemetry/exporter/internal/otlp/OtlpUserAgent
    at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.<init>(OtlpGrpcSpanExporterBuilder.java:48)
    at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter.builder(OtlpGrpcSpanExporter.java:40)
    at com.logindex.geoservice.configuration.OtelConfiguration.spanExporter(OtelConfiguration.kt:19)
    ... 171 common frames omitted
Caused by: java.lang.ClassNotFoundException: io.opentelemetry.exporter.internal.otlp.OtlpUserAgent
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)

What dependency is missing there? there's no such class io.opentelemetry.exporter.internal.otlp.OtlpUserAgent in the library io.opentelemetry:opentelemetry-exporter-otlp:1.26.0


Solution

  • OTel is not stable yet so not every version of the OTel SDK is compatible with every version of Micrometer Tracing due to breaking changes in the OTel SDK.

    You should delete all of your version definitions and let the Spring Boot BOM define versions for you, this is what you need:

    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'io.micrometer:micrometer-registry-prometheus'
    implementation 'io.micrometer:micrometer-tracing-bridge-otel'
    implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
    

    Btw Jaeger also supports Zipkin so you can use Brave too with the Zipkin exporter.