Measure Spring RestTemplate HTTP request time

13,926

Solution 1

You can use AOP and the built in PerformanceMonitorInterceptor of Spring. You need to correctly define which methods of which calss you want to intercept then you can measure. You can configure it something like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans      
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
        http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    <bean id="springMonitoredService"
        class="com.myorg.service.springmon.MyServiceSpringImpl"/>


    <bean id="springMonitoringAspectInterceptor"        
class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor">
        <property name="loggerName"     
                value="com.myorg.SPRING_MONITOR"/>      
    </bean>


    <aop:config>
            <aop:pointcut id="springMonitoringPointcut"
                   expression="execution(* java.net.HttpURLConnection.connect(..))"/>




                <aop:advisor pointcut-ref="springMonitoringPointcut" 
            advice-ref="springMonitoringAspectInterceptor"/>      
    </aop:config>

</beans>

Solution 2

You can use Stopwatch to do that.

public class PerfRequestSyncInterceptor implements ClientHttpRequestInterceptor {

    private final static Logger LOG = LoggerFactory.getLogger(PerfRequestSyncInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest hr, byte[] bytes, ClientHttpRequestExecution chre) throws IOException {
        StopWatch stopwatch = StopWatch.createStarted();
        ClientHttpResponse response = chre.execute(hr, bytes);
        stopwatch.stop();

        LOG.info("method=" + hr.getMethod() + ", uri="+hr.getURI() + ", response_time=" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + ", response_code=" + response.getStatusCode().value());

        return response;
    }
}

And in the class where restTemplate is instanced

private final List<ClientHttpRequestInterceptor> requestInterceptors = new ArrayList<>();
requestInterceptors.add(new PerfRequestSyncInterceptor());
this.restTemplate.setInterceptors(requestInterceptors);

Add the Stopwatch dependency for maven:

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>r05</version>
</dependency>
Share:
13,926
whlk
Author by

whlk

Apparently, this user prefers to keep an air of mystery about them.

Updated on July 20, 2022

Comments

  • whlk
    whlk almost 2 years

    I want to measure the time of the HTTP GET request of a RestTemplate.getForObject call without the the time needed for parsing the response. So just the time the remote HTTP call needs. I already tried setting a ClientHttpRequestInterceptor but I dont think this is the right way to do it as the time seems to be wrong:

    public class PerfRequestSyncInterceptor implements ClientHttpRequestInterceptor {
    private Logger log = Logger.getLogger(this.getClass());
    
    @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
    
        long start = System.nanoTime();
        ClientHttpResponse resp = execution.execute(request, body);
    
        log.debug("remote request time: "
                + ((System.nanoTime() - start) * Math.pow(10, -9)));
        return resp;
      }
    }
    


    Call:

    RestTemplate rest = new RestTemplate();
    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
    interceptors.add(new PerfRequestSyncInterceptor());
    rest.setInterceptors(interceptors);
    
    Response inob = rest.getForObject(xmlURL, Response.class);
    

    How can I measure the time of a RestTemplate HTTP request?

  • whlk
    whlk over 11 years
    And which method should I configure for measurement?
  • Peter Szanto
    Peter Szanto over 11 years
    Internally RestTemplate uses java.net.HttpURLConnection you will need to measure the connect() method. Additionally you can try the getDoOutput() method too
  • whlk
    whlk over 11 years
    May I ask you to update your answer to point to this methods?
  • Asif
    Asif over 6 years
    This doesn't work for me. But if I change the expression to a public method of my class that uses rest template, it works. Is my version of template not using HttpURLConnection?
  • J.R.
    J.R. almost 6 years
    Thanks for this answer. I tried it but it did not what was expected. Maybe it's due to changes in Spring (I did not investigate). Just want to put it here to warn others to not rely on the results when done like that. I issued a request to a server in debug mode, so I had to press 2 times resume on the server but the interceptor measured 1ms as time - what is simply impossible.
  • Sahil333
    Sahil333 about 3 years
    The same problem is faced by me dictated by @J.R. Do not use this