31
votes
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

This will add several useful endpoints to your application. One of them is /health. When you start your application and navigate to the /health endpoint you will see it returns already some data.

{
    "status":"UP",
    "diskSpace": {
        "status":"UP",
        "free":56443746,
        "threshold":1345660
    }
}

How to add a custom health check in spring boot health?

4

4 Answers

37
votes

Adding a custom health check is easy. Just create a new Java class, extend it from the AbstractHealthIndicator and implement the doHealthCheck method. The method gets a builder passed with some useful methods. Call builder.up() if your health is OK or builder.down() if it is not. What you do to check the health is completely up to you. Maybe you want to ping some server or check some files.

@Component
public class CustomHealthCheck extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder bldr) throws Exception {
        // TODO implement some check
        boolean running = true;
        if (running) {
          bldr.up();
        } else {
          bldr.down();
        }
    }
}

This is enough to activate the new health check (make sure @ComponentScan is on your application). Restart your application and locate your browser to the /health endpoint and you will see the newly added health check.

{
    "status":"UP",
    "CustomHealthCheck": {
        "status":"UP"
    },
    "diskSpace": {
        "status":"UP",
        "free":56443746,
        "threshold":1345660
    }
}
18
votes

Since Spring Boot 2.X

As stated by @yuranos87 the actuator concept has changed in Spring Boot 2.X but you can still add custom health checks easily by implementing HealthIndicator or for reactive applications ReactiveHealthIndicator:

@Component
public class CacheHealthIndicator implements HealthIndicator {

@Override
public Health health() {
    long result = checkSomething();
    if (result <= 0) {
        return Health.down().withDetail("Something Result", result).build();
    }
    return Health.up().build();      
  }
}

or

@Component
public class CacheHealthIndicator implements ReactiveHealthIndicator {

@Override
public Mono<Health> health() {
    return Mono.fromCallable(() -> checkSomething())
        .map(result -> {
            if (result <= 0) {
                return Health.down().withDetail("Something Result", result).build();
            }
            return Health.up().build();
        });
   }
}

Additionally you can add or extend any endpoint with @Endpointor @EndpointWebExtension. Endpoints here are info, health and many more. So you can add custom health check by using @Endpoint but it is much easier to do with HealthIndicator.

You can find more information about custom health checks and custom endpoints in the spring boot documentation.

8
votes

Spring Boot 2.X has significantly changed actuator. A new, better mechanism to extend existing endpoints is enabled via @EndpointWebExtension.

That being said, health endpoint is a bit trickier to extend because one extension for it is provided out of the box by actuator itself. Without manipulating beans initialization process, your application will not be able to start since it will see 2 extensions and will not understand which one to choose. An easier way would be to use info instead and extend it:

@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
   @Value("${info.build.version}")
   private String versionNumber;
   @Value("${git.commit.id}")
   private String gitCommit;
   @Value("${info.build.name}")
   private String applicationName;
   ...
   @ReadOperation
   public WebEndpointResponse<Map> info() {

Don't forget that you can also re-map URLs. In my case I prefer /status to /health and don't want /actuator/ in the path:

management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.info=status

Another reason why I prefer /info is because I don't get this nested structure, which is default for /health:

{
"status": {
    "status": "ON",
0
votes

If you want to have custom status message then You can check answer here - https://stackoverflow.com/a/66985769/4952800