package com.github.kristofa.brave.resteasy; import javax.ws.rs.ext.Provider; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.ClientRequestAdapter; import com.github.kristofa.brave.ClientRequestInterceptor; import com.github.kristofa.brave.ClientResponseAdapter; import com.github.kristofa.brave.ClientResponseInterceptor; import com.github.kristofa.brave.ClientTracer; import com.github.kristofa.brave.NoAnnotationsClientResponseAdapter; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpClientRequest; import com.github.kristofa.brave.http.HttpClientRequestAdapter; import com.github.kristofa.brave.http.HttpClientResponseAdapter; import com.github.kristofa.brave.http.HttpResponse; import com.github.kristofa.brave.http.SpanNameProvider; import org.jboss.resteasy.annotations.interception.ClientInterceptor; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.spi.interception.ClientExecutionContext; import org.jboss.resteasy.spi.interception.ClientExecutionInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import static com.github.kristofa.brave.internal.Util.checkNotNull; /** * {@link ClientExecutionInterceptor} that uses the {@link ClientTracer} to set up a new span. </p> It adds the necessary * HTTP header parameters to the request to propagate trace information. It also adds some span annotations: * <ul> * <li>Binary Annotation, key: request, value: http method and full request url.</li> * <li>Binary Annoration, key: response.code, value: http reponse code. This annotation is only submitted when response code * is unsuccessful</li> * <li>Annotation: failure. Only submitted when response code is unsuccessful. This allows us to filter on unsuccessful * requests. * </ul> * If you add a http header with key: X-B3-SpanName, and with a custom span name as value this value will be used as span * name iso the path. * <p/> * We assume the first part of the URI is the context path. The context name will be used as service name in endpoint. * Remaining part of path will be used as span name unless X-B3-SpanName http header is set. For example, if we have URI: * <p/> * <code>http://localhost:8080/service/path/a/b</code> * <p/> * The service name will be 'service. The span name will be '/path/a/b'. * * @author kristof * @deprecated There is no plan to continue supporting RestEasy 2.x */ @Deprecated @Component @Provider @ClientInterceptor public class BraveClientExecutionInterceptor implements ClientExecutionInterceptor { /** Creates a tracing interceptor with defaults. Use {@link #builder(Brave)} to customize. */ public static BraveClientExecutionInterceptor create(Brave brave) { return new Builder(brave).build(); } public static Builder builder(Brave brave) { return new Builder(brave); } public static final class Builder { final Brave brave; SpanNameProvider spanNameProvider = new DefaultSpanNameProvider(); Builder(Brave brave) { // intentionally hidden this.brave = checkNotNull(brave, "brave"); } public Builder spanNameProvider(SpanNameProvider spanNameProvider) { this.spanNameProvider = checkNotNull(spanNameProvider, "spanNameProvider"); return this; } public BraveClientExecutionInterceptor build() { return new BraveClientExecutionInterceptor(this); } } private final ClientRequestInterceptor requestInterceptor; private final ClientResponseInterceptor responseInterceptor; private final SpanNameProvider spanNameProvider; @Autowired // internal BraveClientExecutionInterceptor(SpanNameProvider spanNameProvider, Brave brave) { this(builder(brave).spanNameProvider(spanNameProvider)); } BraveClientExecutionInterceptor(Builder b) { // intentionally hidden this.requestInterceptor = b.brave.clientRequestInterceptor(); this.responseInterceptor = b.brave.clientResponseInterceptor(); this.spanNameProvider = b.spanNameProvider; } /** * Create a new instance. * * @param spanNameProvider Provides span name. * @param requestInterceptor Client request interceptor. * @param responseInterceptor Client response interceptor. * @deprecated please use {@link #create(Brave)} or {@link #builder(Brave)} */ @Deprecated public BraveClientExecutionInterceptor(SpanNameProvider spanNameProvider, ClientRequestInterceptor requestInterceptor, ClientResponseInterceptor responseInterceptor) { this.requestInterceptor = requestInterceptor; this.spanNameProvider = spanNameProvider; this.responseInterceptor = responseInterceptor; } /** * {@inheritDoc} */ @Override public ClientResponse<?> execute(final ClientExecutionContext ctx) throws Exception { final ClientRequest request = ctx.getRequest(); final HttpClientRequest httpClientRequest = new RestEasyHttpClientRequest(request); final ClientRequestAdapter adapter = new HttpClientRequestAdapter(httpClientRequest, spanNameProvider); requestInterceptor.handle(adapter); ClientResponse<?> response = null; try { response = ctx.proceed(); } catch (final Exception e) { throw e; } finally { if (response != null) { final HttpResponse httpResponse = new RestEasyHttpClientResponse(response); final ClientResponseAdapter responseAdapter = new HttpClientResponseAdapter(httpResponse); responseInterceptor.handle(responseAdapter); } else { responseInterceptor.handle(NoAnnotationsClientResponseAdapter.getInstance()); } } return response; } }