Spring Boot Actuator Custom Health Check Tutorial

  • 2021-11-02 00:55:11
  • OfStack

Health check is one of the important endpoints in Spring Boot Actuator, which makes it easy to see the running status of the application. This article introduces how to customize health check on the basis of the previous article.

1. Overview

In this section, we briefly explain the dependency and enable configuration and show the default health information. First, you need to introduce dependencies:


compile("org.springframework.boot:spring-boot-starter-actuator")

Now validate with the http://localhost: 8080/actuator/health endpoint:


{"status":"UP"}

By default, this endpoint returns summary health information for many components in the application, but you can modify the property configuration to show the details:


management:
  endpoint:
    health:
      show-details: always

Now visit again and return the following results:


{
  "status": "UP",
  "components": {
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 214748360704,
        "free": 112483500032,
        "threshold": 10485760,
        "exists": true
      }
    },
    "ping": {
      "status": "UP"
    }
  }
}

View the source code of DiskSpaceHealthIndicatorProperties file:


@ConfigurationProperties(prefix = "management.health.diskspace")
public class DiskSpaceHealthIndicatorProperties {
 /**
  * Path used to compute the available disk space.
  */
 private File path = new File(".");
 /**
  * Minimum disk space that should be available.
  */
 private DataSize threshold = DataSize.ofMegabytes(10);
 public File getPath() {
  return this.path;
 }
 public void setPath(File path) {
  this.path = path;
 }
 public DataSize getThreshold() {
  return this.threshold;
 }
 public void setThreshold(DataSize threshold) {
  Assert.isTrue(!threshold.isNegative(), "threshold must be greater than or equal to 0");
  this.threshold = threshold;
 }
}

The above results show the current project startup path. The alarm value is 10M, and these properties can be modified by configuration.

2. Predefined health metrics

The above Json response shows "ping" and "diskSpace" checks. These tests are also called health indicators, and if the application references the data source, Spring will increase db health indicators; At the same time, "diskSpace" is the default configuration.

Spring Boot includes many predefined health indicators, one of which is listed below:

DataSourceHealthIndicator MongoHealthIndicator Neo4jHealthIndicator CassandraHealthIndicator RedisHealthIndicator CassandraHealthIndicator RabbitHealthIndicator CouchbaseHealthIndicator DiskSpaceHealthIndicator (See the example above.) ElasticsearchHealthIndicator MongoHealthIndicator0 JmsHealthIndicator MailHealthIndicator SolrHealthIndicator

If Mongo or Solr is used in Spring Boot application, Spring Boot will automatically increase the corresponding health index.

3. Customize your health metrics

Spring Boot provides a bundle of predefined health indicators, but it doesn't stop you from increasing your own health indicators. 1 There are two custom type checks:

Individual health indicator components and combined health indicator components.

3.1 Customizing the Single Metrics Component

Customization requires implementing the HealthIndicator interface and re-establishing the health () method with the @ Component annotation. Suppose the sample application communicates with service A (start) and service B (shut down). If any 1 service goes down, the application will be considered to be down. Therefore, we will write two health indicators.


@Component
public class ServiceAHealthIndicator implements HealthIndicator {
    private final String message_key = "Service A";
    @Override
    public Health health() {
        if (!isRunningServiceA()) {
            return Health.down().withDetail(message_key, "Not Available").build();
        }
        return Health.up().withDetail(message_key, "Available").build();
    }
    private Boolean isRunningServiceA() {
        Boolean isRunning = true;
        // Logic Skipped
        return isRunning;
    }
}

@Component
public class ServiceBHealthIndicator implements HealthIndicator {
    private final String message_key = "Service B";
    @Override
    public Health health() {
        if (!isRunningServiceB()) {
            return Health.down().withDetail(message_key, "Not Available").build();
        }
        return Health.up().withDetail(message_key, "Available").build();
    }
    private Boolean isRunningServiceB() {
        Boolean isRunning = false;
        // Logic Skipped
        return isRunning;
    }
}

Now, we see the added indicators in the health monitoring response. The ServerA status is UP, and ServiceB is DOWN, so the whole monitoring detection status is DOWN.


{
  "status": "DOWN",
  "components": {
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 214748360704,
        "free": 112483229696,
        "threshold": 10485760,
        "exists": true
      }
    },
    "ping": {
      "status": "UP"
    },
    "serviceA": {
      "status": "UP",
      "details": {
        "Service A": "Available"
      }
    },
    "serviceB": {
      "status": "DOWN",
      "details": {
        "Service B": "Not Available"
      }
    }
  }
}

3.2 Custom Combination Health Checks

The previous example makes it easy to see the status of each metric. But sometimes you need to see the status of a resource based on several metrics, and you need to use HealthContributor, which does not define methods and is used only for tags. If a service is implemented with a combination of two other actions, the service state is normal only if both work at the same time. Finally, use CompositeHealthContributors to combine multiple indicators:


public class ServiceAHealthIndicator 
    implements HealthIndicator, HealthContributor {
...
}

The following defines the combined health examination metrics:


@Component("UserServiceAPI")
public class UserServiceAPIHealthContributor 
    implements CompositeHealthContributor {
  
  private Map<String, HealthContributor> 
          contributors = new LinkedHashMap<>();
  @Autowired
  public UserServiceAPIHealthContributor(
      ServiceAHealthIndicator serviceAHealthIndicator, ServiceBHealthIndicator serviceBHealthIndicator) {
  
    contributors.put("serverA",  serviceAHealthIndicator);
    contributors.put("serverB", serviceBHealthIndicator);
  }
  /**
   *  return list of health contributors
   */
  @Override
  public Iterator<NamedContributor<HealthContributor>> iterator() {
    return contributors.entrySet().stream()
       .map((entry) -> NamedContributor.of(entry.getKey(), entry.getValue())).iterator();
  }
  
  @Override
  public HealthContributor getContributor(String name) {
    return contributors.get(name);
  }
}

Now we use serverA and serverB to combine the new check UserServiceAPI.

4. Summary

In this article, we learned about Spring Boot health indicators and related configurations, as well as predefined health indicators, and introduced how to customize health indicators.


Related articles: