package brave.spring.webmvc;
import brave.Span;
import brave.Tracer;
import brave.Tracer.SpanInScope;
import brave.Tracing;
import brave.http.HttpServerHandler;
import brave.http.HttpTracing;
import brave.propagation.TraceContext;
import brave.servlet.HttpServletAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/**
* Tracing interceptor for Spring Web MVC, which can be used as both an {@link
* AsyncHandlerInterceptor} or a normal {@link HandlerInterceptor}.
*/
public final class TracingHandlerInterceptor extends HandlerInterceptorAdapter {
public static AsyncHandlerInterceptor create(Tracing tracing) {
return new TracingHandlerInterceptor(HttpTracing.create(tracing));
}
public static AsyncHandlerInterceptor create(HttpTracing httpTracing) {
return new TracingHandlerInterceptor(httpTracing);
}
final Tracer tracer;
final HttpServerHandler<HttpServletRequest, HttpServletResponse> handler;
final TraceContext.Extractor<HttpServletRequest> extractor;
@Autowired TracingHandlerInterceptor(HttpTracing httpTracing) { // internal
tracer = httpTracing.tracing().tracer();
handler = HttpServerHandler.create(httpTracing, new HttpServletAdapter());
extractor = httpTracing.tracing().propagation().extractor(HttpServletRequest::getHeader);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) {
if (request.getAttribute(SpanInScope.class.getName()) != null) {
return true; // already handled (possibly due to async request)
}
Span span = handler.handleReceive(extractor, request);
request.setAttribute(SpanInScope.class.getName(), tracer.withSpanInScope(span));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object o, Exception ex) {
Span span = tracer.currentSpan();
if (span == null) return;
((SpanInScope) request.getAttribute(SpanInScope.class.getName())).close();
handler.handleSend(response, ex, span);
}
}