How to instrument Apache HttpClient using micrometer tracing

785 views Asked by At

I'm using spring micrometer for tracing purpose and tried configuring the HttpClient the following way.

MicrometerHttpClientInterceptor interceptorProvider = new MicrometerHttpClientInterceptor(new SimpleMeterRegistry(),
        x -> x.getRequestLine().getUri(),
        Tags.empty(),
        false);


return HttpClients.custom()
        .addInterceptorFirst(interceptorProvider.getRequestInterceptor())
        .addInterceptorLast(interceptorProvider.getResponseInterceptor())
        .build();

But the http client is not adding tracing headers to any of the HTTP requests.

Is there anything equivalent to Brave's instrumentation or any support for interceptors from Micrometer?

1

There are 1 answers

0
Arun Gowda On BEST ANSWER

EDITED ANSWER:

After the initial solution, I later figured out the previous solution (below) creates a new observation leading to generation of new spanIds. This is undesired behavior.

Hence I went with the interceptor approach:

Interceptor:

import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.propagation.Propagator;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpException;
import org.apache.http.HttpMessage;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.protocol.HttpContext;

import java.io.IOException;
import java.util.Arrays;


@Slf4j
public class TracingInterceptorHC4 implements HttpRequestInterceptor {

    private final Tracer tracer;
    private final Propagator propagator;

    public TracingInterceptorHC4(Tracer tracer, Propagator propagator) {
        this.tracer = tracer;
        this.propagator = propagator;
    }

    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        log.debug("Before adding tracing headers: {}", Arrays.toString(request.getAllHeaders()));
        if (tracer.currentSpan() != null) {
            propagator.inject(tracer.currentSpan().context(), request, HttpMessage::addHeader);
        } else {
            log.debug("Current span is absent. Hence skipping tracing headers injection");
        }
        log.debug("After adding tracing headers: {}", Arrays.toString(request.getAllHeaders()));
    }
}

Registering the interceptor while creating client:

return HttpClients.custom()
        .addInterceptorLast( new TracingInterceptorHC4(tracer, propagator))
        .build();

tracer and propagator are taken from Spring container by autowiring.


Previous answer:

I was able to instrument http client by building it the following way:

final MicrometerHttpRequestExecutor httpRequestExecutor = MicrometerHttpRequestExecutor
        .builder(new SimpleMeterRegistry())
        .uriMapper(x -> x.getRequestLine().getUri())
        .observationRegistry(observationRegistry)
        .build();

return HttpClients.custom()
        .setRequestExecutor(httpRequestExecutor)
        .build();

ObservationRegistry is autowired.

There is support for both apache HC4 and HC5. Import accordingly.

I also had missed adding the below properties.

management.tracing.propagation.consume=B3_MULTI
management.tracing.propagation.produce=B3_MULTI