From cb17075e8a083aa5575a11eaa879c4e2a8ca915f Mon Sep 17 00:00:00 2001 From: Soeren Unruh Date: Wed, 31 Jul 2024 13:14:37 +0200 Subject: [PATCH] Client observations creating too many uri tag values; fixes gh-4290 --- .../http/RestTemplateEurekaHttpClient.java | 86 ++++++++----------- .../http/WebClientEurekaHttpClient.java | 50 +++++------ .../http/AbstractEurekaHttpClientTests.java | 63 +++++++++++++- .../RestTemplateEurekaHttpClientTests.java | 1 + .../http/WebClientEurekaHttpClientTests.java | 3 +- 5 files changed, 126 insertions(+), 77 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java index 7677f079d..7dbab1108 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java @@ -16,7 +16,6 @@ package org.springframework.cloud.netflix.eureka.http; -import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -38,14 +37,15 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.util.ObjectUtils; import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse; /** * @author Daniel Lavoie * @author Václav Plic + * @author Soeren Unruh */ public class RestTemplateEurekaHttpClient implements EurekaHttpClient { @@ -71,29 +71,24 @@ public RestTemplate getRestTemplate() { @Override public EurekaHttpResponse register(InstanceInfo info) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl) - .path("apps/{appName}") - .buildAndExpand(info.getAppName()) - .toUri(); + String urlPath = serviceUrl + "apps/{appName}"; HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip"); headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.POST, new HttpEntity<>(info, headers), - Void.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.POST, new HttpEntity<>(info, headers), + Void.class, info.getAppName()); return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build(); } @Override public EurekaHttpResponse cancel(String appName, String id) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl) - .path("apps/{appName}/{id}") - .buildAndExpand(appName, id) - .toUri(); + String urlPath = serviceUrl + "apps/{appName}/{id}"; - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.DELETE, null, Void.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class, appName, + id); return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build(); } @@ -101,18 +96,14 @@ public EurekaHttpResponse cancel(String appName, String id) { @Override public EurekaHttpResponse sendHeartBeat(String appName, String id, InstanceInfo info, InstanceStatus overriddenStatus) { - UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl) - .path("apps/{appName}/{id}") - .queryParam("status", info.getStatus().toString()) - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()); + String urlPath = serviceUrl + "apps/{appName}/{id}?status={status}&lastDirtyTimestamp={lastDirtyTimestamp}"; if (overriddenStatus != null) { - uriBuilder = uriBuilder.queryParam("overriddenstatus", overriddenStatus.name()); + urlPath = urlPath + "&overriddenstatus={overriddenStatus}"; } - URI uri = uriBuilder.buildAndExpand(appName, id).toUri(); - - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.PUT, null, InstanceInfo.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.PUT, null, InstanceInfo.class, + appName, id, info.getStatus(), info.getLastDirtyTimestamp(), overriddenStatus); EurekaHttpResponseBuilder eurekaResponseBuilder = anEurekaHttpResponse( response.getStatusCode().value(), InstanceInfo.class) @@ -128,27 +119,21 @@ public EurekaHttpResponse sendHeartBeat(String appName, String id, @Override public EurekaHttpResponse statusUpdate(String appName, String id, InstanceStatus newStatus, InstanceInfo info) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl) - .path("apps/{appName}/{id}/status") - .queryParam("value", newStatus.name()) - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()) - .buildAndExpand(appName, id) - .toUri(); + String urlPath = serviceUrl + + "apps/{appName}/{id}/status?value={value}&lastDirtyTimestamp={lastDirtyTimestamp}"; - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.PUT, null, Void.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.PUT, null, Void.class, appName, id, + newStatus, info.getLastDirtyTimestamp()); return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build(); } @Override public EurekaHttpResponse deleteStatusOverride(String appName, String id, InstanceInfo info) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl) - .path("apps/{appName}/{id}/status") - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()) - .buildAndExpand(appName, id) - .toUri(); + String urlPath = serviceUrl + "apps/{appName}/{id}/status?lastDirtyTimestamp={lastDirtyTimestamp}"; - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.DELETE, null, Void.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class, appName, id, + info.getLastDirtyTimestamp()); return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build(); } @@ -158,17 +143,16 @@ public EurekaHttpResponse getApplications(String... regions) { return getApplicationsInternal("apps/", regions); } - private EurekaHttpResponse getApplicationsInternal(String urlPath, String[] regions) { - UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl).path(urlPath); + private EurekaHttpResponse getApplicationsInternal(String urlPath, String[] regions, + Object... uriVariables) { + String url = serviceUrl + urlPath; if (regions != null && regions.length > 0) { - uriBuilder = uriBuilder.queryParam("regions", StringUtil.join(regions)); + url = url + (urlPath.contains("?") ? "&" : "?") + "regions={regions}"; } - URI uri = uriBuilder.build().toUri(); - - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, null, - EurekaApplications.class); + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, null, + EurekaApplications.class, ObjectUtils.addObjectToArray(uriVariables, StringUtil.join(regions))); return anEurekaHttpResponse(response.getStatusCode().value(), response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody() @@ -184,19 +168,20 @@ public EurekaHttpResponse getDelta(String... regions) { @Override public EurekaHttpResponse getVip(String vipAddress, String... regions) { - return getApplicationsInternal("vips/" + vipAddress, regions); + return getApplicationsInternal("vips/{vipAddress}", regions, vipAddress); } @Override public EurekaHttpResponse getSecureVip(String secureVipAddress, String... regions) { - return getApplicationsInternal("svips/" + secureVipAddress, regions); + return getApplicationsInternal("svips/{secureVipAddress}", regions, secureVipAddress); } @Override public EurekaHttpResponse getApplication(String appName) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl).path("apps/{appName}").buildAndExpand(appName).toUri(); + String urlPath = serviceUrl + "apps/{appName}"; - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, null, Application.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.GET, null, Application.class, + appName); Application application = response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody() ? response.getBody() : null; @@ -206,18 +191,19 @@ public EurekaHttpResponse getApplication(String appName) { @Override public EurekaHttpResponse getInstance(String appName, String id) { - return getInstanceInternal("apps", appName, id); + return getInstanceInternal("apps/{appName}/{id}", appName, id); } @Override public EurekaHttpResponse getInstance(String id) { - return getInstanceInternal("instances", id); + return getInstanceInternal("instances/{id}", id); } - private EurekaHttpResponse getInstanceInternal(String... pathSegments) { - URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl).pathSegment(pathSegments).build().toUri(); + private EurekaHttpResponse getInstanceInternal(String urlPath, Object... uriVariables) { + urlPath = serviceUrl + urlPath; - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, null, InstanceInfo.class); + ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.GET, null, InstanceInfo.class, + uriVariables); return anEurekaHttpResponse(response.getStatusCode().value(), response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody() ? response.getBody() diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java index 41a886115..e01799678 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java @@ -17,7 +17,6 @@ package org.springframework.cloud.netflix.eureka.http; import java.util.Map; -import java.util.Optional; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.InstanceStatus; @@ -34,6 +33,7 @@ import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.util.ObjectUtils; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; @@ -44,6 +44,7 @@ * @author Daniel Lavoie * @author Haytham Mohamed * @author Václav Plic + * @author Soeren Unruh */ public class WebClientEurekaHttpClient implements EurekaHttpClient { @@ -56,7 +57,7 @@ public WebClientEurekaHttpClient(WebClient webClient) { @Override public EurekaHttpResponse register(InstanceInfo info) { return webClient.post() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}").build(info.getAppName())) + .uri("apps/{appName}", info.getAppName()) .body(BodyInserters.fromValue(info)) .header(HttpHeaders.ACCEPT_ENCODING, "gzip") .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) @@ -70,7 +71,7 @@ public EurekaHttpResponse register(InstanceInfo info) { @Override public EurekaHttpResponse cancel(String appName, String id) { return webClient.delete() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}").build(appName, id)) + .uri("apps/{appName}/{id}", appName, id) .retrieve() .onStatus(HttpStatusCode::isError, this::ignoreError) .toBodilessEntity() @@ -83,10 +84,8 @@ public EurekaHttpResponse sendHeartBeat(String appName, String id, InstanceStatus overriddenStatus) { ResponseEntity response = webClient.put() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}") - .queryParam("status", info.getStatus().toString()) - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()) - .build(appName, id)) + .uri("apps/{appName}/{id}?status={status}&lastDirtyTimestamp={lastDirtyTimestamp}", appName, id, + info.getStatus(), info.getLastDirtyTimestamp()) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .retrieve() @@ -112,10 +111,8 @@ public EurekaHttpResponse sendHeartBeat(String appName, String id, public EurekaHttpResponse statusUpdate(String appName, String id, InstanceStatus newStatus, InstanceInfo info) { return webClient.put() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status") - .queryParam("value", newStatus.name()) - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()) - .build(appName, id)) + .uri("apps/{appName}/{id}/status?value={value}&lastDirtyTimestamp={lastDirtyTimestamp}", appName, id, + newStatus, info.getLastDirtyTimestamp()) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatusCode::isError, this::ignoreError) @@ -127,9 +124,8 @@ public EurekaHttpResponse statusUpdate(String appName, String id, Instance @Override public EurekaHttpResponse deleteStatusOverride(String appName, String id, InstanceInfo info) { return webClient.delete() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status") - .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()) - .build(appName, id)) + .uri("apps/{appName}/{id}/status?lastDirtyTimestamp={lastDirtyTimestamp}", appName, id, + info.getLastDirtyTimestamp()) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatusCode::isError, this::ignoreError) @@ -143,12 +139,16 @@ public EurekaHttpResponse getApplications(String... regions) { return getApplicationsInternal("apps/", regions); } - private EurekaHttpResponse getApplicationsInternal(String urlPath, String[] regions) { - Optional regionsParam = (regions != null && regions.length > 0) ? Optional.of(StringUtil.join(regions)) - : Optional.empty(); + private EurekaHttpResponse getApplicationsInternal(String urlPath, String[] regions, + Object... uriVariables) { + String url = urlPath; + + if (regions != null && regions.length > 0) { + url = url + (urlPath.contains("?") ? "&" : "?") + "regions={regions}"; + } ResponseEntity response = webClient.get() - .uri(uriBuilder -> uriBuilder.path(urlPath).queryParamIfPresent("regions", regionsParam).build()) + .uri(url, ObjectUtils.addObjectToArray(uriVariables, StringUtil.join(regions))) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .retrieve() @@ -172,19 +172,19 @@ public EurekaHttpResponse getDelta(String... regions) { @Override public EurekaHttpResponse getVip(String vipAddress, String... regions) { - return getApplicationsInternal("vips/" + vipAddress, regions); + return getApplicationsInternal("vips/{vipAddress}", regions, vipAddress); } @Override public EurekaHttpResponse getSecureVip(String secureVipAddress, String... regions) { - return getApplicationsInternal("svips/" + secureVipAddress, regions); + return getApplicationsInternal("svips/{secureVipAddress}", regions, secureVipAddress); } @Override public EurekaHttpResponse getApplication(String appName) { ResponseEntity response = webClient.get() - .uri(uriBuilder -> uriBuilder.path("apps/{appName}").build(appName)) + .uri("apps/{appName}", appName) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatusCode::isError, this::ignoreError) @@ -201,17 +201,17 @@ public EurekaHttpResponse getApplication(String appName) { @Override public EurekaHttpResponse getInstance(String appName, String id) { - return getInstanceInternal("apps", appName, id); + return getInstanceInternal("apps/{appName}/{id}", appName, id); } @Override public EurekaHttpResponse getInstance(String id) { - return getInstanceInternal("instances", id); + return getInstanceInternal("instances/{id}", id); } - private EurekaHttpResponse getInstanceInternal(String... pathSegments) { + private EurekaHttpResponse getInstanceInternal(String urlPath, Object... uriVariables) { ResponseEntity response = webClient.get() - .uri(uriBuilder -> uriBuilder.pathSegment(pathSegments).build()) + .uri(urlPath, uriVariables) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatusCode::isError, this::ignoreError) diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/AbstractEurekaHttpClientTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/AbstractEurekaHttpClientTests.java index 804790c99..adfa3154c 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/AbstractEurekaHttpClientTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/AbstractEurekaHttpClientTests.java @@ -17,17 +17,30 @@ package org.springframework.cloud.netflix.eureka.http; import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.InstanceInfo.InstanceStatus; import com.netflix.discovery.shared.Applications; import com.netflix.discovery.shared.transport.EurekaHttpClient; import com.netflix.discovery.shared.transport.EurekaHttpResponse; + +import io.micrometer.observation.Observation; +import io.micrometer.observation.tck.ObservationContextAssert; +import io.micrometer.observation.tck.TestObservationRegistry; +import io.micrometer.observation.tck.TestObservationRegistryAssert; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.http.HttpStatus; +import org.springframework.http.client.observation.ClientHttpObservationDocumentation; import static org.assertj.core.api.Assertions.assertThat; +import java.util.Set; + +import org.apache.commons.lang3.ArrayUtils; +import org.assertj.core.api.InstanceOfAssertFactories; + /** * @author Haytham Mohamed * @author Václav Plic @@ -38,16 +51,22 @@ abstract class AbstractEurekaHttpClientTests { protected InstanceInfo info; + protected final TestObservationRegistry observationRegistry = TestObservationRegistry.create(); + abstract void setup(); @Test void testRegister() { assertThat(eurekaHttpClient.register(info).getStatusCode()).isEqualTo(HttpStatus.OK.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test"); } @Test void testCancel() { assertThat(eurekaHttpClient.cancel("test", "test").getStatusCode()).isEqualTo(HttpStatus.OK.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test"); } @ParameterizedTest @@ -56,18 +75,24 @@ void testSendHeartBeat(String instanceId) { EurekaHttpResponse response = eurekaHttpClient.sendHeartBeat("test", instanceId, info, null); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK.value()); assertThat(response.getEntity()).isNotNull(); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings(instanceId); } @Test void testSendHeartBeatFourOFour() { assertThat(eurekaHttpClient.sendHeartBeat("fourOFour", "test", info, null).getStatusCode()) .isEqualTo(HttpStatus.NOT_FOUND.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("fourOFour", "test"); } @Test void testSendHeartBeatFourOFourWithBody() { assertThat(eurekaHttpClient.sendHeartBeat("fourOFourWithBody", "test", info, null).getStatusCode()) .isEqualTo(HttpStatus.NOT_FOUND.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("fourOFourWithBody", "test"); } @ParameterizedTest @@ -76,12 +101,16 @@ void testStatusUpdate(String instanceId) { assertThat( eurekaHttpClient.statusUpdate("test", instanceId, InstanceInfo.InstanceStatus.UP, info).getStatusCode()) .isEqualTo(HttpStatus.OK.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test", instanceId); } @Test void testDeleteStatusOverride() { assertThat(eurekaHttpClient.deleteStatusOverride("test", "test", info).getStatusCode()) .isEqualTo(HttpStatus.OK.value()); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test"); } @Test @@ -89,29 +118,39 @@ void testGetApplications() { Applications entity = eurekaHttpClient.getApplications().getEntity(); assertThat(entity).isNotNull(); assertThat(eurekaHttpClient.getApplications("us", "eu").getEntity()).isNotNull(); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("us,eu"); } @Test void testGetDelta() { eurekaHttpClient.getDelta().getEntity(); eurekaHttpClient.getDelta("us", "eu").getEntity(); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("us,eu"); } @Test void testGetVips() { eurekaHttpClient.getVip("test"); eurekaHttpClient.getVip("test", "us", "eu"); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test", "us,eu"); } @Test void testGetSecureVip() { eurekaHttpClient.getSecureVip("test"); - eurekaHttpClient.getSecureVip("test", "us", "eu"); + eurekaHttpClient.getSecureVip("test", "us,eu"); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test", "us,eu"); } @Test void testGetApplication() { eurekaHttpClient.getApplication("test"); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings("test"); } @ParameterizedTest @@ -119,6 +158,28 @@ void testGetApplication() { void testGetInstance(String instanceId) { eurekaHttpClient.getInstance(instanceId); eurekaHttpClient.getInstance("test", instanceId); + + assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings(instanceId); + } + + /** + * Verifies that the client request observations that are created by the eureka client + * implementation do not have the URI key-value containing anything that could be + * considered high-cardinality like the lastDirtyTimestamp or an instance id. + * @param values Strings that should not appear in the URI key-value in addition to + * the common ones. Must not be empty. + */ + private void assertThatClientHttpObservationUriKeyValueDoesNotContainVariableStrings(CharSequence... values) { + TestObservationRegistryAssert.assertThat(this.observationRegistry) + .forAllObservationsWithNameEqualTo("http.client.requests", c -> ((ObservationContextAssert) c) + .asInstanceOf(InstanceOfAssertFactories.type(Observation.Context.class)) + .extracting(context -> context + .getLowCardinalityKeyValue(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI.asString()) + .getValue()) + .asString() + .doesNotContain(Set.of(info.getAppName(), info.getLastDirtyTimestamp().toString())) + .doesNotContain(ArrayUtils.toStringArray(InstanceStatus.values())) + .doesNotContain(values)); } } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTests.java index 79e83c125..95f0f2bb3 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTests.java @@ -55,6 +55,7 @@ class RestTemplateEurekaHttpClientTests extends AbstractEurekaHttpClientTests { @BeforeEach void setup() { eurekaHttpClient = new RestTemplateTransportClientFactory().newClient(new DefaultEndpoint(serviceUrl)); + ((RestTemplateEurekaHttpClient) eurekaHttpClient).getRestTemplate().setObservationRegistry(observationRegistry); EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClientTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClientTests.java index 49df864e6..50d1fb283 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClientTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClientTests.java @@ -47,7 +47,8 @@ class WebClientEurekaHttpClientTests extends AbstractEurekaHttpClientTests { @BeforeEach void setup() { - eurekaHttpClient = new WebClientTransportClientFactory(WebClient::builder) + eurekaHttpClient = new WebClientTransportClientFactory( + () -> WebClient.builder().observationRegistry(observationRegistry)) .newClient(new DefaultEndpoint(serviceUrl)); EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils);