-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
Hi,
Here are the versions this discussion is related to :
- Spring 5.1.4.RELEASE
- SpringBoot 2.1.2.RELEASE
- Micrometer 1.1.2
Using reactive WebClient with micrometer give the ability to expose a lot of interesting metrics (such as number of requests, duration, ...).
As describe in the official documentation, metrics generated by an instrumented client are tagged with the request’s URI template prior to variable substitution, if possible (for example, /api/person/{id}).
Indeed, it appears that the URI template cannot be used when specifying uri using UriBuilder
. So doing this :
webclient.get().uri("/api/person/{id}", "1234")...
will generate a metric with the expected uri template (eg : /api/person/{id}), but using uri builder like this :
webclient.get().uri(uriBuilder -> uriBuilder.path("/api/person/{id}").build("1234"))
will generate metrics using the substituted uri (eg : /api/person/1234).
This is annoying cause we can have lot of possible uris and we loose precious information (and I think the uri builder is the smartest way to forge uris).
Looking closer, it appears that there is no URI_TEMPLATE_ATTRIBUTE
attribute set when using UriBuilder
with WebClient
.
Digging deeper, I discovered that the current implementation does not take care about baseUri
set on the WebClient
. So doing this :
webClientBuilder().baseUri("https://foo.com/api").build().get().uri("/person/{id}", "1234")...
Will generate a metric using /person/{id}
instead of /api/person/{id}
.
I suggest to make few changes on UriBuilder
to be able to get access to the original uri template (add a getUriTemplate
method). This way we could adapt the DefaultWebClient
like this :
@Override
public RequestBodySpec uri(String uriTemplate, Object... uriVariables) {
UriBuilder uriBuilder = uriBuilderFactory.uriString(uriTemplate);
attribute(URI_TEMPLATE_ATTRIBUTE, uriBuilder.getUriTemplate());
return uri(uriBuilder.build(uriVariables));
}
@Override
public RequestBodySpec uri(String uriTemplate, Map<String, ?> uriVariables) {
UriBuilder uriBuilder = uriBuilderFactory.uriString(uriTemplate);
attribute(URI_TEMPLATE_ATTRIBUTE, uriBuilder.getUriTemplate());
return uri(uriBuilder.build(uriVariables));
}
@Override
public RequestBodySpec uri(Function<UriBuilder, URI> uriFunction) {
UriBuilder uriBuilder = uriBuilderFactory.builder();
RequestBodySpec uri = uri(uriFunction.apply(uriBuilder));
attribute(URI_TEMPLATE_ATTRIBUTE, uriBuilder.getUriTemplate());
return uri;
}
This solution seems very simple but I would like to know if you think this is a good approach and if it make sense for you ?
If you want I can make a pull request (around 10 lines of code).
Keep me in touch.