diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java index 19ff4a0435..16ea2c877c 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java @@ -228,13 +228,13 @@ final class DefaultRestClient implements RestClient { } throw unknownContentTypeException; } - catch (UncheckedIOException | IOException | HttpMessageNotReadableException ex) { + catch (UncheckedIOException | IOException | HttpMessageNotReadableException exc) { Throwable cause; - if (ex instanceof UncheckedIOException uncheckedIOException) { + if (exc instanceof UncheckedIOException uncheckedIOException) { cause = uncheckedIOException.getCause(); } else { - cause = ex; + cause = exc; } RestClientException restClientException = new RestClientException("Error while extracting response for type [" + ResolvableType.forType(bodyType) + "] and content type [" + contentType + "]", cause); @@ -243,6 +243,12 @@ final class DefaultRestClient implements RestClient { } throw restClientException; } + catch (RestClientException restClientException) { + if (observation != null) { + observation.error(restClientException); + } + throw restClientException; + } finally { if (observation != null) { observation.stop(); diff --git a/spring-web/src/test/java/org/springframework/web/client/RestClientObservationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestClientObservationTests.java index ed8d7fce50..62cbca8598 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestClientObservationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestClientObservationTests.java @@ -66,8 +66,6 @@ class RestClientObservationTests { private final ClientHttpResponse response = mock(); - private final ResponseErrorHandler errorHandler = mock(); - private final HttpMessageConverter converter = mock(); private RestClient client; @@ -79,7 +77,6 @@ class RestClientObservationTests { this.client = RestClient.builder() .messageConverters(converters -> converters.add(0, this.converter)) .requestFactory(this.requestFactory) - .defaultStatusHandler(this.errorHandler) .observationRegistry(this.observationRegistry) .build(); this.observationRegistry.observationConfig().observationHandler(new ContextAssertionObservationHandler()); @@ -122,6 +119,10 @@ class RestClientObservationTests { @Test void shouldContributeServerErrorOutcome() throws Exception { + ResponseErrorHandler errorHandler = mock(); + given(errorHandler.hasError(response)).willReturn(true); + this.client = this.client.mutate().defaultStatusHandler(errorHandler).build(); + String url = "https://example.org"; mockSentRequest(GET, url); mockResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR); @@ -201,6 +202,19 @@ class RestClientObservationTests { assertThatHttpObservation().hasLowCardinalityKeyValue("exception", "UnknownContentTypeException"); } + @Test + void shouldAddRestClientExceptionAsError() throws Exception { + String url = "https://example.org"; + mockSentRequest(GET, url); + mockResponseStatus(HttpStatus.NOT_FOUND); + mockResponseBody("Not Found", MediaType.TEXT_HTML); + + assertThatExceptionOfType(RestClientException.class).isThrownBy(() -> + client.get().uri(url).retrieve().toEntity(String.class)); + + assertThatHttpObservation().hasLowCardinalityKeyValue("exception", "NotFound"); + } + @Test void registerObservationWhenReadingBody() throws Exception { mockSentRequest(GET, "https://example.org"); @@ -239,7 +253,6 @@ class RestClientObservationTests { private void mockResponseStatus(HttpStatus responseStatus) throws Exception { given(request.execute()).willReturn(response); - given(errorHandler.hasError(response)).willReturn(responseStatus.isError()); given(response.getStatusCode()).willReturn(responseStatus); given(response.getStatusText()).willReturn(responseStatus.getReasonPhrase()); }