All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brave.okhttp3.TracingInterceptor Maven / Gradle / Ivy

package brave.okhttp3;

import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.http.HttpClientHandler;
import brave.http.HttpTracing;
import brave.propagation.Propagation.Setter;
import brave.propagation.TraceContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import okhttp3.Connection;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import zipkin2.Endpoint;

/**
 * This is a network-level interceptor, which creates a new span for each attempt. Note that this
 * does not work well for high traffic servers, as the span context can be lost when under backlog.
 * In cases like that, use {@link TracingCallFactory}.
 */
public final class TracingInterceptor implements Interceptor {
  static final Setter SETTER = new Setter() {
    @Override public void put(Request.Builder carrier, String key, String value) {
      carrier.header(key, value);
    }

    @Override public String toString() {
      return "Request.Builder::header";
    }
  };

  public static Interceptor create(Tracing tracing) {
    return create(HttpTracing.create(tracing));
  }

  public static Interceptor create(HttpTracing httpTracing) {
    return new TracingInterceptor(httpTracing);
  }

  final Tracer tracer;
  final String remoteServiceName;
  final HttpClientHandler handler;
  final TraceContext.Injector injector;

  TracingInterceptor(HttpTracing httpTracing) {
    if (httpTracing == null) throw new NullPointerException("HttpTracing == null");
    tracer = httpTracing.tracing().tracer();
    remoteServiceName = httpTracing.serverName();
    handler = HttpClientHandler.create(httpTracing, new HttpAdapter());
    injector = httpTracing.tracing().propagation().injector(SETTER);
  }

  @Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    Request.Builder requestBuilder = request.newBuilder();

    Span span = handler.handleSend(injector, requestBuilder, request);
    parseServerAddress(chain.connection(), span);
    Response response = null;
    Throwable error = null;
    try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
      return response = chain.proceed(requestBuilder.build());
    } catch (IOException | RuntimeException | Error e) {
      error = e;
      throw e;
    } finally {
      handler.handleReceive(response, error, span);
    }
  }

  /** This is different than default because the request does not hold the address */
  void parseServerAddress(Connection connection, Span span) {
    if (span.isNoop()) return;
    InetSocketAddress remoteAddress = connection.route().socketAddress();
    Endpoint.Builder builder = Endpoint.newBuilder().serviceName(remoteServiceName);
    builder.parseIp(remoteAddress.getAddress());
    builder.port(remoteAddress.getPort());
    span.remoteEndpoint(builder.build());
  }

  static final class HttpAdapter extends brave.http.HttpClientAdapter {
    @Override public String method(Request request) {
      return request.method();
    }

    @Override public String path(Request request) {
      return request.url().encodedPath();
    }

    @Override public String url(Request request) {
      return request.url().toString();
    }

    @Override public String requestHeader(Request request, String name) {
      return request.header(name);
    }

    @Override public Integer statusCode(Response response) {
      return statusCodeAsInt(response);
    }

    @Override public int statusCodeAsInt(Response response) {
      return response.code();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy