Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for nested requests in MetricsClientHttpRequestInterceptor
Browse files Browse the repository at this point in the history
nosan committed Dec 26, 2019

Verified

This commit was signed with the committer’s verified signature.
davidwendt David Wendt
1 parent d64b719 commit b50d833
Showing 2 changed files with 70 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@

import java.io.IOException;
import java.net.URI;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@@ -30,6 +32,7 @@
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.CollectionUtils;
import org.springframework.web.util.UriTemplateHandler;

/**
@@ -41,7 +44,7 @@
*/
class MetricsClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

private static final ThreadLocal<String> urlTemplate = new NamedThreadLocal<>("Rest Template URL Template");
private static final ThreadLocal<Deque<String>> urlTemplate = new NamedThreadLocal<>("Rest Template URL Template");

private final MeterRegistry meterRegistry;

@@ -96,7 +99,9 @@ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttp
finally {
getTimeBuilder(request, response).register(this.meterRegistry).record(System.nanoTime() - startTime,
TimeUnit.NANOSECONDS);
urlTemplate.remove();
if (CollectionUtils.isEmpty(urlTemplate.get())) {
urlTemplate.remove();
}
}
}

@@ -105,13 +110,13 @@ UriTemplateHandler createUriTemplateHandler(UriTemplateHandler delegate) {

@Override
public URI expand(String url, Map<String, ?> arguments) {
urlTemplate.set(url);
addFirstUrl(url);
return delegate.expand(url, arguments);
}

@Override
public URI expand(String url, Object... arguments) {
urlTemplate.set(url);
addFirstUrl(url);
return delegate.expand(url, arguments);
}

@@ -120,8 +125,22 @@ public URI expand(String url, Object... arguments) {

private Timer.Builder getTimeBuilder(HttpRequest request, ClientHttpResponse response) {
return this.autoTimer.builder(this.metricName)
.tags(this.tagProvider.getTags(urlTemplate.get(), request, response))
.tags(this.tagProvider.getTags(removeFirstUrl(), request, response))
.description("Timer of RestTemplate operation");
}

private static void addFirstUrl(String url) {
Deque<String> templates = urlTemplate.get();
if (templates == null) {
templates = new LinkedList<>();
urlTemplate.set(templates);
}
templates.offerFirst(url);
}

private static String removeFirstUrl() {
Deque<String> templates = urlTemplate.get();
return (templates != null) ? templates.pollFirst() : null;
}

}
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

package org.springframework.boot.actuate.metrics.web.client;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

@@ -29,7 +30,11 @@

import org.springframework.boot.actuate.metrics.AutoTimer;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.test.web.client.match.MockRestRequestMatchers;
import org.springframework.test.web.client.response.MockRestResponseCreators;
@@ -107,4 +112,45 @@ void interceptRestTemplateWithUri() throws URISyntaxException {
this.mockServer.verify();
}

@Test
void interceptNestedRequest() {
this.mockServer.expect(MockRestRequestMatchers.requestTo("/test/123"))
.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(MockRestResponseCreators.withSuccess("OK", MediaType.APPLICATION_JSON));

RestTemplate nestedRestTemplate = new RestTemplate();
MockRestServiceServer nestedMockServer = MockRestServiceServer.createServer(nestedRestTemplate);
nestedMockServer.expect(MockRestRequestMatchers.requestTo("/nestedTest/124"))
.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(MockRestResponseCreators.withSuccess("OK", MediaType.APPLICATION_JSON));
this.customizer.customize(nestedRestTemplate);

TestInterceptor testInterceptor = new TestInterceptor(nestedRestTemplate);
this.restTemplate.getInterceptors().add(testInterceptor);

this.restTemplate.getForObject("/test/{id}", String.class, 123);
this.registry.get("http.client.requests").tags("uri", "/test/{id}").timer();
this.registry.get("http.client.requests").tags("uri", "/nestedTest/{nestedId}").timer();

this.mockServer.verify();
nestedMockServer.verify();
}

private static final class TestInterceptor implements ClientHttpRequestInterceptor {

private final RestTemplate restTemplate;

private TestInterceptor(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
this.restTemplate.getForObject("/nestedTest/{nestedId}", String.class, 124);
return execution.execute(request, body);
}

}

}

0 comments on commit b50d833

Please sign in to comment.