Reputation: 65
Is there any way to make Spring Actuator perform health check periodically? I'm thinking, maybe, there's an option to have some Runnable in my custom implementation of HealthIndicator, but for me this idea doesn't look quite good. I want to check Cassandra and, if failed, perform some emergency actions
Upvotes: 5
Views: 9352
Reputation: 13235
You may just periodically invoke /health endpoint from some external monitoring system (like Nagios) and take appropriate action if response is not HTTP 200. If you make authenticated call to /health endpoint, then response body contains details what exactly failed (unauthenticated call has just HTTP response code).
Spring Actuator on its own is not meant to take any actions. It is meant just to be used by /health
endpoint.
But if you really want to extend that idea and take some actions on failed health checks, then have a look at source code of spring-boot actuator.
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cassandra
It contains implementation of every health check.
You may easily reuse them and write your own implementation that will invoke each HealthIndicator
periodically.
For details, please check how org.springframework.boot.actuate.health.HealthEndpoint
looks like.
You may do exactly same thing periodically.
Note that this may not be best idea. You will heavily depend on implementation details of particular version of actuator. After updating version of Sping Boot (they release new version often, and it is good idea to update because of security fixes and new fatures) your custom logic may does not compile, stop to work or work incorrectly.
Upvotes: 1
Reputation: 362
If you are using Spring Boot >= 2.2, you can use the separate library spring-boot-async-health-indicator to run your healthchecks periodically.
Simply annotate your HealthIndicator
with @AsyncHealth
(and potentially redefine the refreshRate
attribute to determine how often to run it).
Example:
@AsyncHealth
@Component
public class PeriodicalHealthCheck implements HealthIndicator {
@Override
public Health health() { //will be executed asynchronously
actualCheck();
return Health.up().build();
}
}
Disclaimer: I created this library for this exact purpose
Upvotes: 0
Reputation: 171
I came across this entry via googling since I was looking to periodically run the health check. Like mentioned in earlier post, you can invoke the health endpoint periodically from external monitoring system but say you want to use micrometer to send health metrics to external registry like NewRelic and you don't want to rely on external ping. Then you can use import org.springframework.boot.actuate.health.HealthEndpoint like as follows:
@Configuration
@EnableScheduling
public class HealthMetricsConfiguration {
private final String GAUGE_NAME = "gaugeName";
private AtomicInteger gauge;
private HealthEndpoint healthEndpoint;
public HealthMetricsConfiguration(MeterRegistry registry, HealthEndpoint healthEndpoint) {
this.healthEndpoint = healthEndpoint;
gauge = registry.gauge(GAUGE_NAME, new AtomicInteger());
gauge.set(getStatusCode(this.healthEndpoint));
}
private int getStatusCode(HealthEndpoint healthEndPoint) {
Status status = healthEndPoint.health().getStatus();
if(Status.OUT_OF_SERVICE.equals(status)) {
return 3;
}else if(Status.DOWN.equals(status)) {
return 2;
}else if(Status.UP.equals(status)) {
return 1;
}else {
return 0; //Status.UNKNOWN
}
}
@Scheduled(fixedDelayString = 60000, initialDelayString = 60000)
public void periodicRunSelfHealthCheck() {
gauge.set(getStatusCode(this.healthEndpoint));
}
}
The key is that healthEndpoint.health() will run your health check. The code runs a health check every minute.
Upvotes: 1