javaspringmicrometerspring-micrometermicrometer-tracing

Micrometer tracing: Why spanId is a part of traceId and 32 characters long instead of 16?


AFAIK, spanId and traceId which goes into MDC are 16 character Strings. But in my application, I noticed the spanId is part of the 32 character traceId. Below is a sample of the same.

2023-10-31, [[[traceId=6540ee3f2997f144f45483631005208e, spanId=f45483631005208e]]] [http-nio-8085-exec-1] INFO com.example.trace.Controller - Inside Hi

I am using micrometer-tracing v1.1.6 with Brave v5.15.1 as my vendor. Following is my application.properties

server.port=8085
spring.application.name=exampleApp

logging.pattern.console=%d{yyyy-MM-dd }, [[[%mdc]]] [%thread] %-5level %logger{36} - %msg%n

management.tracing.sampling.probability=0.0
management.tracing.propagation.type=B3_MULTI

logging.level.root=info

I tried looking into things in debugging mode and found the method that generates it:

static String toTraceIdString(long traceIdHigh, long traceId) {
    if (traceIdHigh != 0) {
      char[] result = RecyclableBuffers.parseBuffer();
      writeHexLong(result, 0, traceIdHigh);
      writeHexLong(result, 16, traceId);
      return new String(result, 0, 32);
   }
    return toLowerHex(traceId);
}

However this didn't help me much.

How do I get this to add 16 character traceId into MDC instead of 32 character traceId+spanId as traceId?


Solution

  • This is happening because, in BraveAutoConfiguration the Tracing object is built with .traceId128Bit(true).

    To override this, we will have to define custom Tracing bean within our application instead of relying on Spring auto config.

    Following is the bean(Taken from BraveAutoConfiguration class and tweaked as necessary):

    package com.example.trace;
    
    
    import brave.Tracing;
    import brave.TracingCustomizer;
    import brave.handler.SpanHandler;
    import brave.propagation.CurrentTraceContext;
    import brave.propagation.Propagation;
    import brave.sampler.Sampler;
    import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    
    import java.util.List;
    
    @Configuration
    @EnableConfigurationProperties(TracingProperties.class)
    public class BraveAutoConf {
    
    
        @Bean
        public Tracing braveTracing(Environment environment, TracingProperties properties, List<SpanHandler> spanHandlers,
                                    List<TracingCustomizer> tracingCustomizers, CurrentTraceContext currentTraceContext,
                                    Propagation.Factory propagationFactory, Sampler sampler) {
    
    
            //NOTE: skipped the type/produce/consume=W3C and span joining property compatibility check. (This is invalid config)
    
            String applicationName = environment.getProperty("spring.application.name", "AppName");
            Tracing.Builder builder = Tracing.newBuilder()
                    .currentTraceContext(currentTraceContext)
                    .traceId128Bit(false)
                    .supportsJoin(properties.getBrave().isSpanJoiningSupported())
                    .propagationFactory(propagationFactory)
                    .sampler(sampler)
                    .localServiceName(applicationName);
            spanHandlers.forEach(builder::addSpanHandler);
            for (TracingCustomizer tracingCustomizer : tracingCustomizers) {
                tracingCustomizer.customize(builder);
            }
            return builder.build();
        }
    
    }
    

    This will generate 16 character traceId instead of 32 character trace+spanId. However, do note that the traceId and the first spanId will be the same with this configuration.