Skip to content

Instantly share code, notes, and snippets.

@sterlp
Last active February 27, 2024 12:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sterlp/21e0355550b281923b420344abeea26a to your computer and use it in GitHub Desktop.
Save sterlp/21e0355550b281923b420344abeea26a to your computer and use it in GitHub Desktop.
Spring Boot HealthTemplate for Spring Actuator
public class HealthTemplate<T> implements HealthIndicator {
private final boolean resultAsValue;
private final Health.Builder health = Health.unknown();
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
private final AtomicInteger numberOfErrors = new AtomicInteger(0);
private final AtomicLong callDuration = new AtomicLong(0L);
public HealthTemplate() {
resultAsValue = false;
}
public HealthTemplate(String name) {
this(name, false);
}
public HealthTemplate(String name, boolean resultAsValue) {
health.withDetail("name", name);
this.resultAsValue = resultAsValue;
}
@Override
public Health health() {
final var count = numberOfExecutions.get();
health.withDetail("number_of_executions", count);
health.withDetail("number_of_errors", numberOfErrors.get());
health.withDetail("avg_execution_duration_ms", count > 0 ? (long)(callDuration.get() / count) : 0);
return health.build();
}
public T execute(Callable<T> toRun) {
long time = System.currentTimeMillis();
try {
final var result = toRun.call();
health.status(Status.UP);
if (resultAsValue) health.withDetail("value", result);
return result;
} catch (Exception e) {
numberOfErrors.incrementAndGet();
health.status(Status.DOWN);
health.withException(e);
throw sneakyThrow(e);
} finally {
time = System.currentTimeMillis() - time;
numberOfExecutions.incrementAndGet();
callDuration.addAndGet(time);
health.withDetail("last_execution_timestamp", OffsetDateTime.now());
health.withDetail("last_execution_duration_ms", time);
}
}
public HealthTemplate<T> withDetail(@NonNull String key, @NonNull Object value) {
health.withDetail(key, value);
return this;
}
public HealthTemplate<T> status(Status status) {
health.status(status);
return this;
}
@SuppressWarnings("unchecked")
private <E extends Throwable> E sneakyThrow(Throwable t) throws E {
throw (E)t;
}
}
@sterlp
Copy link
Author

sterlp commented Feb 19, 2024

public class FooService implements HealthIndicator {
    private final HealthTemplate<Long> healthTemplate = new HealthTemplate<>();
    
    public Long doBar() {
        return healthTemplate.execute(() -> {
             var result = runWrappedFoo();
             return result.size(); // return any value
         });
    }
    @Override
    public Health health() {
        return healthTemplate.health();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment