diff --git a/pom.xml b/pom.xml index aac243ab5..1590955f6 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ netflix 4.2.0-SNAPSHOT 4.2.0-SNAPSHOT - 1.20.3 + 1.20.4 5.15.0 diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index d6b1efb37..961cfaedb 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -98,6 +98,12 @@ spring-cloud-starter test + + org.awaitility + awaitility + test + + diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMetricsAutoConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMetricsAutoConfiguration.java index 62bce04e1..d47a30a21 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMetricsAutoConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMetricsAutoConfiguration.java @@ -28,11 +28,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.core.task.TaskExecutor; /** * Auto-configuration for Eureka Instance metrics. * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.1.2 */ @ConditionalOnClass(MeterRegistry.class) @@ -51,8 +53,8 @@ class EurekaInstanceMetricsAutoConfiguration { @ConditionalOnMissingBean @Bean public EurekaInstanceMonitor eurekaInstanceMeterBinder(MeterRegistry meterRegistry, - PeerAwareInstanceRegistry instanceRegistry, EurekaInstanceTagsProvider tagProvider) { - return new EurekaInstanceMonitor(meterRegistry, instanceRegistry, tagProvider); + PeerAwareInstanceRegistry instanceRegistry, EurekaInstanceTagsProvider tagProvider, TaskExecutor executor) { + return new EurekaInstanceMonitor(meterRegistry, instanceRegistry, tagProvider, executor); } } diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMonitor.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMonitor.java index 99bbd624a..5442ec232 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMonitor.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/metrics/EurekaInstanceMonitor.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.eureka.server.metrics; import java.util.Map; import java.util.Objects; +import java.util.concurrent.Executor; import java.util.stream.Collectors; import com.netflix.eureka.registry.PeerAwareInstanceRegistry; @@ -36,6 +37,7 @@ import org.springframework.context.event.SmartApplicationListener; * {@link PeerAwareInstanceRegistry}. * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.1.2 */ public class EurekaInstanceMonitor implements SmartApplicationListener { @@ -46,14 +48,17 @@ public class EurekaInstanceMonitor implements SmartApplicationListener { private final EurekaInstanceTagsProvider tagProvider; + private final Executor executor; + EurekaInstanceMonitor(MeterRegistry meterRegistry, PeerAwareInstanceRegistry instanceRegistry, - EurekaInstanceTagsProvider tagProvider) { + EurekaInstanceTagsProvider tagProvider, Executor executor) { Objects.requireNonNull(meterRegistry); this.instanceRegistry = Objects.requireNonNull(instanceRegistry); this.tagProvider = Objects.requireNonNull(tagProvider); this.eurekaInstances = MultiGauge.builder("eureka.server.instances") .description("Number of application instances registered with the Eureka server.") .register(meterRegistry); + this.executor = executor; } @Override @@ -71,6 +76,10 @@ public class EurekaInstanceMonitor implements SmartApplicationListener { .stream() .flatMap(application -> application.getInstances().stream()) .collect(Collectors.groupingBy(tagProvider::eurekaInstanceTags, Collectors.counting())); + executor.execute(() -> registerMetrics(aggregatedCounts)); + } + + private void registerMetrics(Map aggregatedCounts) { eurekaInstances.register(aggregatedCounts.entrySet() .stream() .map(entry -> MultiGauge.Row.of(entry.getKey(), entry.getValue())) diff --git a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorTests.java b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorTests.java index 41872218e..a5740752e 100644 --- a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorTests.java +++ b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorTests.java @@ -28,14 +28,21 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceMonitor; import org.springframework.context.annotation.Configuration; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getInstanceInfo; import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getLeaseInfo; /** + * Tests for {@link EurekaInstanceMonitor}. + * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma */ @SpringBootTest(classes = EurekaInstanceMonitorTests.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, @@ -151,9 +158,11 @@ class EurekaInstanceMonitorTests { } private void assertEurekaInstance(Map meterRegistryCounts) { - meterRegistryCounts.forEach((tags, - count) -> assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value()) - .isEqualTo(count)); + await().atMost(5, SECONDS) + .pollInterval(fibonacci()) + .untilAsserted(() -> meterRegistryCounts.forEach((tags, + count) -> assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value()) + .isEqualTo(count))); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorWithCustomTagsProviderTests.java b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorWithCustomTagsProviderTests.java index ec832013f..c7ea689dc 100644 --- a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorWithCustomTagsProviderTests.java +++ b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/EurekaInstanceMonitorWithCustomTagsProviderTests.java @@ -27,16 +27,23 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceMonitor; import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceTagsProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getInstanceInfo; import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getLeaseInfo; /** + * Tests for {@link EurekaInstanceMonitor} with custom tags provider. + * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma */ @SpringBootTest(classes = EurekaInstanceMonitorWithCustomTagsProviderTests.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, @@ -82,9 +89,11 @@ class EurekaInstanceMonitorWithCustomTagsProviderTests { } private void assertEurekaInstance(Map meterRegistryCounts) { - meterRegistryCounts.forEach((tags, - count) -> assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value()) - .isEqualTo(count)); + await().atMost(5, SECONDS) + .pollInterval(fibonacci()) + .untilAsserted(() -> meterRegistryCounts.forEach((tags, + count) -> assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value()) + .isEqualTo(count))); } @Configuration(proxyBeanMethods = false)