6

I'm trying to monitor rest template metrics for my spring boot application via micrometer & prometheus. When I use Resttemplate built with ResttemplateBuilder and use to call for another api, it did get the expected http.client.requests metrics. But for AsyncResttemplate when I create with AsyncResttemplate and use it to call for another api, It didn't provide any http.client.requests metrics.

This is the code when i create the AsyncResttemplate bean

    @Bean
    public AsyncRestTemplate asyncRestTemplate(){
        return new AsyncRestTemplate();
    }

This is the code when I call another api with async

    public ListenableFuture async() {
        ListenableFuture<ResponseEntity<AccountResponse>> accountResponseList = asyncRestTemplate.exchange(accountUrl, HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), AccountResponse.class);
        accountResponseList.addCallback(new ListenableFutureCallback<ResponseEntity<AccountResponse>>() {
            @Override
            public void onSuccess(ResponseEntity<AccountResponse> accountResponseResponseEntity) {
                System.out.println("Success");
            }

            @Override
            public void onFailure(Throwable throwable) {
                System.out.println("Failure");
            }
        });
        return accountResponseList;
    }

And these are the relevant dependencies imported in pom.xml

<dependency>
      <groupId>io.micrometer</groupId>
      <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

This is what i expect to get from micrometer-prometheus metrics

# HELP http_client_requests_seconds Timer of RestTemplate operation
# TYPE http_client_requests_seconds summary
http_client_requests_seconds_count{application="${spring.application.name}",clientName="localhost",method="GET",status="200",uri="/getAllAccount",} 1.0
http_client_requests_seconds_sum{application="${spring.application.name}",clientName="localhost",method="GET",status="200",uri="/getAllAccount",} 0.0242929
# HELP http_client_requests_seconds_max Timer of RestTemplate operation
# TYPE http_client_requests_seconds_max gauge
http_client_requests_seconds_max{application="${spring.application.name}",clientName="localhost",method="GET",status="200",uri="/getAllAccount",} 0.0242929

The metrics above are from ResttemplateBuilder, is there a way that these can be obtained for AsyncRestTemplate too?

Update: From M. Deinum's advice I change the bean to

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder){
        return builder.setConnectTimeout(Duration.ofSeconds(500)).build();
    }

    @Bean
    public AsyncRestTemplate asyncRestTemplate(RestTemplate restTemplate){
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        SimpleAsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();
        asyncTaskExecutor.setConcurrencyLimit(10);
        requestFactory.setTaskExecutor(asyncTaskExecutor);
        return new AsyncRestTemplate(requestFactory, restTemplate);
    }

But still not get any http.client.requests from async call

PD1743
  • 61
  • 1
  • 3
  • Use the `RestTemplateBuilder` to create a `RestTemplate` and use the to construct an `AsyncRestTemplate` (the `AsyncRestTemplate` is just a wrapper for a `RestTemplate`). – M. Deinum Oct 30 '19 at 08:33

1 Answers1

3

Something like this should do.

@Bean
public AsyncRestTemplate asyncRestTemplate(RestTemplateBuilder builder){
  RestTemplate rest = builder.build();
  AsyncClientHttpRequestFactory requestFactory = (AsyncClientHttpRequestFactory) rest.getRequestFactory();
  return new AsyncRestTemplate(requestFactory, rest);
}

This will reuse the existing configuration. The AsyncRestTemplate is just a wrapper around the RestTemplate combining it with a `TaskExecutor.

NOTE: Be aware that the AsyncRestTemplate as of Spring 5 is deprecated and will likely be removed somewhere in the near future!.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • I try it and got this exception `Caused by: java.lang.ClassCastException: org.springframework.http.client.InterceptingClientHttpRequestFactory cannot be cast to org.springframework.http.client.AsyncClientHttpRequestFactory` – PD1743 Oct 30 '19 at 09:24
  • Darn, didn't take the wrapping into account. Use `new SimpleClientHttpRequestFactory()` instead of obtaining it from the `RestTemplate`. Unless you already configured another `ClientHttpRequestFactory` yourself, then reuse and inject that one. – M. Deinum Oct 30 '19 at 09:31
  • Tried this configuration and able to make the call, but I still couldn't get the http.client.requests metrics. – PD1743 Oct 30 '19 at 10:39
  • Then did you really use the builder to work with the `RestTEmplate` or did some additional configuration? Define it like a bean perhaps? – M. Deinum Oct 30 '19 at 10:58
  • I've already post the thing that I changed and still not get any metrics from http.client.requests – PD1743 Oct 31 '19 at 03:51