Hi guys, I'm trying to use RestClient together with Micrometer's Observation API, what i'm trying to do is to supply some additional context, the "senderServiceName", that i'd like to exist as a tag in my metrics. Today, the internalExchange looks the following way:

...
ClientRequestObservationContext observationContext = new ClientRequestObservationContext(clientRequest);
observationContext.setUriTemplate(this.uriTemplate);
observation = ClientHttpObservationDocumentation.HTTP_CLIENT_EXCHANGES.observation(observationConvention,
        DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry).start();
...

As you can see, the observationContext is being composed from the request carrier, and directly sent to the observation. As the logic of the request creation has its complexity, I've thought of just passing an UnaryOperator which will allow me the take the initialized context, modify it (maybe to an extension of ClientRequestObservationContext) and return the modified version.

Something like:

private <T> T exchangeInternal(ExchangeFunction<T> exchangeFunction, ExchangeOptions exchangeOptions) {
    Assert.notNull(exchangeFunction, "ExchangeFunction must not be null");
    Assert.notNull(exchangeOptions, "ExchangeOptions must not be null");

    ClientHttpResponse clientResponse = null;
    Observation observation = null;
    URI uri = null;
    try {
        if (DefaultRestClient.this.defaultRequest != null) {
            DefaultRestClient.this.defaultRequest.accept(this);
        }
        uri = initUri();
        HttpHeaders headers = initHeaders();
        ClientHttpRequest clientRequest = createRequest(uri);
        clientRequest.getHeaders().addAll(headers);
        ClientRequestObservationContext observationContext = exchangeOptions.observationContextOperator()
                .apply(new ClientRequestObservationContext(clientRequest));
        observationContext.setUriTemplate(this.uriTemplate);
        observation = ClientHttpObservationDocumentation.HTTP_CLIENT_EXCHANGES.observation(observationConvention,
                DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry).start();
...
}

Should I issue a PR which allows it?

Thanks.

Comment From: bclozel

I don't think this would make sense from an API perspective. You can already configure a custom convention and this should have everything it needs from the request. I would suggest looking into #32027 as a possible way out for this would be to use a request attribute or a request context holder. This senderServiceName information could be then extracted by your custom convention without changing this internal contract.

Comment From: davebarda

I don't think this would make sense from an API perspective. You can already configure a custom convention and this should have everything it needs from the request. I would suggest looking into #32027 as a possible way out for this would be to use a request attribute or a request context holder. This senderServiceName information could be then extracted by your custom convention without changing this internal contract.

In my context, which isn't an Http request, I don't find the usage of random globals a safer nor cleaner way of setting context for the observability, afterall, it is what it is, an observation context...

Comment From: bclozel

@davebarda this could be an argument for a request attribute feature, then. Can you make this case in the linked issue and explain how you're solving this problem with RestTemplate please?