spring-webfluxspring-cloud-sleuthmicrometer-tracing

Need help in initiating the trace context for non HTTP request


We are consuming the message from queue, process getting initiated in the service (having lot of logs in this service) immediately and invokes multiple downstream using HTTP rest client.

we able to generate the trace context(traceId, txnId) for down stream HTTP requests, however we are unable to generate trace context and set it at the place message consume.

Basically we are trying to generate traceId, txnId as soon as message is consumed from queue and use it for log in the service + down stream services.

Tried the following 4 approaches but unable to generate trace context and pass it to downstream.

  1. Hooks.enableAutomaticContextPropagation(); and setting the contextWrite

  2. contextWrite(Context.of(TraceContext.class, context));

  3. Observation observation = Observation.createNotStarted(...);

  4. MDC.put('txnId','')

Spring boot v2.7.14 Reactor core v3.4.31

enableAutomaticContextPropagation supported in Reactor core v3.5.3, unfortunately Spring boot version can not be upgraded at the moment. Is there any other possible way to enable the context propagation downstream?

long generatedLong = new Random().nextLong();

String txnId = StringUtils.lowerCase(RandomStringUtils.randomAlphabetic(16));

final BaggageField baggageField = 
BaggageField.create(TXN_ID_BAGGAGE);
baggageField.updateValue(txnId);

final BaggageFields baggageFields = BaggageFields.newFactory(List.of(baggageField), 1).create();

final TraceContext traceContext = TraceContext.newBuilder().traceId(generatedLong)
 .spanId(generatedLong)
 .parentId(generatedLong)
 .addExtra(baggageFields).build();

return Mono.defer(() -> {
   return validate(request).then(Mono.defer(() -> {
           return service.modify(request)
                  .then(successResponse())
                  .onErrorResume(e -> errorResponse(e));
            })).onErrorResume(e -> errorResponse(e));
        }).contextWrite(Context.of(TraceContext.class, traceContext));

Solution

  • Initiate the span at the start of the invocation and propagated the context

    private final Tracer tracer;
    var span = tracer.spanBuilder().start();
    final TraceContext context = span.context();
    return Mono.defer(() -> {
          ..............
          ..............
    ).contextWrite(Context.of(TraceContext.class, context))
    .doFinally(f -> span.end());