Spring Boot Actuators: Customise Health Endpoint
Tags: java, springboot, spring, monitoring
Published: 2023-07-22 11:38:30


In [last post](https://dev.to/manojshr/spring-boot-actuators-to-expose-operational-info-2aok), I talked about configuring and leveraging spring boot actuators to configure your boot application to have production ready features.

In this Post, let's customise **Health** endpoint, which is one of the important actuator endpoint, It helps in:
- **Monitoring Application Health**: The Health endpoint provides a simple and standardized way to monitor the health of your application. It allows you to quickly check whether your application is running correctly or encountering any issues. Monitoring the health status of your application helps you identify and respond to potential problems early, reducing downtime and ensuring a better user experience.
- **Proactive Issue Detection**: By regularly polling the Health endpoint, monitoring tools and systems can proactively detect any degradation or failure in your application's health. This enables your operations team to take immediate action before issues escalate and impact users.
- **Integration with Orchestration Tools**: In modern production environments, applications are often managed and orchestrated by tools like Kubernetes, Docker Swarm, or cloud platforms.
- **Operational Insights**: The Health endpoint provides essential information about your application's internals. You can customize the endpoint to include details about database connections, external service status, resource availability, and more. These details are valuable for troubleshooting and gaining insights into your application's behavior during runtime.

Spring Actuators provide rich API support to customize health endpoint response.

Let's first enable health endpoint from the configurations and allow it to show details:
```properties
management.endpoints.web.exposure.include=health
management.endpoint.health.show-details=always
```

**By default**, it exposes ping status and disk details:
```json
{
    "status": "UP",
    "components": {
        "diskSpace": {
            ...
            ...
            ...
        },
        "ping": {
            "status": "UP"
        }
    }
}
```
We can disable this default response by setting `management.health.defaults.enabled` property to `false`

### Customising Health endpoint by implementing HealthIndicator
Implementing the HealthIndicator interface allows you to create custom health indicators to monitor specific aspects of your application.

The `HealthIndicator` (package: org.springframework.boot.actuate.health) interface is part of the Spring Boot Actuator module, and it provides a single method, `health()`, that returns a `Health` object representing the health status of your custom indicator. It provides several static methods to create instances of Health, as well as to add additional details and contextual information about the health check.

Here are some commonly used static methods of the `Health` class:

> **up():** Creates a Health instance with an `UP` status, indicating that the application is in a healthy state.

> **down():** Creates a Health instance with a `DOWN` status.

> **unknown():** Creates a Health instance with an `UNKNOWN` status.

> **status(Status status):** Creates a Health instance with a custom status. The Status enum represents the health status, and it can be `UP, DOWN, or UNKNOWN`.

> **withDetail(String key, Object value):** Adds additional details to the Health instance. These details provide more information about the health status and can be useful for troubleshooting and monitoring.

> **withDetails(Map<String, Object> details):** Adds multiple details to the Health instance at once, using a Map of key-value pairs.


Let's now write an implementation of the `HealthIndicator` interface i.e. `ExternalServiceHealthIndicator.class`. It's a typical example, where I am returning a Health object based on HTTP statusCode received from external service call.
```java
@Component
public class ExternalServiceHealthIndicator implements HealthIndicator {

    private final Random randomizer = new Random();
    private final List<Integer> statusCodes = List.of(200, 204, 401, 404, 503);

    @Override
    public Health health() {
        int randomStatusCode = statusCodes.get(randomizer.nextInt(statusCodes.size()));
        Health.Builder healthBuilder = new Health.Builder();
        return (switch(randomStatusCode) {
            case 200, 204 -> healthBuilder.up()
                    .withDetail("External_Service", "Service is Up and Running ✅")
                    .withDetail("url", "https://example.com");
            case 503 -> healthBuilder.down()
                    .withDetail("External_Service", "Service is Down 🔻")
                    .withDetail("alternative_url", "https://alt-example.com");
            default -> healthBuilder.unknown().withException(new RuntimeException("Received status: " + randomStatusCode));
        }).build();
    }
}
```

### @ConditionalOnEnabledHealthIndicator annotation
@ConditionalOnEnabledHealthIndicator is a meta-annotation in ` org.springframework.boot.actuate.autoconfigure.health` package to conditionally enable or disable the health check provided by that specific indicator and requires `indicatorName` as a mandatory String argument which can be enabled with the externalised application configuration. Let's see an example in action.
```java
@Component
@ConditionalOnEnabledHealthIndicator("external_service_health")
public class ExternalServiceHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        ...
    }
}
```

The Custom indicator can be enabled/disabled by setting `management.health.<custom-indicator>.enabled` property true/false in the application's configuration. If the property is not present or set to false, the indicator will not be enabled.
```properties
management.health.external_service_health.enabled: true
```
### Final Words
Health Endpoint is a really useful endpoint to Monitor your Application health, get Operational insights, health check your deployments. Please share your thoughts/opinions in the comments.