spring-bootmicrometerdistributed-tracingotel

Spring Boot 3.1.0: Problems with custom io.opentelemetry.sdk.trace.samplers.Sampler and OTLP/Spring Boot: empty/undefined span information


I am using Micrometer / OTLP in Spring Boot (MVC web services). The tracing information is visualized with Jaeger. TraceId and SpanId are generated and added to the MDC, visualization is working fine, I can see all the spans with application name and REST method information in Jaeger.

But I am encountering problems, when trying to process spans using a custom implementation of io.opentelemetry.sdk.trace.samplers.Sampler in order to exclude some spans based on the URL (e.g. health checks), along the lines of this example: https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/examples/extension/src/main/java/com/example/javaagent/DemoSampler.java

Versions:

Excerpt from pom.xml:

    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>io.micrometer</groupId>
          <artifactId>micrometer-tracing-bom</artifactId>
          <version>1.1.2</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>


    <dependency>
      <groupId>io.micrometer</groupId>
      <artifactId>micrometer-tracing</artifactId>
    </dependency>
    <dependency>
      <groupId>io.micrometer</groupId>
      <artifactId>micrometer-tracing-bridge-otel</artifactId>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-exporter-otlp</artifactId>
    </dependency>

Excerpt from application.yaml:

management:
  tracing:
    enabled: true
    sampling:
      probability: 1.0
  otlp:
    tracing:
      endpoint: http://localhost:14318/v1/traces

This custom Sampler is provided as a @Bean (the code is in Kotlin):

class CustomOtlpSampler : Sampler {

    override fun shouldSample(
        parentContext: Context,
        traceId: String,
        name: String,
        spanKind: SpanKind,
        attributes: Attributes,
        parentLinks: List<LinkData>
    ): SamplingResult {

        if (name.contains("health") || name.contains("apidoc")) {
            return SamplingResult.create(SamplingDecision.DROP)
        }
        return SamplingResult.create(SamplingDecision.RECORD_AND_SAMPLE);
    }

    override fun getDescription(): String = "CustomSampler"
}

When calling a REST method, the debugging stops in the method shouldSample(...), but every time I see in the debugger:

name = "<unspecified name>"
attributes = {}

Actually, when removing this @Bean and installing a breakpoint in io.opentelemetry.sdk.trace.samplers.TraceIdRatioBasedSampler, debugging stops there as expected, but I see the same "empty/undefined" values.

My question: How can I access the URL of the method for the span?


Solution

  • in order to exclude some spans based on the URL

    A sampler is not meant to do this. You can either use a SpanExportingPredicate or an ObservationPredicate, I recommend the latter. See more info: