
com.foryouandyourcustomers.health.CustomHealthIndicator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of health-check Show documentation
Show all versions of health-check Show documentation
The main goal of this module is to enable the creation of health checks as a tool for testing the
application in run time.
The newest version!
package com.foryouandyourcustomers.health;
import static com.foryouandyourcustomers.health.HealthCheckType.LARGE;
import static com.foryouandyourcustomers.health.HealthCheckType.MEDIUM;
import static com.foryouandyourcustomers.health.HealthCheckType.ONCE;
import static com.foryouandyourcustomers.health.HealthCheckType.SHORT;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class CustomHealthIndicator
implements HealthIndicator,
ApplicationContextAware,
ApplicationListener {
private ConcurrentMap healthStatus;
private List runOnlyOnceMethods;
private List shortScheduledMethods;
private List mediumScheduledMethods;
private List largeScheduledMethods;
private ApplicationContext applicationContext;
@Value("${health.check.basepackage}")
public String healthCheckPackage;
@Override
public Health health() {
Health.Builder builder = new Health.Builder();
this.healthStatus.keySet().forEach(key -> builder.withDetail(key, this.healthStatus.get(key)));
HealthDescription other = new HealthDescription();
other.setUp(true);
HealthDescription description =
healthStatus.values().stream().filter(v -> !v.isUp()).findFirst().orElse(other);
if (!description.isUp()) {
return builder.down().build();
}
return builder.up().build();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
this.healthStatus = Maps.newConcurrentMap();
if (Strings.isNullOrEmpty(healthCheckPackage)) {
healthCheckPackage = "";
}
Reflections reflections =
new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage(healthCheckPackage))
.setScanners(new MethodAnnotationsScanner()));
Set methods = reflections.getMethodsAnnotatedWith(HealthCheck.class);
methods.forEach(
method -> {
HealthDescription description = new HealthDescription();
description.setMethodName(method.getName());
healthStatus.put(method.getName(), description);
});
runOnlyOnceMethods = getMethods(methods, ONCE);
shortScheduledMethods = getMethods(methods, SHORT);
mediumScheduledMethods = getMethods(methods, MEDIUM);
largeScheduledMethods = getMethods(methods, LARGE);
}
@Scheduled(fixedDelayString = "${health.check.schedule.short}")
public void runShortScheduledCheckTests() {
executeMethods(shortScheduledMethods);
}
@Scheduled(fixedDelayString = "${health.check.schedule.medium}")
public void runMediumScheduledCheckTests() {
executeMethods(mediumScheduledMethods);
}
@Scheduled(fixedDelayString = "${health.check.schedule.large}")
public void runLargeScheduledCheckTests() {
executeMethods(largeScheduledMethods);
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
executeMethods(runOnlyOnceMethods);
runShortScheduledCheckTests();
runMediumScheduledCheckTests();
runLargeScheduledCheckTests();
}
/**
* Execute the methods one at the time and adds the result to health status.
* @param methods List of methods to execute
*/
private void executeMethods(List methods) {
methods.forEach(
method -> {
HealthDescription healthDescription = healthStatus.get(method.getName());
healthDescription.setLastStart(new Date());
try {
Object userData = method.invoke(applicationContext.getBean(method.getDeclaringClass()));
String description =
userData != null ? new ObjectMapper().writeValueAsString(userData) : "";
healthStatus.put(
method.getName(), setDescription(healthDescription, true, "UP", description));
} catch (Exception e) {
healthStatus.put(
method.getName(),
setDescription(healthDescription, false, "DOWN", e.getCause().getMessage()));
}
});
}
private HealthDescription setDescription(
HealthDescription healthDescription, boolean up, String status, String description) {
healthDescription.setUp(up);
Date lastStart = healthDescription.getLastStart();
healthDescription.setRunDuration(new Date().getTime() - lastStart.getTime());
healthDescription.setStatus(status);
healthDescription.setDescription(description);
return healthDescription;
}
private List getMethods(Set methods, HealthCheckType type) {
return methods
.stream()
.filter(method -> method.getAnnotation(HealthCheck.class).type().equals(type))
.collect(Collectors.toList());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy