Is this (https://stackoverflow.com/questions/41222405/adding-the-traceid-from-spring-cloud-sleuth-to-response) still the best way to do it in > 1.2.0?
Thanks.
You can extend the TraceFilter and register your own version that will override this method https://github.com/spring-cloud/spring-cloud-sleuth/blob/1.2.x/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java#L403-L416 . In that method you have access to the Response and you can inject the Tracer to get the current span. That way you have both the trace id and you can modify the response headers. Does it make sense?
Note to myself: Add a test and embed that test in the docs
:+1: Thanks and yes, it does.
Wish :):) spring.sleuth.responseheader = true
Heh - I'll close this issue for now but if anyone is interested in reopening it please upvote. If there are quite a few people interested in it we'll come back to the discussion.
is there any example for this, thanks
BTW there is a discussion about this going on here - https://github.com/openzipkin/openzipkin.github.io/issues/48 . So in case of questions "why" we don't allow this by default please let's go to that issue.
I'll prepare sample code of how you can achieve this and update the documentation too.
One note... If you want to do this with versions prior to 1.2.5 you have to create a bean like this, with a @Primary annotation:
@Bean
@Primary
TraceFilter myTraceFilter(BeanFactory beanFactory, final Tracer tracer) {
return new TraceFilter(beanFactory) {
@Override protected void addResponseTags(HttpServletResponse response,
Throwable e) {
// execute the default behaviour
super.addResponseTags(response, e);
// for readability we're returning trace id in a hex form
response.addHeader("ZIPKIN-TRACE-ID",
Span.idToHex(tracer.getCurrentSpan().getTraceId()));
// we can also add some custom tags
tracer.addTag("custom", "tag");
}
};
}
@marcingrzejszczak We used HandlerInterceptorAdapter to implement this with the following code:
@Slf4j
@RequiredArgsConstructor
public class TraceHeaderInterceptor extends HandlerInterceptorAdapter {
private static final String TRACE_ID = "TraceId";
private final BeanFactory beanFactory;
private Tracer tracer;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
if (getTracer().isTracing() && StringUtils.isEmpty(response.getHeader(TRACE_ID))) {
response
.setHeader(TRACE_ID, Span.idToHex(getTracer().getCurrentSpan().getTraceId()));
}
return true;
}
private Tracer getTracer() {
if (tracer == null) {
tracer = beanFactory.getBean(Tracer.class);
}
return tracer;
}
}
Seems like TraceFilter was removed on 2.0.0. Is there an alternative to have the trace ID on response headers?
We're doing the following bean registration
@Bean
public FilterRegistrationBean traceWebFilter(
TracingFilter tracingFilter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(tracingFilter);
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST);
filterRegistrationBean.setOrder(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER);
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean exceptionThrowingFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new ExceptionLoggingFilter());
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST);
filterRegistrationBean.setOrder(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1);
return filterRegistrationBean;
}
@Bean
@ConditionalOnMissingBean
public TracingFilter tracingFilter(HttpTracing tracing) {
return (TracingFilter) TracingFilter.create(tracing);
}
You can create your own filter that starts after the TracingFilter one and set the trace id in the response.
Can this be as simple as an annotation @EnableTraceIdsInResponse?
If you create such an annotation then for sure it can :)
One note... If you want to do this with versions prior to
1.2.5you have to create a bean like this, with a@Primaryannotation:@Bean @Primary TraceFilter myTraceFilter(BeanFactory beanFactory, final Tracer tracer) { return new TraceFilter(beanFactory) { @Override protected void addResponseTags(HttpServletResponse response, Throwable e) { // execute the default behaviour super.addResponseTags(response, e); // for readability we're returning trace id in a hex form response.addHeader("ZIPKIN-TRACE-ID", Span.idToHex(tracer.getCurrentSpan().getTraceId())); // we can also add some custom tags tracer.addTag("custom", "tag"); } }; }
response.isCommitted() and response can't Modify
with spring-cloud Hoxton.RELEASE, I have done following implementation
public class ResponseTrackingFilter extends OncePerRequestFilter {
private static final String TRACKING_HEADER = "X-TRACKING-ID";
private Tracer tracer;
@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
final Span currentSpan = tracer.currentSpan();
if (null != currentSpan && StringUtils.isEmpty(response.getHeader(TRACKING_HEADER))) {
final String traceId = currentSpan.context().traceIdString();
log.debug("Added tracking id in response - {}", traceId);
response.setHeader(TRACKING_HEADER, traceId);
}
filterChain.doFilter(request, response);
}
}
Most helpful comment
:+1: Thanks and yes, it does.
Wish :):) spring.sleuth.responseheader = true