Add support for ReactiveHealthIndicatorRegistry
This commit updates the initial proposal to add support for reactive use cases as well. A reactive application can use ReactiveHealthIndicatorRegistry as an alternative to HealthIndicatorRegistry. Closes gh-4965
This commit is contained in:
@@ -20,8 +20,10 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.DefaultReactiveHealthIndicatorRegistry;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicatorRegistry;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
/**
|
||||
@@ -41,11 +43,10 @@ public abstract class CompositeReactiveHealthIndicatorConfiguration<H extends Re
|
||||
if (beans.size() == 1) {
|
||||
return createHealthIndicator(beans.values().iterator().next());
|
||||
}
|
||||
CompositeReactiveHealthIndicator composite = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator);
|
||||
beans.forEach((name, source) -> composite.addHealthIndicator(name,
|
||||
ReactiveHealthIndicatorRegistry registry = new DefaultReactiveHealthIndicatorRegistry();
|
||||
beans.forEach((name, source) -> registry.register(name,
|
||||
createHealthIndicator(source)));
|
||||
return composite;
|
||||
return new CompositeReactiveHealthIndicator(this.healthAggregator, registry);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -16,23 +16,21 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.health;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthIndicatorFactory;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||
import org.springframework.boot.actuate.health.HealthEndpointWebExtension;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthStatusHttpMapper;
|
||||
import org.springframework.boot.actuate.health.HealthWebEndpointResponseMapper;
|
||||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicatorRegistry;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -70,19 +68,16 @@ class HealthEndpointWebExtensionConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@ConditionalOnSingleCandidate(ReactiveHealthIndicatorRegistry.class)
|
||||
static class ReactiveWebHealthConfiguration {
|
||||
|
||||
private final ReactiveHealthIndicator reactiveHealthIndicator;
|
||||
|
||||
ReactiveWebHealthConfiguration(ObjectProvider<HealthAggregator> healthAggregator,
|
||||
ObjectProvider<Map<String, ReactiveHealthIndicator>> reactiveHealthIndicators,
|
||||
ObjectProvider<Map<String, HealthIndicator>> healthIndicators) {
|
||||
this.reactiveHealthIndicator = new CompositeReactiveHealthIndicatorFactory()
|
||||
.createReactiveHealthIndicator(
|
||||
healthAggregator.getIfAvailable(OrderedHealthAggregator::new),
|
||||
reactiveHealthIndicators
|
||||
.getIfAvailable(Collections::emptyMap),
|
||||
healthIndicators.getIfAvailable(Collections::emptyMap));
|
||||
ReactiveHealthIndicatorRegistry registry) {
|
||||
this.reactiveHealthIndicator = new CompositeReactiveHealthIndicator(
|
||||
healthAggregator.getIfAvailable(OrderedHealthAggregator::new),
|
||||
registry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -16,13 +16,22 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.health;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicatorRegistry;
|
||||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicatorRegistry;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicatorRegistryFactory;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -71,4 +80,20 @@ public class HealthIndicatorAutoConfiguration {
|
||||
return HealthIndicatorRegistryBeans.get(applicationContext);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Flux.class)
|
||||
static class ReactiveHealthIndicatorConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ReactiveHealthIndicatorRegistry reactiveHealthIndicatorRegistry(
|
||||
ObjectProvider<Map<String, ReactiveHealthIndicator>> reactiveHealthIndicators,
|
||||
ObjectProvider<Map<String, HealthIndicator>> healthIndicators) {
|
||||
return new ReactiveHealthIndicatorRegistryFactory().createReactiveHealthIndicatorRegistry(
|
||||
reactiveHealthIndicators.getIfAvailable(Collections::emptyMap),
|
||||
healthIndicators.getIfAvailable(Collections::emptyMap));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.health;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthIndicatorFactory;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Creates a {@link CompositeReactiveHealthIndicator} from beans in the
|
||||
* {@link ApplicationContext}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
final class HealthIndicatorBeansReactiveComposite {
|
||||
|
||||
private HealthIndicatorBeansReactiveComposite() {
|
||||
}
|
||||
|
||||
public static ReactiveHealthIndicator get(ApplicationContext applicationContext) {
|
||||
HealthAggregator healthAggregator = getHealthAggregator(applicationContext);
|
||||
return new CompositeReactiveHealthIndicatorFactory()
|
||||
.createReactiveHealthIndicator(healthAggregator,
|
||||
applicationContext.getBeansOfType(ReactiveHealthIndicator.class),
|
||||
applicationContext.getBeansOfType(HealthIndicator.class));
|
||||
}
|
||||
|
||||
private static HealthAggregator getHealthAggregator(
|
||||
ApplicationContext applicationContext) {
|
||||
try {
|
||||
return applicationContext.getBean(HealthAggregator.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return new OrderedHealthAggregator();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthWebEndpointResponseMapper;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicatorRegistry;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -217,6 +218,24 @@ public class ReactiveHealthEndpointWebExtensionTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registryCanBeAltered() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(HealthIndicatorsConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
ReactiveHealthIndicatorRegistry registry = context.getBean(
|
||||
ReactiveHealthIndicatorRegistry.class);
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).block().getBody().getDetails())
|
||||
.containsOnlyKeys("application", "first", "second");
|
||||
assertThat(registry.unregister("second")).isNotNull();
|
||||
assertThat(extension.health(null).block().getBody().getDetails())
|
||||
.containsKeys("application", "first");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class HealthIndicatorsConfiguration {
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ReactiveHealthIndicator} that returns health indications from all registered
|
||||
* delegates. Provides an alternative {@link Health} for a delegate that reaches a
|
||||
@@ -37,7 +35,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator {
|
||||
|
||||
private final Map<String, ReactiveHealthIndicator> indicators;
|
||||
private final ReactiveHealthIndicatorRegistry registry;
|
||||
|
||||
private final HealthAggregator healthAggregator;
|
||||
|
||||
@@ -47,15 +45,42 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
|
||||
private final Function<Mono<Health>, Mono<Health>> timeoutCompose;
|
||||
|
||||
/**
|
||||
* Create a new {@link CompositeReactiveHealthIndicator}.
|
||||
* @param healthAggregator the health aggregator
|
||||
* @deprecated since 2.1.0 in favour of
|
||||
* {@link #CompositeReactiveHealthIndicator(HealthAggregator, ReactiveHealthIndicatorRegistry)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CompositeReactiveHealthIndicator(HealthAggregator healthAggregator) {
|
||||
this(healthAggregator, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CompositeReactiveHealthIndicator} from the specified
|
||||
* indicators.
|
||||
* @param healthAggregator the health aggregator
|
||||
* @param indicators a map of {@link ReactiveHealthIndicator HealthIndicators} with
|
||||
* the key being used as an indicator name.
|
||||
* @deprecated since 2.1.0 in favour of
|
||||
* {@link #CompositeReactiveHealthIndicator(HealthAggregator, ReactiveHealthIndicatorRegistry)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CompositeReactiveHealthIndicator(HealthAggregator healthAggregator,
|
||||
Map<String, ReactiveHealthIndicator> indicators) {
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
Assert.notNull(indicators, "Indicators must not be null");
|
||||
this.indicators = new LinkedHashMap<>(indicators);
|
||||
this(healthAggregator, new DefaultReactiveHealthIndicatorRegistry(indicators));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CompositeReactiveHealthIndicator} from the indicators in the
|
||||
* given {@code registry}.
|
||||
* @param healthAggregator the health aggregator
|
||||
* @param registry the registry of {@link ReactiveHealthIndicator HealthIndicators}.
|
||||
*/
|
||||
public CompositeReactiveHealthIndicator(HealthAggregator healthAggregator,
|
||||
ReactiveHealthIndicatorRegistry registry) {
|
||||
this.registry = registry;
|
||||
this.healthAggregator = healthAggregator;
|
||||
this.timeoutCompose = (mono) -> (this.timeout != null ? mono.timeout(
|
||||
Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : mono);
|
||||
@@ -66,10 +91,15 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
* @param name the name of the health indicator
|
||||
* @param indicator the health indicator to add
|
||||
* @return this instance
|
||||
* @throws IllegalStateException if an indicator with the given {@code name}
|
||||
* is already registered.
|
||||
* @deprecated since 2.1.0 in favour of
|
||||
* {@link ReactiveHealthIndicatorRegistry#register(String, ReactiveHealthIndicator)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CompositeReactiveHealthIndicator addHealthIndicator(String name,
|
||||
ReactiveHealthIndicator indicator) {
|
||||
this.indicators.put(name, indicator);
|
||||
this.registry.register(name, indicator);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -92,7 +122,7 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
|
||||
@Override
|
||||
public Mono<Health> health() {
|
||||
return Flux.fromIterable(this.indicators.entrySet())
|
||||
return Flux.fromIterable(this.registry.getAll().entrySet())
|
||||
.flatMap((entry) -> Mono.zip(Mono.just(entry.getKey()),
|
||||
entry.getValue().health().compose(this.timeoutCompose)))
|
||||
.collectMap(Tuple2::getT1, Tuple2::getT2)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,19 +16,20 @@
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Factory to create a {@link CompositeReactiveHealthIndicator}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
* @deprecated since 2.1.0 in favor of
|
||||
* {@link CompositeReactiveHealthIndicator#CompositeReactiveHealthIndicator(HealthAggregator, ReactiveHealthIndicatorRegistry)}
|
||||
*/
|
||||
@Deprecated
|
||||
public class CompositeReactiveHealthIndicatorFactory {
|
||||
|
||||
private final Function<String, String> healthIndicatorNameFactory;
|
||||
@@ -62,30 +63,11 @@ public class CompositeReactiveHealthIndicatorFactory {
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
Assert.notNull(reactiveHealthIndicators,
|
||||
"ReactiveHealthIndicators must not be null");
|
||||
CompositeReactiveHealthIndicator healthIndicator = new CompositeReactiveHealthIndicator(
|
||||
healthAggregator);
|
||||
merge(reactiveHealthIndicators, healthIndicators)
|
||||
.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
healthIndicator.addHealthIndicator(name, indicator);
|
||||
});
|
||||
return healthIndicator;
|
||||
}
|
||||
|
||||
private Map<String, ReactiveHealthIndicator> merge(
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
if (ObjectUtils.isEmpty(healthIndicators)) {
|
||||
return reactiveHealthIndicators;
|
||||
}
|
||||
Map<String, ReactiveHealthIndicator> allIndicators = new LinkedHashMap<>(
|
||||
reactiveHealthIndicators);
|
||||
healthIndicators.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
allIndicators.computeIfAbsent(name,
|
||||
(n) -> new HealthIndicatorReactiveAdapter(indicator));
|
||||
});
|
||||
return allIndicators;
|
||||
ReactiveHealthIndicatorRegistryFactory factory = new ReactiveHealthIndicatorRegistryFactory(
|
||||
this.healthIndicatorNameFactory);
|
||||
return new CompositeReactiveHealthIndicator(healthAggregator,
|
||||
factory.createReactiveHealthIndicatorRegistry(reactiveHealthIndicators,
|
||||
healthIndicators));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ReactiveHealthIndicatorRegistry}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class DefaultReactiveHealthIndicatorRegistry
|
||||
implements ReactiveHealthIndicatorRegistry {
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final Map<String, ReactiveHealthIndicator> healthIndicators;
|
||||
|
||||
/**
|
||||
* Create a new {@link DefaultReactiveHealthIndicatorRegistry}.
|
||||
*/
|
||||
public DefaultReactiveHealthIndicatorRegistry() {
|
||||
this(new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link DefaultReactiveHealthIndicatorRegistry} from the specified
|
||||
* indicators.
|
||||
* @param healthIndicators a map of {@link HealthIndicator}s with the key
|
||||
* being used as an indicator name.
|
||||
*/
|
||||
public DefaultReactiveHealthIndicatorRegistry(
|
||||
Map<String, ReactiveHealthIndicator> healthIndicators) {
|
||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||
this.healthIndicators = new LinkedHashMap<>(healthIndicators);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String name, ReactiveHealthIndicator healthIndicator) {
|
||||
Assert.notNull(healthIndicator, "HealthIndicator must not be null");
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
synchronized (this.monitor) {
|
||||
ReactiveHealthIndicator existing = this.healthIndicators.putIfAbsent(name,
|
||||
healthIndicator);
|
||||
if (existing != null) {
|
||||
throw new IllegalStateException(
|
||||
"HealthIndicator with name '" + name + "' already registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveHealthIndicator unregister(String name) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
synchronized (this.monitor) {
|
||||
return this.healthIndicators.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveHealthIndicator get(String name) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
synchronized (this.monitor) {
|
||||
return this.healthIndicators.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ReactiveHealthIndicator> getAll() {
|
||||
synchronized (this.monitor) {
|
||||
return Collections
|
||||
.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import java.util.Map;
|
||||
public interface HealthIndicatorRegistry {
|
||||
|
||||
/**
|
||||
* Registers the given {@code healthIndicator}, associating it with the
|
||||
* Registers the given {@link HealthIndicator}, associating it with the
|
||||
* given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @param healthIndicator the indicator
|
||||
@@ -41,7 +41,7 @@ public interface HealthIndicatorRegistry {
|
||||
void register(String name, HealthIndicator healthIndicator);
|
||||
|
||||
/**
|
||||
* Unregisters the {@code HealthIndicator} previously registered with the
|
||||
* Unregisters the {@link HealthIndicator} previously registered with the
|
||||
* given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @return the unregistered indicator, or {@code null} if no indicator was
|
||||
@@ -50,7 +50,7 @@ public interface HealthIndicatorRegistry {
|
||||
HealthIndicator unregister(String name);
|
||||
|
||||
/**
|
||||
* Returns the health indicator registered with the given {@code name}.
|
||||
* Returns the {@link HealthIndicator} registered with the given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @return the health indicator, or {@code null} if no indicator was
|
||||
* registered with the given {@code name}.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A registry of {@link ReactiveHealthIndicator ReactiveHealthIndicators}.
|
||||
* <p>
|
||||
* Implementations <strong>must</strong> be thread-safe.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Vedran Pavic
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public interface ReactiveHealthIndicatorRegistry {
|
||||
|
||||
/**
|
||||
* Registers the given {@link ReactiveHealthIndicator}, associating it with the
|
||||
* given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @param healthIndicator the indicator
|
||||
* @throws IllegalStateException if an indicator with the given {@code name}
|
||||
* is already registered.
|
||||
*/
|
||||
void register(String name, ReactiveHealthIndicator healthIndicator);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link ReactiveHealthIndicator} previously registered with the
|
||||
* given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @return the unregistered indicator, or {@code null} if no indicator was
|
||||
* found in the registry for the given {@code name}.
|
||||
*/
|
||||
ReactiveHealthIndicator unregister(String name);
|
||||
|
||||
/**
|
||||
* Returns the {@link ReactiveHealthIndicator} registered with the given {@code name}.
|
||||
* @param name the name of the indicator
|
||||
* @return the health indicator, or {@code null} if no indicator was
|
||||
* registered with the given {@code name}.
|
||||
*/
|
||||
ReactiveHealthIndicator get(String name);
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the registered health indicators and their names.
|
||||
* The contents of the map do not reflect subsequent changes to the
|
||||
* registry.
|
||||
* @return the snapshot of registered health indicators
|
||||
*/
|
||||
Map<String, ReactiveHealthIndicator> getAll();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Factory to create a {@link HealthIndicatorRegistry}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class ReactiveHealthIndicatorRegistryFactory {
|
||||
|
||||
private final Function<String, String> healthIndicatorNameFactory;
|
||||
|
||||
public ReactiveHealthIndicatorRegistryFactory(
|
||||
Function<String, String> healthIndicatorNameFactory) {
|
||||
this.healthIndicatorNameFactory = healthIndicatorNameFactory;
|
||||
}
|
||||
|
||||
public ReactiveHealthIndicatorRegistryFactory() {
|
||||
this(new HealthIndicatorNameFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ReactiveHealthIndicatorRegistry} based on the specified health
|
||||
* indicators. Each {@link HealthIndicator} are wrapped to a
|
||||
* {@link HealthIndicatorReactiveAdapter}. If two instances share the same name, the
|
||||
* reactive variant takes precedence.
|
||||
* @param reactiveHealthIndicators the {@link ReactiveHealthIndicator} instances
|
||||
* mapped by name
|
||||
* @param healthIndicators the {@link HealthIndicator} instances mapped by name if
|
||||
* any.
|
||||
* @return a {@link ReactiveHealthIndicator} that delegates to the specified
|
||||
* {@code reactiveHealthIndicators}.
|
||||
*/
|
||||
public ReactiveHealthIndicatorRegistry createReactiveHealthIndicatorRegistry(
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
Assert.notNull(reactiveHealthIndicators,
|
||||
"ReactiveHealthIndicators must not be null");
|
||||
return initialize(new DefaultReactiveHealthIndicatorRegistry(),
|
||||
reactiveHealthIndicators, healthIndicators);
|
||||
}
|
||||
|
||||
protected <T extends ReactiveHealthIndicatorRegistry> T initialize(T registry,
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
merge(reactiveHealthIndicators, healthIndicators)
|
||||
.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
registry.register(name, indicator);
|
||||
});
|
||||
return registry;
|
||||
}
|
||||
|
||||
private Map<String, ReactiveHealthIndicator> merge(
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
if (ObjectUtils.isEmpty(healthIndicators)) {
|
||||
return reactiveHealthIndicators;
|
||||
}
|
||||
Map<String, ReactiveHealthIndicator> allIndicators = new LinkedHashMap<>(
|
||||
reactiveHealthIndicators);
|
||||
healthIndicators.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
allIndicators.computeIfAbsent(name,
|
||||
(n) -> new HealthIndicatorReactiveAdapter(indicator));
|
||||
});
|
||||
return allIndicators;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Deprecated
|
||||
public class CompositeReactiveHealthIndicatorFactoryTests {
|
||||
|
||||
private static final Health UP = new Health.Builder().status(Status.UP).build();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,9 @@
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -38,13 +41,12 @@ public class CompositeReactiveHealthIndicatorTests {
|
||||
|
||||
private OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator();
|
||||
|
||||
private CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator);
|
||||
|
||||
@Test
|
||||
public void singleIndicator() {
|
||||
this.indicator.addHealthIndicator("test", () -> Mono.just(HEALTHY));
|
||||
StepVerifier.create(this.indicator.health()).consumeNextWith((h) -> {
|
||||
CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator, new DefaultReactiveHealthIndicatorRegistry(
|
||||
Collections.singletonMap("test", () -> Mono.just(HEALTHY))));
|
||||
StepVerifier.create(indicator.health()).consumeNextWith((h) -> {
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).containsOnlyKeys("test");
|
||||
assertThat(h.getDetails().get("test")).isEqualTo(HEALTHY);
|
||||
@@ -53,24 +55,31 @@ public class CompositeReactiveHealthIndicatorTests {
|
||||
|
||||
@Test
|
||||
public void longHealth() {
|
||||
Map<String, ReactiveHealthIndicator> indicators = new HashMap<>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
this.indicator.addHealthIndicator("test" + i,
|
||||
new TimeoutHealth(10000, Status.UP));
|
||||
indicators.put("test" + i, new TimeoutHealth(10000, Status.UP));
|
||||
}
|
||||
StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
|
||||
CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator,
|
||||
new DefaultReactiveHealthIndicatorRegistry(indicators));
|
||||
StepVerifier.withVirtualTime(indicator::health).expectSubscription()
|
||||
.thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).hasSize(50);
|
||||
}).verifyComplete();
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).hasSize(50);
|
||||
}).verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeoutReachedUsesFallback() {
|
||||
this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
|
||||
.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
|
||||
Map<String, ReactiveHealthIndicator> indicators = new HashMap<>();
|
||||
indicators.put("slow", new TimeoutHealth(10000, Status.UP));
|
||||
indicators.put("fast", new TimeoutHealth(10, Status.UP));
|
||||
CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator,
|
||||
new DefaultReactiveHealthIndicatorRegistry(indicators))
|
||||
.timeoutStrategy(100, UNKNOWN_HEALTH);
|
||||
StepVerifier.create(this.indicator.health()).consumeNextWith((h) -> {
|
||||
StepVerifier.create(indicator.health()).consumeNextWith((h) -> {
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
|
||||
assertThat(h.getDetails().get("slow")).isEqualTo(UNKNOWN_HEALTH);
|
||||
@@ -80,16 +89,20 @@ public class CompositeReactiveHealthIndicatorTests {
|
||||
|
||||
@Test
|
||||
public void timeoutNotReached() {
|
||||
this.indicator.addHealthIndicator("slow", new TimeoutHealth(10000, Status.UP))
|
||||
.addHealthIndicator("fast", new TimeoutHealth(10, Status.UP))
|
||||
Map<String, ReactiveHealthIndicator> indicators = new HashMap<>();
|
||||
indicators.put("slow", new TimeoutHealth(10000, Status.UP));
|
||||
indicators.put("fast", new TimeoutHealth(10, Status.UP));
|
||||
CompositeReactiveHealthIndicator indicator = new CompositeReactiveHealthIndicator(
|
||||
this.healthAggregator,
|
||||
new DefaultReactiveHealthIndicatorRegistry(indicators))
|
||||
.timeoutStrategy(20000, null);
|
||||
StepVerifier.withVirtualTime(this.indicator::health).expectSubscription()
|
||||
StepVerifier.withVirtualTime(indicator::health).expectSubscription()
|
||||
.thenAwait(Duration.ofMillis(10000)).consumeNextWith((h) -> {
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
|
||||
assertThat(h.getDetails().get("slow")).isEqualTo(HEALTHY);
|
||||
assertThat(h.getDetails().get("fast")).isEqualTo(HEALTHY);
|
||||
}).verifyComplete();
|
||||
assertThat(h.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(h.getDetails()).containsOnlyKeys("slow", "fast");
|
||||
assertThat(h.getDetails().get("slow")).isEqualTo(HEALTHY);
|
||||
assertThat(h.getDetails().get("fast")).isEqualTo(HEALTHY);
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
static class TimeoutHealth implements ReactiveHealthIndicator {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultReactiveHealthIndicatorRegistry}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class DefaultReactiveHealthIndicatorRegistryTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private ReactiveHealthIndicator one = mock(ReactiveHealthIndicator.class);
|
||||
|
||||
private ReactiveHealthIndicator two = mock(ReactiveHealthIndicator.class);
|
||||
|
||||
private DefaultReactiveHealthIndicatorRegistry registry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
given(this.one.health()).willReturn(Mono.just(
|
||||
new Health.Builder().unknown().withDetail("1", "1").build()));
|
||||
given(this.two.health()).willReturn(Mono.just(
|
||||
new Health.Builder().unknown().withDetail("2", "2").build()));
|
||||
this.registry = new DefaultReactiveHealthIndicatorRegistry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void register() {
|
||||
this.registry.register("one", this.one);
|
||||
this.registry.register("two", this.two);
|
||||
assertThat(this.registry.getAll()).hasSize(2);
|
||||
assertThat(this.registry.get("one")).isSameAs(this.one);
|
||||
assertThat(this.registry.get("two")).isSameAs(this.two);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerAlreadyUsedName() {
|
||||
this.registry.register("one", this.one);
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("HealthIndicator with name 'one' already registered");
|
||||
this.registry.register("one", this.two);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregister() {
|
||||
this.registry.register("one", this.one);
|
||||
this.registry.register("two", this.two);
|
||||
assertThat(this.registry.getAll()).hasSize(2);
|
||||
ReactiveHealthIndicator two = this.registry.unregister("two");
|
||||
assertThat(two).isSameAs(this.two);
|
||||
assertThat(this.registry.getAll()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterUnknown() {
|
||||
this.registry.register("one", this.one);
|
||||
assertThat(this.registry.getAll()).hasSize(1);
|
||||
ReactiveHealthIndicator two = this.registry.unregister("two");
|
||||
assertThat(two).isNull();
|
||||
assertThat(this.registry.getAll()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllIsASnapshot() {
|
||||
this.registry.register("one", this.one);
|
||||
Map<String, ReactiveHealthIndicator> snapshot = this.registry.getAll();
|
||||
assertThat(snapshot).containsOnlyKeys("one");
|
||||
this.registry.register("two", this.two);
|
||||
assertThat(snapshot).containsOnlyKeys("one");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllIsImmutable() {
|
||||
this.registry.register("one", this.one);
|
||||
Map<String, ReactiveHealthIndicator> snapshot = this.registry.getAll();
|
||||
|
||||
this.thrown.expect(UnsupportedOperationException.class);
|
||||
snapshot.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ReactiveHealthIndicatorRegistryFactory}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ReactiveHealthIndicatorRegistryFactoryTests {
|
||||
|
||||
private static final Health UP = new Health.Builder().status(Status.UP).build();
|
||||
|
||||
private static final Health DOWN = new Health.Builder().status(Status.DOWN).build();
|
||||
|
||||
private final ReactiveHealthIndicatorRegistryFactory factory = new ReactiveHealthIndicatorRegistryFactory();
|
||||
|
||||
@Test
|
||||
public void defaultHealthIndicatorNameFactory() {
|
||||
ReactiveHealthIndicatorRegistry registry = this.factory.createReactiveHealthIndicatorRegistry(
|
||||
Collections.singletonMap("myHealthIndicator", () -> Mono.just(UP)), null);
|
||||
assertThat(registry.getAll()).containsOnlyKeys("my");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthIndicatorIsAdapted() {
|
||||
ReactiveHealthIndicatorRegistry registry = this.factory.createReactiveHealthIndicatorRegistry(
|
||||
Collections.singletonMap("test", () -> Mono.just(UP)),
|
||||
Collections.singletonMap("regular", () -> DOWN));
|
||||
assertThat(registry.getAll()).containsOnlyKeys("test", "regular");
|
||||
StepVerifier.create(registry.get("regular").health()).consumeNextWith((h) -> {
|
||||
assertThat(h.getStatus()).isEqualTo(Status.DOWN);
|
||||
assertThat(h.getDetails()).isEmpty();
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -725,16 +725,20 @@ NOTE: If you have secured your application and wish to use `always`, your securi
|
||||
configuration must permit access to the health endpoint for both authenticated and
|
||||
unauthenticated users.
|
||||
|
||||
Health information is collected from all
|
||||
Health information is collected from the content of a
|
||||
{sc-spring-boot-actuator}/health/HealthIndicatorRegistry.{sc-ext}[
|
||||
`HealthIndicatorRegistry`] (by default all
|
||||
{sc-spring-boot-actuator}/health/HealthIndicator.{sc-ext}[`HealthIndicator`] instances
|
||||
registered with {sc-spring-boot-actuator}/health/HealthIndicatorRegistry.{sc-ext}[
|
||||
`HealthIndicatorRegistry`]. Spring Boot includes a number of auto-configured
|
||||
defined in your `ApplicationContext`. Spring Boot includes a number of auto-configured
|
||||
`HealthIndicators` and you can also write your own. By default, the final system state is
|
||||
derived by the `HealthAggregator` which sorts the statuses from each `HealthIndicator`
|
||||
based on an ordered list of statuses. The first status in the sorted list is used as the
|
||||
overall health status. If no `HealthIndicator` returns a status that is known to the
|
||||
`HealthAggregator`, an `UNKNOWN` status is used.
|
||||
|
||||
TIP: The `HealthIndicatorRegistry` can be used to register and unregister health
|
||||
indicators at runtime.
|
||||
|
||||
|
||||
|
||||
==== Auto-configured HealthIndicators
|
||||
@@ -819,10 +823,6 @@ NOTE: The identifier for a given `HealthIndicator` is the name of the bean witho
|
||||
`HealthIndicator` suffix, if it exists. In the preceding example, the health information
|
||||
is available in an entry named `my`.
|
||||
|
||||
Additionally, you can register (and unregister) `HealthIndicator` instances in runtime
|
||||
using {sc-spring-boot-actuator}/health/HealthIndicatorRegistry.{sc-ext}[
|
||||
`HealthIndicatorRegistry`].
|
||||
|
||||
In addition to Spring Boot's predefined
|
||||
{sc-spring-boot-actuator}/health/Status.{sc-ext}[`Status`] types, it is also possible for
|
||||
`Health` to return a custom `Status` that represents a new system state. In such cases, a
|
||||
@@ -877,10 +877,17 @@ The following table shows the default status mappings for the built-in statuses:
|
||||
==== Reactive Health Indicators
|
||||
For reactive applications, such as those using Spring WebFlux, `ReactiveHealthIndicator`
|
||||
provides a non-blocking contract for getting application health. Similar to a traditional
|
||||
`HealthIndicator`, health information is collected from all
|
||||
{sc-spring-boot-actuator}/health/ReactiveHealthIndicator.{sc-ext}[`ReactiveHealthIndicator`]
|
||||
beans defined in your `ApplicationContext`. Regular `HealthIndicator` beans that do not
|
||||
check against a reactive API are included and executed on the elastic scheduler.
|
||||
`HealthIndicator`, health information is collected from the content of a
|
||||
{sc-spring-boot-actuator}/health/ReactiveHealthIndicatorRegistry.{sc-ext}[
|
||||
`ReactiveHealthIndicatorRegistry`] (by default all
|
||||
{sc-spring-boot-actuator}/health/HealthIndicator.{sc-ext}[`HealthIndicator`] and
|
||||
{sc-spring-boot-actuator}/health/ReactiveHealthIndicator.{sc-ext}[
|
||||
`ReactiveHealthIndicator`] instances defined in your `ApplicationContext`. Regular
|
||||
`HealthIndicator` that do not check against a reactive API are executed on the elastic
|
||||
scheduler.
|
||||
|
||||
TIP: In a reactive application, The `ReactiveHealthIndicatorRegistry` can be used to
|
||||
register and unregister health indicators at runtime.
|
||||
|
||||
To provide custom health information from a reactive API, you can register Spring beans
|
||||
that implement the
|
||||
|
||||
Reference in New Issue
Block a user