From 079ae668c08523399f105db51e3cab120ff512ff Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Wed, 9 Mar 2022 15:52:47 +0100 Subject: [PATCH] Add resolving Health Status from composite indicators. --- .../eureka/EurekaHealthCheckHandler.java | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) 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 370c48d5e..19f5ce420 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 @@ -19,19 +19,21 @@ package org.springframework.cloud.netflix.eureka; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; -import java.util.stream.Collectors; import com.netflix.appinfo.HealthCheckHandler; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.InstanceStatus; -import reactor.core.publisher.Mono; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.actuate.health.CompositeHealthContributor; +import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor; import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthContributor; import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.actuate.health.NamedContributor; +import org.springframework.boot.actuate.health.ReactiveHealthContributor; import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.health.StatusAggregator; @@ -58,6 +60,7 @@ import org.springframework.util.Assert; * @author Spencer Gibb * @author Nowrin Anwar Joyita * @author Bertrand Renuart + * @author Olga Maciaszek-Sharma * @see HealthCheckHandler * @see StatusAggregator */ @@ -77,14 +80,14 @@ public class EurekaHealthCheckHandler private ApplicationContext applicationContext; - private Map healthIndicators = new HashMap<>(); + private Map healthContributors = new HashMap<>(); /** * {@code true} until the context is stopped. */ private boolean running = true; - private Map reactiveHealthIndicators = new HashMap<>(); + private Map reactiveHealthContributors = new HashMap<>(); public EurekaHealthCheckHandler(StatusAggregator statusAggregator) { this.statusAggregator = statusAggregator; @@ -99,39 +102,28 @@ public class EurekaHealthCheckHandler @Override public void afterPropertiesSet() { - final Map healthIndicators = applicationContext.getBeansOfType(HealthIndicator.class); - final Map reactiveHealthIndicators = applicationContext - .getBeansOfType(ReactiveHealthIndicator.class); - - populateHealthIndicators(healthIndicators); - populateReactiveHealthIndicators(reactiveHealthIndicators); + populateHealthContributors(applicationContext.getBeansOfType(HealthContributor.class)); + reactiveHealthContributors.putAll(applicationContext.getBeansOfType(ReactiveHealthContributor.class)); } - void populateHealthIndicators(Map healthIndicators) { - for (Map.Entry entry : healthIndicators.entrySet()) { + void populateHealthContributors(Map healthContributors) { + for (Map.Entry entry : healthContributors.entrySet()) { // ignore EurekaHealthIndicator and flatten the rest of the composite // otherwise there is a never ending cycle of down. See gh-643 if (entry.getValue() instanceof DiscoveryCompositeHealthContributor) { DiscoveryCompositeHealthContributor indicator = (DiscoveryCompositeHealthContributor) entry.getValue(); - indicator.forEach(contributor -> { - if (!(contributor.getContributor() instanceof EurekaHealthIndicator)) { - this.healthIndicators.put(contributor.getName(), - (HealthIndicator) contributor.getContributor()); + indicator.getIndicators().forEach((name, discoveryHealthIndicator) -> { + if (!(discoveryHealthIndicator instanceof EurekaHealthIndicator)) { + healthContributors.put(name, (HealthIndicator) discoveryHealthIndicator::health); } }); } else { - this.healthIndicators.put(entry.getKey(), entry.getValue()); + this.healthContributors.put(entry.getKey(), entry.getValue()); } } } - void populateReactiveHealthIndicators(Map reactiveHealthIndicators) { - for (Map.Entry entry : reactiveHealthIndicators.entrySet()) { - this.reactiveHealthIndicators.put(entry.getKey(), entry.getValue()); - } - } - @Override public InstanceStatus getStatus(InstanceStatus instanceStatus) { if (running) { @@ -151,21 +143,39 @@ public class EurekaHealthCheckHandler } protected Status getStatus(StatusAggregator statusAggregator) { - Status status; - Set statusSet = new HashSet<>(); - if (healthIndicators != null) { - statusSet.addAll(healthIndicators.values().stream().map(HealthIndicator::health).map(Health::getStatus) - .collect(Collectors.toSet())); + for (HealthContributor contributor : healthContributors.values()) { + processContributor(statusSet, contributor); } - - if (reactiveHealthIndicators != null) { - statusSet.addAll(reactiveHealthIndicators.values().stream().map(ReactiveHealthIndicator::health) - .map(Mono::block).filter(Objects::nonNull).map(Health::getStatus).collect(Collectors.toSet())); + for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) { + processContributor(statusSet, contributor); } + return statusAggregator.getAggregateStatus(statusSet); + } - status = statusAggregator.getAggregateStatus(statusSet); - return status; + private void processContributor(Set statusSet, HealthContributor contributor) { + if (contributor instanceof CompositeHealthContributor) { + for (NamedContributor contrib : (CompositeHealthContributor) contributor) { + processContributor(statusSet, contrib.getContributor()); + } + } + else if (contributor instanceof HealthIndicator) { + statusSet.add(((HealthIndicator) contributor).health().getStatus()); + } + } + + private void processContributor(Set statusSet, ReactiveHealthContributor contributor) { + if (contributor instanceof CompositeReactiveHealthContributor) { + for (NamedContributor contrib : (CompositeReactiveHealthContributor) contributor) { + processContributor(statusSet, contrib.getContributor()); + } + } + else if (contributor instanceof ReactiveHealthIndicator) { + Health health = ((ReactiveHealthIndicator) contributor).health().block(); + if (health != null) { + statusSet.add(health.getStatus()); + } + } } protected InstanceStatus mapToInstanceStatus(Status status) {