Spring Boot HealthIndicator by Example

11,359

Solution 1

1) You can have as much health indicators as you like. Just create beans which will extend org.springframework.boot.actuate.health.HealthIndicator and they will be automatically picked up by actuator's healthcheck endpoint. The name of your bean will be the name of certain health indicator. In your example myHealthCheck and diskSpace are beans in spring context that were called when you hit /health. diskSpace is one of predefined health indicators in spring boot comming from org.springframework.boot.actuate.health.DiskSpaceHealthIndicator.

2) top level status is accumulative state of all your health indicators. You can configure the way how it works but by default it'll show the lowest state (you have one of health indicators in DOWN state so accumulative state shown as DOWN)

Solution 2

You can implement several HealthIndicators and they will all contribute to the final overall value of UP or DOWN. The final value is an aggregate of all other values (determined by a StatusAggregator).

Example 1 (Healthy)

@Component
public class ExampleOneHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
      // do something to check health

      // inspect the return 

      // healthy
      return Health.up().build();
    }
}

Example 2 (Unhealthy)

@Component
public class ExampleTwoHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
      // do something to check health

      // inspect the return 

      // unhealthy
      return Health.down().build();
    }
}

Example 3 (Unhealthy with details)

@Component
public class ExampleThreeHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
      // do something to check health

      // inspect the return 

      // unhealthy with details
      return Health.down()
                .withDetail("reason", "details about why it failed")
                .build();
    }
}

With the above three examples and the management.endpoint.health.show-details set to always (in the application.properties), you'd get the following result when calling /actuator/health.

{
    "status": "DOWN",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 1000240963584,
                "free": 880857858048,
                "threshold": 10485760
            }
        },
        "exampleOne": {
            "status": "UP"
        },
        "exampleThree": {
            "status": "DOWN",
            "details": {
                "reason": "details about why it failed"
            }
        },
        "exampleTwo": {
            "status": "DOWN"
        },
        "ping": {
            "status": "UP"
        }
    }
}

The names in the response are the class name (camel-cased) before HealthIndicator (e.g. ExampleOneHealthIndicator --> exampleOne)

The other names (such as diskSpace or ping) come from the built in health checks and the class names are named just as you'd expect (DiskSpaceHealthIndicator & PingHealthIndicator)

Note that the top-level status is DOWN. This is determined by the StatusAggregator. The default one is https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/actuate/health/SimpleStatusAggregator.html

Example code

https://github.com/dustinschultz/spring-boot-actuator-custom-health-checks

Share:
11,359
smeeb
Author by

smeeb

Updated on June 23, 2022

Comments

  • smeeb
    smeeb almost 2 years

    I am looking to build a robust and detailed health check endpoint (/health) on my Spring Boot REST service. I just read this excellent Baeldung article on the subject but still have a few concerns.

    Ideally my /health endpoint would be able to take into account the individual health of ALL my subsystems (10+ of them) including the health of the host (CPU, disk utilization, available memory, etc.).

    I can't tell whether Spring Boot expects you to build one-and-only one HealthIndicator impl. Or if the idea is to build one HealthIndicator impl for each major subsystem (each of which can be independently "up" or "down" respectively.

    Also, in that Baeldung example, what is the difference between the top-level status and the myHealthCheck.status and where do each of them come from (in the code)?

    {
        "status" : "DOWN",
        "myHealthCheck" : {
            "status" : "DOWN",
            "Error Code" : 1,
            "Description" : "You custom MyHealthCheck endpoint is down"
         },
         "diskSpace" : {
             "status" : "UP",
             "free" : 209047318528,
             "threshold" : 10485760
         }
    }
    

    And where does diskSpace come from?!

  • smeeb
    smeeb over 6 years
    Awesome thanks @SimY4 (+1) - how do I configure the top level status myself? I understand the default is to take the lowest state of all the health indicator, but in my particular case I have some custom logic for determining overall health (some HealthIndicators can be down and the service may still be considered to be "up", etc.). Any ideas? Thanks again!
  • SimY4
    SimY4 over 6 years
    @smeeb you have to provide your own org.springframework.boot.actuate.health.HealthAggregator bean that will produce accumulative state for your health indicators, or play with your custom statuses. Like, you can introduce your own status SEEMS_OK or ALMOST and put them in order with others using management.health.status.order= property