Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@

import java.util.function.Function;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* Base {@link HealthIndicator} implementations that encapsulates creation of
Expand All @@ -40,10 +36,6 @@ public abstract class AbstractHealthIndicator implements HealthIndicator {

private static final String NO_MESSAGE = null;

private static final String DEFAULT_MESSAGE = "Health check failed";

private final Log logger = LogFactory.getLog(getClass());

private final Function<Exception, String> healthCheckFailedMessage;

/**
Expand Down Expand Up @@ -84,17 +76,10 @@ public final Health health() {
catch (Exception ex) {
builder.down(ex);
}
logExceptionIfPresent(builder.getException());
HealthLogger.logExceptionIfPresent(builder.getException());
return builder.build();
}

private void logExceptionIfPresent(Throwable throwable) {
if (throwable != null && this.logger.isWarnEnabled()) {
String message = (throwable instanceof Exception ex) ? this.healthCheckFailedMessage.apply(ex) : null;
this.logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE, throwable);
}
}

/**
* Actual health check logic.
* @param builder the {@link Builder} to report health status and details
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@

import java.util.function.Function;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* Base {@link ReactiveHealthIndicator} implementations that encapsulates creation of
Expand All @@ -38,10 +35,6 @@ public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthI

private static final String NO_MESSAGE = null;

private static final String DEFAULT_MESSAGE = "Health check failed";

private final Log logger = LogFactory.getLog(getClass());

private final Function<Throwable, String> healthCheckFailedMessage;

/**
Expand Down Expand Up @@ -79,22 +72,15 @@ public final Mono<Health> health() {
try {
Health.Builder builder = new Health.Builder();
Mono<Health> result = doHealthCheck(builder).onErrorResume(this::handleFailure);
return result.doOnNext((health) -> logExceptionIfPresent(builder.getException()));
return result.doOnNext((health) -> HealthLogger.logExceptionIfPresent(builder.getException()));
}
catch (Exception ex) {
return handleFailure(ex);
}
}

private void logExceptionIfPresent(Throwable ex) {
if (ex != null && this.logger.isWarnEnabled()) {
String message = (ex instanceof Exception) ? this.healthCheckFailedMessage.apply(ex) : null;
this.logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE, ex);
}
}

private Mono<Health> handleFailure(Throwable ex) {
logExceptionIfPresent(ex);
HealthLogger.logExceptionIfPresent(ex);
return Mono.just(new Health.Builder().down(ex).build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public final class Health extends HealthComponent {

private final Map<String, Object> details;

private final Throwable exception;

/**
* Create a new {@link Health} instance with the specified status and details.
* @param builder the Builder to use
Expand All @@ -63,11 +65,13 @@ private Health(Builder builder) {
Assert.notNull(builder, "Builder must not be null");
this.status = builder.status;
this.details = Collections.unmodifiableMap(builder.details);
this.exception = builder.exception;
}

Health(Status status, Map<String, Object> details) {
this.status = status;
this.details = details;
this.exception = null;
}

/**
Expand All @@ -88,6 +92,14 @@ public Map<String, Object> getDetails() {
return this.details;
}

/**
* Return the exception of the health.
* @return the exception (or {@code null})
*/
public Throwable getException() {
return this.exception;
}

/**
* Return a new instance of this {@link Health} with all {@link #getDetails() details}
* removed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ private T getAggregateContribution(ApiVersion apiVersion, HealthEndpointGroup gr
private T getLoggedHealth(C contributor, String name, boolean showDetails) {
Instant start = Instant.now();
try {
return getHealth(contributor, showDetails);
T health = getHealth(contributor, showDetails);
HealthLogger.logExceptionIfPresent(health.getException());
return health;
}
finally {
if (logger.isWarnEnabled() && this.slowIndicatorLoggingThreshold != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.springframework.boot.actuate.health;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

public class HealthLogger {

private static final Log logger = LogFactory.getLog(HealthLogger.class);
private static final String DEFAULT_MESSAGE = "Health check failed";

public static void logExceptionIfPresent(Throwable throwable) {
if (throwable != null && logger.isWarnEnabled()) {
String message = (throwable instanceof Exception ex) ? ex.getMessage() : null;
logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE, throwable);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.springframework.boot.actuate.health;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(OutputCaptureExtension.class)
class HealthLoggerTests {

private static final Log logger = LogFactory.getLog(HealthLogger.class);

@Test
void logExceptionIfPresentShouldLogException(CapturedOutput output) {
Exception exception = new Exception("Test exception");
HealthLogger.logExceptionIfPresent(exception);
assertThat(output).contains("Test exception");
}

@Test
void logExceptionIfPresentShouldNotLogWhenNoException(CapturedOutput output) {
HealthLogger.logExceptionIfPresent(null);
assertThat(output).doesNotContain("Health check failed");
}

@Test
void logExceptionIfPresentShouldLogDefaultMessageWhenNoMessage(CapturedOutput output) {
Exception exception = new Exception();
HealthLogger.logExceptionIfPresent(exception);
assertThat(output).contains("Health check failed");
}
}