3

My application is a spring-rabbitmq based application(neither spring-cloud nor spring-boot), requests were received from one queue and sent responses to another queue.

I want to use brave to trace the system by injecting Zipkin headers before sending messages and extracting Zipkin headers right after receiving messages.

The problem is In step3 of the following scenario, how can I get span1 before sending message?

Scenario:

step1, app -> mq (new created span1, root span, client)
step2, mq -> app (receive span1, server)
step3, app -> mq (**new created span2, child span of span1, client**)
step4, mq -> app (receive span2, server)

Code snippet before sending message:

     try{
        Span currentSpan = tracer.currentSpan();
        Span newSpan = null;
        if(currentSpan == null){
            newSpan = tracer.newTrace();
        }else{
            newSpan = tracer.newChild(currentSpan.context());
        }

        Map<String, String> strHeaders = new HashMap<String, String>();
        tracing.propagation().injector(Map<String, String>::put).inject(newSpan.context(),strHeaders);
        messageProperties.setHeader("zipkin.brave.tracing.headers", strHeaders);
        newSpan.name("send").kind(Kind.CLIENT).start().flush();
    }catch(Exception e){
        logger.warn("zipkin problem", e);
    }

In the above code, Span currentSpan = tracer.currentSpan(); , the currentSpan is always null.

Code snippet after receiving message:

    try{
        Map<String, Object> msgHeaders = messageProperties.getHeaders();
        Object headersObj = msgHeaders.get("zipkin.brave.tracing.headers");
        Map<String, String> strHeaders = null;
        if(headersObj != null){
            strHeaders = (HashMap<String, String>)headersObj;
        }
        TraceContextOrSamplingFlags result = tracing.propagation().extractor(Map<String, String>::get).extract(strHeaders);

        if(result.context() != null){
            Span clientSpan = tracer.joinSpan(result.context());
            clientSpan.name("receive").kind(Kind.SERVER).start().flush();
        }
    }catch(Exception e){
        logger.warn("zipkin problem", e);
    }

Brave configuration code:

@Configuration
public class BraveSpringConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(BraveSpringConfiguration.class);

    /** Configuration for how to send spans to Zipkin */
    @Bean
    public Sender sender() {
        logger.debug("okhttpsender");
        return OkHttpSender.create("http://127.0.0.1:9411/api/v1/spans");
    }

    /** Configuration for how to buffer spans into messages for Zipkin */
    @Bean
    public Reporter<Span> reporter() {
        logger.debug("asyncreporter");
        return AsyncReporter.builder(sender()).build();
    }

    /** Controls aspects of tracing such as the name that shows up in the UI */
    @Bean
    public Tracing tracing() {
        logger.debug("one tracing");
        return Tracing.newBuilder()
            .localServiceName("spring-rabbitmq-brave")
            //// log4j2, import brave.context.log4j2.ThreadContextCurrentTraceContext;
            //.currentTraceContext(ThreadContextCurrentTraceContext.create()) // puts trace IDs into logs
            .currentTraceContext(MDCCurrentTraceContext.create()) // puts trace IDs into logs
            .sampler(Sampler.ALWAYS_SAMPLE) // always sampler
            .reporter(reporter())
            .build();
    }

    /** Controls aspects of tracing such as the name that shows up in the UI */
    @Bean
    public Tracer tracer() {
        logger.debug("one tracer");
        return tracing().tracer();
    }
}

Following are my references:

  1. https://github.com/openzipkin/brave/tree/master/brave#one-way-tracing

  2. https://github.com/openzipkin/brave/blob/master/brave/src/test/java/brave/features/async/OneWaySpanTest.java

  3. https://gist.github.com/adriancole/76d94054b77e3be338bd75424ca8ba30

Arghavan
  • 1,125
  • 1
  • 11
  • 17

1 Answers1

5

Problem solved. tracer.withSpanInScope(clientSpan) would do the work.

Note that, withSpanInScope(...) has not been called before sending messages .

  • 2
    Thanks! After few hours of banging my head against the wall this saved my day. – malejpavouk Nov 02 '18 at 13:46
  • @Alpha TAN you saved a day!!! An interesting point is how did you get to know about this solution?? – Dhruv Apr 05 '20 at 15:20
  • @DHRUVBANSAL Glad it helps. The solution comes from the fact that brave works in usual cases. It must work through some way, then I dug into the source :) –  Apr 09 '20 at 05:58