Start RestTemplate observation wtih available request
Prior to this commit, the `RestTemplate` `ClientHttpObservation` would be started before the request object is available. While this would also measure the connection estalishment for some HTTP client libraries, this arrangement is incompatible with a tracing approach where the request must be available to propagate information through the request headers. This commit ensures that the observation only starts when the request is available. Fixes gh-29234
This commit is contained in:
@@ -36,8 +36,13 @@ public class ClientHttpObservationContext extends RequestReplySenderContext<Clie
|
||||
@Nullable
|
||||
private String uriTemplate;
|
||||
|
||||
public ClientHttpObservationContext() {
|
||||
/**
|
||||
* Create an observation context for {@link ClientHttpRequest} observations.
|
||||
* @param request the HTTP client request
|
||||
*/
|
||||
public ClientHttpObservationContext(ClientHttpRequest request) {
|
||||
super(ClientHttpObservationContext::setRequestHeader);
|
||||
this.setCarrier(request);
|
||||
}
|
||||
|
||||
private static void setRequestHeader(@Nullable ClientHttpRequest request, String name, String value) {
|
||||
|
||||
@@ -839,14 +839,20 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
|
||||
Assert.notNull(url, "url is required");
|
||||
Assert.notNull(method, "HttpMethod is required");
|
||||
ClientHttpObservationContext observationContext = new ClientHttpObservationContext();
|
||||
ClientHttpRequest request;
|
||||
try {
|
||||
request = createRequest(url, method);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ResourceAccessException exception = createResourceAccessException(url, method, ex);
|
||||
throw exception;
|
||||
}
|
||||
ClientHttpObservationContext observationContext = new ClientHttpObservationContext(request);
|
||||
observationContext.setUriTemplate(uriTemplate);
|
||||
Observation observation = ClientHttpObservation.HTTP_REQUEST.observation(this.observationConvention,
|
||||
DEFAULT_OBSERVATION_CONVENTION, observationContext, this.observationRegistry).start();
|
||||
observationContext.setUriTemplate(uriTemplate);
|
||||
ClientHttpResponse response = null;
|
||||
try {
|
||||
ClientHttpRequest request = createRequest(url, method);
|
||||
observationContext.setCarrier(request);
|
||||
if (requestCallback != null) {
|
||||
requestCallback.doWithRequest(request);
|
||||
}
|
||||
@@ -856,11 +862,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
return (responseExtractor != null ? responseExtractor.extractData(response) : null);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
String resource = url.toString();
|
||||
String query = url.getRawQuery();
|
||||
resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
|
||||
ResourceAccessException exception = new ResourceAccessException("I/O error on " + method.name() +
|
||||
" request for \"" + resource + "\": " + ex.getMessage(), ex);
|
||||
ResourceAccessException exception = createResourceAccessException(url, method, ex);
|
||||
observation.error(exception);
|
||||
throw exception;
|
||||
}
|
||||
@@ -876,6 +878,15 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
}
|
||||
}
|
||||
|
||||
protected static ResourceAccessException createResourceAccessException(URI url, HttpMethod method, IOException ex) {
|
||||
String resource = url.toString();
|
||||
String query = url.getRawQuery();
|
||||
resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
|
||||
ResourceAccessException exception = new ResourceAccessException("I/O error on " + method.name() +
|
||||
" request for \"" + resource + "\": " + ex.getMessage(), ex);
|
||||
return exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given response, performing appropriate logging and
|
||||
* invoking the {@link ResponseErrorHandler} if necessary.
|
||||
|
||||
Reference in New Issue
Block a user