diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java index ff89ef7f9..60ee28afc 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java @@ -24,6 +24,8 @@ import java.util.Set; import com.netflix.appinfo.HealthCheckHandler; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.InstanceStatus; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -68,6 +70,8 @@ import org.springframework.util.Assert; public class EurekaHealthCheckHandler implements HealthCheckHandler, ApplicationContextAware, InitializingBean, Ordered, Lifecycle { + private static final Log log = LogFactory.getLog(EurekaHealthCheckHandler.class); + private static final Map STATUS_MAPPING = new HashMap<>() { { put(Status.UNKNOWN, InstanceStatus.UNKNOWN); @@ -127,7 +131,11 @@ public class EurekaHealthCheckHandler @Override public InstanceStatus getStatus(InstanceStatus instanceStatus) { if (running) { - return getHealthStatus(); + InstanceStatus status = getHealthStatus(); + if (status != instanceStatus) { + log.info("Eureka health status changed to " + status); + } + return status; } else { // Return nothing if the context is not running, so the status held by the @@ -143,37 +151,41 @@ public class EurekaHealthCheckHandler } protected Status getStatus(StatusAggregator statusAggregator) { - Set statusSet = new HashSet<>(); - for (HealthContributor contributor : healthContributors.values()) { - processContributor(statusSet, contributor); + Set statuses = new HashSet<>(); + for (Map.Entry entry : healthContributors.entrySet()) { + processContributor(statuses, entry.getKey(), entry.getValue()); } - for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) { - processContributor(statusSet, contributor); + for (Map.Entry entry : reactiveHealthContributors.entrySet()) { + processContributor(statuses, entry.getKey(), entry.getValue()); } - return statusAggregator.getAggregateStatus(statusSet); + return statusAggregator.getAggregateStatus(statuses); } - private void processContributor(Set statusSet, HealthContributor contributor) { + private void processContributor(Set statuses, String name, HealthContributor contributor) { if (contributor instanceof CompositeHealthContributor) { for (HealthContributors.Entry contrib : (CompositeHealthContributor) contributor) { - processContributor(statusSet, contrib.contributor()); + processContributor(statuses, contrib.name(), contrib.contributor()); } } else if (contributor instanceof HealthIndicator) { - statusSet.add(((HealthIndicator) contributor).health().getStatus()); + Status status = ((HealthIndicator) contributor).health().getStatus(); + log.debug("Health contributor " + name + " has status " + status); + statuses.add(status); } } - private void processContributor(Set statusSet, ReactiveHealthContributor contributor) { + private void processContributor(Set statuses, String name, ReactiveHealthContributor contributor) { if (contributor instanceof CompositeReactiveHealthContributor) { for (ReactiveHealthContributors.Entry contrib : (CompositeReactiveHealthContributor) contributor) { - processContributor(statusSet, contrib.contributor()); + processContributor(statuses, contrib.name(), contrib.contributor()); } } else if (contributor instanceof ReactiveHealthIndicator) { Health health = ((ReactiveHealthIndicator) contributor).health().block(); if (health != null) { - statusSet.add(health.getStatus()); + Status status = health.getStatus(); + log.debug("Health contributor " + name + " has status " + status); + statuses.add(status); } } } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java index f4eacdee1..396f6f30f 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java @@ -30,6 +30,7 @@ import org.springframework.boot.health.actuate.endpoint.SimpleStatusAggregator; import org.springframework.boot.health.contributor.AbstractHealthIndicator; import org.springframework.boot.health.contributor.AbstractReactiveHealthIndicator; import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.CompositeReactiveHealthContributor; import org.springframework.boot.health.contributor.Health; import org.springframework.boot.health.contributor.HealthContributor; import org.springframework.boot.health.contributor.HealthContributors; @@ -41,6 +42,7 @@ import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicato import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; @@ -195,6 +197,33 @@ class EurekaHealthCheckHandlerTests { } + public static class NamedUpHealthConfiguration { + + @Bean + public HealthIndicator upHealthIndicator() { + return () -> Health.up().build(); + } + + } + + public static class NamedDownHealthConfiguration { + + @Bean + public HealthIndicator downHealthIndicator() { + return () -> Health.down().build(); + } + + } + + public static class NamedReactiveUpHealthConfiguration { + + @Bean + public ReactiveHealthIndicator reactiveUpHealthIndicator() { + return () -> Mono.just(Health.up().build()); + } + + } + public static class FatalHealthConfiguration { @Bean @@ -327,4 +356,15 @@ class EurekaHealthCheckHandlerTests { } + @Configuration + static class NamedReactiveDownHealthConfiguration { + + @Bean + CompositeReactiveHealthContributor namedReactiveDownHealthContributor() { + return CompositeReactiveHealthContributor.fromMap(Map.of("reactiveDownHealthIndicator", + (ReactiveHealthIndicator) () -> Mono.just(Health.down().build()))); + } + + } + }