Reputation:
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:
https://github.com/openzipkin/brave/tree/master/brave#one-way-tracing
https://gist.github.com/adriancole/76d94054b77e3be338bd75424ca8ba30
Upvotes: 3
Views: 2245
Reputation:
Problem solved. tracer.withSpanInScope(clientSpan)
would do the work.
Note that, withSpanInScope(...)
has not been called before sending messages .
Upvotes: 5