简体   繁体   中英

Measure Spring RestTemplate HTTP request time

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?

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>

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>

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

I had the same requirements. I want to know the server response time to gauge how long it takes the server to respond without any RestTemplate response processing. I added two interceptors to the HttpClientBuilder with a map so I could measure the time between the low level request and response.

HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

// Attach interceptors
ResponseTimeInterceptor interceptor = new ResponseTimeInterceptor();
httpClientBuilder.addInterceptorFirst( (HttpRequestInterceptor) interceptor );
httpClientBuilder.addInterceptorFirst( (HttpResponseInterceptor) interceptor );

// Use client with RestTemplate or on its own
HttpClient client = httpClientBuilder.build();

Here is the minimal dual-duty interceptor:

public class ResponseTimeInterceptor implements HttpRequestInterceptor, HttpResponseInterceptor {
    private final Map<HttpContext, Long> requestMap = new MaxSizeHashMap<>( 50 );

    @Override
    public void process( HttpRequest httpRequest, HttpContext httpContext ) throws HttpException, IOException {
        requestMap.put( httpContext, System.currentTimeMillis() );
    }

    @Override
    public void process( HttpResponse httpResponse, HttpContext httpContext ) throws HttpException, IOException {
        long startTime = requestMap.getOrDefault( httpContext, 0L );
        long diff = System.currentTimeMillis() - startTime;
        System.out.println( "Response time: " + diff + "ms" );
    }
}

After the response interceptor returns, the response data continues into the RestTemplate response handler.

Note: The MaxSizeHashMap is taken from https://stackoverflow.com/a/5601377 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM