Spring Boot starter that provides comprehensive production-ready monitoring and management capabilities for applications
—
The Spring Boot Actuator health system provides comprehensive monitoring of application and infrastructure health through a flexible indicator-based architecture. It allows both built-in and custom health checks with detailed reporting and hierarchical organization.
Primary interface for creating health checks that report application component status.
/**
* Strategy interface for health indicators
*/
@FunctionalInterface
public interface HealthIndicator {
/**
* Return the current health information
* @return the health information
*/
Health health();
/**
* Return the current health information
* @param includeDetails whether to include details in the result
* @return the health information
*/
default Health getHealth(boolean includeDetails) {
Health health = health();
return includeDetails ? health : health.withoutDetails();
}
}Reactive version for asynchronous health checks using Project Reactor.
/**
* Strategy interface for reactive health indicators
*/
@FunctionalInterface
public interface ReactiveHealthIndicator {
/**
* Return the current health information
* @return a Mono that emits health information
*/
Mono<Health> health();
/**
* Return the current health information
* @param includeDetails whether to include details in the result
* @return a Mono that emits health information
*/
default Mono<Health> getHealth(boolean includeDetails) {
return health().map(h -> includeDetails ? h : h.withoutDetails());
}
}Immutable representation of health status with builder pattern support.
/**
* Immutable representation of application health
*/
public final class Health {
/**
* Create a new Builder instance for UP status
* @return new Builder instance
*/
public static Builder up() {
return status(Status.UP);
}
/**
* Create a new Builder instance for DOWN status
* @return new Builder instance
*/
public static Builder down() {
return status(Status.DOWN);
}
/**
* Create a new Builder instance for OUT_OF_SERVICE status
* @return new Builder instance
*/
public static Builder outOfService() {
return status(Status.OUT_OF_SERVICE);
}
/**
* Create a new Builder instance for UNKNOWN status
* @return new Builder instance
*/
public static Builder unknown() {
return status(Status.UNKNOWN);
}
/**
* Create a new Builder instance for the given status
* @param status the health status
* @return new Builder instance
*/
public static Builder status(Status status) {
return new Builder(status);
}
/**
* Get the health status
* @return the health status
*/
public Status getStatus() { /* ... */ }
/**
* Get the health details
* @return the health details
*/
public Map<String, Object> getDetails() { /* ... */ }
/**
* Return a copy of this health without details
* @return health without details
*/
public Health withoutDetails() { /* ... */ }
/**
* Builder for Health instances
*/
public static class Builder {
/**
* Add a detail to the health
* @param key the detail key
* @param value the detail value
* @return this builder
*/
public Builder withDetail(String key, Object value) { /* ... */ }
/**
* Add details to the health
* @param details the details to add
* @return this builder
*/
public Builder withDetails(Map<String, ?> details) { /* ... */ }
/**
* Add an exception to the health details
* @param ex the exception
* @return this builder
*/
public Builder withException(Exception ex) { /* ... */ }
/**
* Build the Health instance
* @return the built Health
*/
public Health build() { /* ... */ }
}
}Standard health status values with support for custom statuses.
/**
* Value object for health status
*/
public final class Status {
/**
* Indicates that the component or subsystem is in an unknown state
*/
public static final Status UNKNOWN = new Status("UNKNOWN");
/**
* Indicates that the component or subsystem is functioning as expected
*/
public static final Status UP = new Status("UP");
/**
* Indicates that the component or subsystem has suffered an unexpected failure
*/
public static final Status DOWN = new Status("DOWN");
/**
* Indicates that the component or subsystem is out of service temporarily
*/
public static final Status OUT_OF_SERVICE = new Status("OUT_OF_SERVICE");
/**
* Create a new status with the given code
* @param code the status code
*/
public Status(String code) { /* ... */ }
/**
* Return the status code
* @return the status code
*/
public String getCode() { /* ... */ }
}Base class that provides common exception handling for health indicators.
/**
* Base HealthIndicator that encapsulates creation of Health instances
* and common exception handling
*/
public abstract class AbstractHealthIndicator implements HealthIndicator {
/**
* Create a new AbstractHealthIndicator
*/
protected AbstractHealthIndicator() { /* ... */ }
/**
* Create a new AbstractHealthIndicator with a custom description
* @param description the description for health check failures
*/
protected AbstractHealthIndicator(String description) { /* ... */ }
@Override
public final Health health() { /* ... */ }
/**
* Actual health check logic. If an exception is thrown the
* health status will be DOWN
* @param builder the Health builder to populate
* @throws Exception if health check fails
*/
protected abstract void doHealthCheck(Health.Builder builder) throws Exception;
}Marker interface for health contributors that can be registered dynamically.
/**
* Marker interface for health contributors
*/
public interface HealthContributor {
// Marker interface - no methods
}Groups multiple health contributors together for hierarchical health reporting.
/**
* A HealthContributor that is composed of other HealthContributors
*/
public interface CompositeHealthContributor extends HealthContributor,
NamedContributors<HealthContributor> {
/**
* Create a composite health contributor from a map of contributors
* @param contributors the contributors
* @return the composite health contributor
*/
static CompositeHealthContributor fromMap(Map<String, HealthContributor> contributors) {
return new DefaultCompositeHealthContributor(contributors);
}
}Registry for dynamically managing health contributors at runtime.
/**
* A registry for health contributors
*/
public interface HealthContributorRegistry extends HealthContributor {
/**
* Register a health contributor
* @param name the name of the contributor
* @param contributor the contributor
*/
void registerContributor(String name, HealthContributor contributor);
/**
* Unregister a health contributor
* @param name the name of the contributor
* @return the unregistered contributor or null
*/
HealthContributor unregisterContributor(String name);
/**
* Get a health contributor by name
* @param name the name of the contributor
* @return the contributor or null if not found
*/
HealthContributor getContributor(String name);
}Simple health indicator that always returns UP status.
/**
* A HealthIndicator that always returns UP
*/
public class PingHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up().build();
}
}Health indicators that report application availability states.
/**
* A HealthIndicator that reports liveness availability state
*/
public class LivenessStateHealthIndicator implements HealthIndicator {
public LivenessStateHealthIndicator(ApplicationAvailability applicationAvailability) { /* ... */ }
@Override
public Health health() { /* ... */ }
}
/**
* A HealthIndicator that reports readiness availability state
*/
public class ReadinessStateHealthIndicator implements HealthIndicator {
public ReadinessStateHealthIndicator(ApplicationAvailability applicationAvailability) { /* ... */ }
@Override
public Health health() { /* ... */ }
}
/**
* Base class for availability state health indicators
*/
public abstract class AvailabilityStateHealthIndicator implements HealthIndicator {
protected AvailabilityStateHealthIndicator(ApplicationAvailability applicationAvailability,
AvailabilityState failureState,
String statusMappingProperty) { /* ... */ }
}@Component
public class DatabaseHealthIndicator extends AbstractHealthIndicator {
private final DatabaseService databaseService;
public DatabaseHealthIndicator(DatabaseService databaseService) {
this.databaseService = databaseService;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
if (databaseService.isConnected()) {
builder.up()
.withDetail("database", "operational")
.withDetail("connections", databaseService.getActiveConnections());
} else {
builder.down()
.withDetail("database", "connection failed")
.withDetail("error", "Unable to connect to database");
}
}
}@Component
public class ExternalServiceHealthIndicator implements ReactiveHealthIndicator {
private final WebClient webClient;
public ExternalServiceHealthIndicator(WebClient webClient) {
this.webClient = webClient;
}
@Override
public Mono<Health> health() {
return webClient.get()
.uri("/health")
.retrieve()
.toBodilessEntity()
.map(response -> Health.up()
.withDetail("service", "available")
.withDetail("status", response.getStatusCode().value())
.build())
.onErrorReturn(Health.down()
.withDetail("service", "unavailable")
.build());
}
}@Component
public class DynamicHealthManager {
private final HealthContributorRegistry healthRegistry;
public DynamicHealthManager(HealthContributorRegistry healthRegistry) {
this.healthRegistry = healthRegistry;
}
public void addServiceHealthCheck(String serviceName, HealthIndicator indicator) {
healthRegistry.registerContributor(serviceName, indicator);
}
public void removeServiceHealthCheck(String serviceName) {
healthRegistry.unregisterContributor(serviceName);
}
}public class CustomHealthIndicator implements HealthIndicator {
public static final Status DEGRADED = new Status("DEGRADED");
@Override
public Health health() {
// Custom business logic to determine health
if (isFullyOperational()) {
return Health.up().build();
} else if (isPartiallyOperational()) {
return Health.status(DEGRADED)
.withDetail("mode", "degraded")
.withDetail("availableFeatures", getAvailableFeatures())
.build();
} else {
return Health.down()
.withDetail("reason", "all services unavailable")
.build();
}
}
}Health system behavior can be configured through application properties:
# Show health details
management.endpoint.health.show-details=always
management.endpoint.health.show-components=always
# Configure health groups
management.endpoint.health.group.custom.include=db,redis,external
management.endpoint.health.group.custom.show-details=when-authorized
# Configure health indicator order
management.health.status.order=DOWN,OUT_OF_SERVICE,UNKNOWN,UP,DEGRADED
# Disable specific health indicators
management.health.ping.enabled=false
# Configure slow indicator threshold
management.endpoint.health.logging.slow-indicator-threshold=10sInstall with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-actuator