I am using Spring boot 2.2.4 with RestTemplate with templatized URI, please see below
private QueryResponse<MetricData<VectorValue>> executeQueryInternal(
String tenant,
String pattern,
Optional<ZonedDateTime> dateTime) {
String url = host + INSTANT_QUERY_END_POINT + "?query={pattern}&timeout={timeout}";
List<Object> parameters = new LinkedList<>();
parameters.add(pattern);
parameters.add(timeoutDuration);
if (dateTime.isPresent()) {
parameters.add(dateTime.get().toEpochSecond());
url += "&time={dateTime}";
log.debug("Executing query: {} for pattern: {}, dateTime: {}", url, pattern, dateTime.get().toEpochSecond());
} else {
log.debug("Executing query: {} for pattern: {}", url, pattern);
}
return restTemplate.exchange(url,
HttpMethod.GET,
requestHeaders(tenant),
new ParameterizedTypeReference<QueryResponse<MetricData<VectorValue>>>() {},
parameters.toArray(new Object[0]))
.getBody();
}
But my micrometer Prometheus Metrics is capturing the full URL, not the template URL causing a cardinality explosion
http_client_requests_seconds_count{clientName="prom.co",method="GET",outcome="SUCCESS",status="200",uri="/api/v1/query?query=sum%20by%20%28topic%2C%20namespace%29%20%28kafka_topic_partitions%29&timeout=30s",} 2.0
http_client_requests_seconds_sum{clientName="prom.co",method="GET",outcome="SUCCESS",status="200",uri="/api/v1/query?query=sum%20by%20%28topic%2C%20namespace%29%20%28kafka_topic_partitions%29&timeout=30s",} 0.11827849
The micrometer team advised to provide a custom@Bean RestTemplateExchangeTagsProvider
and also advised to file an issue with SpringBoot.
Comment From: wilkinsona
If you are using the auto-configured RestTemplate, its metrics should automatically use the URI template when creating the URI tag. Unfortunately, it isn't possible to say why that isn't happening in your case as you haven't shown how the template is being created and configured.
If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.
Comment From: manoja1
Please find below the code where we are creating the RESTTemplate.
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
RestTemplate restTemplate = builder.build();
// See https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#web-uri-encoding
// The default encoding is EncodingMode.URI_COMPONENT for historical reason which doesn't take
// care of reserved characters like "," ";", "+" in the value
// Switch to the safest approach EncodingMode.TEMPLATE_AND_VALUES
DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
uriFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);
restTemplate.setUriTemplateHandler(uriFactory);
return restTemplate;
}
The restTemplate
is used as constructed in executeQueryInternal
method I shared before. We had to switch our default encoding method for the reasons stated in code comments. Is that causing the behavior to change?
Let me know if I need to share a sample project putting these 2 methods together.
Comment From: wilkinsona
Yes, that's what's causing the behaviour to change. The rest template metrics support uses a UriTemplateHandler
to capture the URI template and use it when creating the uri tag. You have overridden this handler so the ability to use the URI template is lost.
I would recommend using a RestTemplateCustomizer
bean to configure the UriTemplateHandler
. If ordered with anything other than lowest precedence, it will then be in place before the metrics-related handler is installed and it will delegate to your custom handler.