|
|
|
|
@ -19,6 +19,7 @@ package org.springframework.web.client;
@@ -19,6 +19,7 @@ package org.springframework.web.client;
|
|
|
|
|
import java.io.ByteArrayInputStream; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.net.URI; |
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.UUID; |
|
|
|
|
|
|
|
|
|
@ -40,6 +41,7 @@ import org.springframework.http.client.observation.ClientRequestObservationConte
@@ -40,6 +41,7 @@ import org.springframework.http.client.observation.ClientRequestObservationConte
|
|
|
|
|
import org.springframework.http.client.observation.ClientRequestObservationConvention; |
|
|
|
|
import org.springframework.http.client.observation.DefaultClientRequestObservationConvention; |
|
|
|
|
import org.springframework.http.converter.HttpMessageConverter; |
|
|
|
|
import org.springframework.util.StreamUtils; |
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
|
|
|
|
@ -84,7 +86,7 @@ class RestClientObservationTests {
@@ -84,7 +86,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeVarArgsAddsUriTemplateAsKeyValue() throws Exception { |
|
|
|
|
void shouldContributeTemplateWhenUriVariables() throws Exception { |
|
|
|
|
mockSentRequest(GET, "https://example.com/hotels/42/bookings/21"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
|
|
|
|
|
@ -95,7 +97,7 @@ class RestClientObservationTests {
@@ -95,7 +97,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeArgsMapAddsUriTemplateAsKeyValue() throws Exception { |
|
|
|
|
void shouldContributeTemplateWhenMap() throws Exception { |
|
|
|
|
mockSentRequest(GET, "https://example.com/hotels/42/bookings/21"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
|
|
|
|
|
@ -107,9 +109,8 @@ class RestClientObservationTests {
@@ -107,9 +109,8 @@ class RestClientObservationTests {
|
|
|
|
|
assertThatHttpObservation().hasLowCardinalityKeyValue("uri", "/hotels/{hotel}/bookings/{booking}"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeAddsSuccessAsOutcome() throws Exception { |
|
|
|
|
void shouldContributeSuccessOutcome() throws Exception { |
|
|
|
|
mockSentRequest(GET, "https://example.org"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
mockResponseBody("Hello World", MediaType.TEXT_PLAIN); |
|
|
|
|
@ -120,7 +121,7 @@ class RestClientObservationTests {
@@ -120,7 +121,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeAddsServerErrorAsOutcome() throws Exception { |
|
|
|
|
void shouldContributeServerErrorOutcome() throws Exception { |
|
|
|
|
String url = "https://example.org"; |
|
|
|
|
mockSentRequest(GET, url); |
|
|
|
|
mockResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
@ -134,7 +135,7 @@ class RestClientObservationTests {
@@ -134,7 +135,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeAddsExceptionAsKeyValue() throws Exception { |
|
|
|
|
void shouldContributeDecodingError() throws Exception { |
|
|
|
|
mockSentRequest(POST, "https://example.org/resource"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
|
|
|
|
|
@ -150,7 +151,7 @@ class RestClientObservationTests {
@@ -150,7 +151,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeWithIoExceptionAddsUnknownOutcome() throws Exception { |
|
|
|
|
void shouldContributeIOError() throws Exception { |
|
|
|
|
String url = "https://example.org/resource"; |
|
|
|
|
mockSentRequest(GET, url); |
|
|
|
|
given(request.execute()).willThrow(new IOException("Socket failure")); |
|
|
|
|
@ -161,7 +162,7 @@ class RestClientObservationTests {
@@ -161,7 +162,7 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void executeWithCustomConventionUsesCustomObservationName() throws Exception { |
|
|
|
|
void shouldUseCustomConvention() throws Exception { |
|
|
|
|
ClientRequestObservationConvention observationConvention = |
|
|
|
|
new DefaultClientRequestObservationConvention("custom.requests"); |
|
|
|
|
RestClient restClient = this.client.mutate().observationConvention(observationConvention).build(); |
|
|
|
|
@ -174,6 +175,56 @@ class RestClientObservationTests {
@@ -174,6 +175,56 @@ class RestClientObservationTests {
|
|
|
|
|
.hasObservationWithNameEqualTo("custom.requests"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void shouldAddClientDecodingErrorAsException() throws Exception { |
|
|
|
|
String url = "https://example.org"; |
|
|
|
|
mockSentRequest(GET, url); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
mockResponseBody("INVALID", MediaType.APPLICATION_JSON); |
|
|
|
|
|
|
|
|
|
assertThatExceptionOfType(RestClientException.class).isThrownBy(() -> |
|
|
|
|
client.get().uri(url).retrieve().body(User.class)); |
|
|
|
|
|
|
|
|
|
assertThatHttpObservation().hasLowCardinalityKeyValue("exception", "RestClientException"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void shouldAddUnknownContentTypeErrorAsException() throws Exception { |
|
|
|
|
String url = "https://example.org"; |
|
|
|
|
mockSentRequest(GET, url); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
mockResponseBody("Not Found", MediaType.TEXT_HTML); |
|
|
|
|
|
|
|
|
|
assertThatExceptionOfType(RestClientException.class).isThrownBy(() -> |
|
|
|
|
client.get().uri(url).retrieve().body(User.class)); |
|
|
|
|
|
|
|
|
|
assertThatHttpObservation().hasLowCardinalityKeyValue("exception", "UnknownContentTypeException"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void registerObservationWhenReadingBody() throws Exception { |
|
|
|
|
mockSentRequest(GET, "https://example.org"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
mockResponseBody("Hello World", MediaType.TEXT_PLAIN); |
|
|
|
|
|
|
|
|
|
client.get().uri("https://example.org").exchange((request, response) -> response.bodyTo(String.class)); |
|
|
|
|
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SUCCESS"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void registerObservationWhenReadingStream() throws Exception { |
|
|
|
|
mockSentRequest(GET, "https://example.org"); |
|
|
|
|
mockResponseStatus(HttpStatus.OK); |
|
|
|
|
mockResponseBody("Hello World", MediaType.TEXT_PLAIN); |
|
|
|
|
|
|
|
|
|
client.get().uri("https://example.org").exchange((request, response) -> { |
|
|
|
|
String result = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8); |
|
|
|
|
response.close(); |
|
|
|
|
return result; |
|
|
|
|
}, false); |
|
|
|
|
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SUCCESS"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void mockSentRequest(HttpMethod method, String uri) throws Exception { |
|
|
|
|
mockSentRequest(method, uri, new HttpHeaders()); |
|
|
|
|
@ -220,4 +271,8 @@ class RestClientObservationTests {
@@ -220,4 +271,8 @@ class RestClientObservationTests {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
record User(String name) { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|