mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-09-17 07:43:44 +00:00
Log health contributor statuses in Eureka health checks
Signed-off-by: 98001yash <yashchauhan.gaya@gmail.com>
This commit is contained in:
+24
-17
@@ -19,11 +19,12 @@ package org.springframework.cloud.netflix.eureka;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
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 +69,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, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<>() {
|
||||
{
|
||||
put(Status.UNKNOWN, InstanceStatus.UNKNOWN);
|
||||
@@ -127,7 +130,12 @@ public class EurekaHealthCheckHandler
|
||||
@Override
|
||||
public InstanceStatus getStatus(InstanceStatus instanceStatus) {
|
||||
if (running) {
|
||||
return getHealthStatus();
|
||||
Map<String, Status> statuses = new HashMap<>();
|
||||
InstanceStatus status = getHealthStatus(statuses);
|
||||
if (status != instanceStatus) {
|
||||
log.info("Eureka health status changed to " + status + " with health contributors " + statuses);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
// Return nothing if the context is not running, so the status held by the
|
||||
@@ -137,43 +145,42 @@ public class EurekaHealthCheckHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected InstanceStatus getHealthStatus() {
|
||||
Status status = getStatus(statusAggregator);
|
||||
protected InstanceStatus getHealthStatus(Map<String, Status> statuses) {
|
||||
Status status = getStatus(statusAggregator, statuses);
|
||||
return mapToInstanceStatus(status);
|
||||
}
|
||||
|
||||
protected Status getStatus(StatusAggregator statusAggregator) {
|
||||
Set<Status> statusSet = new HashSet<>();
|
||||
for (HealthContributor contributor : healthContributors.values()) {
|
||||
processContributor(statusSet, contributor);
|
||||
protected Status getStatus(StatusAggregator statusAggregator, Map<String, Status> statuses) {
|
||||
for (Map.Entry<String, HealthContributor> entry : healthContributors.entrySet()) {
|
||||
processContributor(statuses, entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) {
|
||||
processContributor(statusSet, contributor);
|
||||
for (Map.Entry<String, ReactiveHealthContributor> entry : reactiveHealthContributors.entrySet()) {
|
||||
processContributor(statuses, entry.getKey(), entry.getValue());
|
||||
}
|
||||
return statusAggregator.getAggregateStatus(statusSet);
|
||||
return statusAggregator.getAggregateStatus(new HashSet<>(statuses.values()));
|
||||
}
|
||||
|
||||
private void processContributor(Set<Status> statusSet, HealthContributor contributor) {
|
||||
private void processContributor(Map<String, Status> 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());
|
||||
statuses.put(name, ((HealthIndicator) contributor).health().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void processContributor(Set<Status> statusSet, ReactiveHealthContributor contributor) {
|
||||
private void processContributor(Map<String, Status> 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());
|
||||
statuses.put(name, health.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
@@ -30,17 +30,20 @@ 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;
|
||||
import org.springframework.boot.health.contributor.HealthIndicator;
|
||||
import org.springframework.boot.health.contributor.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.health.contributor.Status;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthContributor;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
|
||||
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;
|
||||
|
||||
@@ -161,6 +164,30 @@ class EurekaHealthCheckHandlerTests {
|
||||
assertThat(status).isEqualTo(InstanceStatus.DOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContributorStatusesWithBlockingIndicators() {
|
||||
initialize(NamedUpHealthConfiguration.class, NamedDownHealthConfiguration.class);
|
||||
|
||||
Map<String, Status> statuses = new HashMap<>();
|
||||
Status status = healthCheckHandler.getStatus(new SimpleStatusAggregator(), statuses);
|
||||
|
||||
assertThat(status).isEqualTo(Status.DOWN);
|
||||
assertThat(statuses).containsEntry("upHealthIndicator", Status.UP);
|
||||
assertThat(statuses).containsEntry("downHealthIndicator", Status.DOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContributorStatusesWithReactiveIndicators() {
|
||||
initialize(NamedReactiveUpHealthConfiguration.class, NamedReactiveDownHealthConfiguration.class);
|
||||
|
||||
Map<String, Status> statuses = new HashMap<>();
|
||||
Status status = healthCheckHandler.getStatus(new SimpleStatusAggregator(), statuses);
|
||||
|
||||
assertThat(status).isEqualTo(Status.DOWN);
|
||||
assertThat(statuses).containsEntry("reactiveUpHealthIndicator", Status.UP);
|
||||
assertThat(statuses).containsEntry("reactiveDownHealthIndicator", Status.DOWN);
|
||||
}
|
||||
|
||||
private void initialize(Class<?>... configurations) {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(configurations);
|
||||
healthCheckHandler.setApplicationContext(applicationContext);
|
||||
@@ -195,6 +222,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 +381,15 @@ class EurekaHealthCheckHandlerTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class NamedReactiveDownHealthConfiguration {
|
||||
|
||||
@Bean
|
||||
CompositeReactiveHealthContributor namedReactiveDownHealthContributor() {
|
||||
return CompositeReactiveHealthContributor.fromMap(Map.of("reactiveDownHealthIndicator",
|
||||
(ReactiveHealthIndicator) () -> Mono.just(Health.down().build())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user