diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/HikariDataSourceMetricsPostProcessor.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/HikariDataSourceMetricsPostProcessor.java index d3898b3d0d..07a6439c2f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/HikariDataSourceMetricsPostProcessor.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/HikariDataSourceMetricsPostProcessor.java @@ -19,9 +19,12 @@ package org.springframework.boot.actuate.autoconfigure.metrics.jdbc; import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory; import io.micrometer.core.instrument.MeterRegistry; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; +import org.springframework.core.Ordered; /** * {@link BeanPostProcessor} that configures Hikari metrics. Such arrangement is necessary @@ -30,7 +33,10 @@ import org.springframework.context.ApplicationContext; * * @author Stephane Nicoll */ -class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor { +class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor, Ordered { + + private static final Log logger = LogFactory + .getLog(HikariDataSourceMetricsPostProcessor.class); private final ApplicationContext context; @@ -53,8 +59,13 @@ class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor { HikariDataSource dataSource) { if (dataSource.getMetricRegistry() == null && dataSource.getMetricsTrackerFactory() == null) { - dataSource.setMetricsTrackerFactory( - new MicrometerMetricsTrackerFactory(registry)); + try { + dataSource.setMetricsTrackerFactory( + new MicrometerMetricsTrackerFactory(registry)); + } + catch (Exception ex) { + logger.warn("Failed to bind Hikari metrics: " + ex.getMessage()); + } } } @@ -65,4 +76,9 @@ class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor { return this.meterRegistry; } + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfigurationTests.java index 94a864b057..10eef4d7c6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfigurationTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.jdbc; +import java.sql.SQLException; import java.util.UUID; import javax.sql.DataSource; @@ -26,6 +27,8 @@ import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.junit.Test; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @@ -33,6 +36,8 @@ import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; import static org.assertj.core.api.Assertions.assertThat; @@ -96,6 +101,29 @@ public class DataSourcePoolMetricsAutoConfigurationTests { }); } + @Test + public void autoConfiguredHikariDataSourceIsInstrumentedWhenUsingDataSourceInitialization() { + this.contextRunner + .withPropertyValues( + "spring.datasource.schema:db/create-custom-schema.sql") + .run((context) -> { + context.getBean(DataSource.class).getConnection(); + MeterRegistry registry = context.getBean(MeterRegistry.class); + registry.get("hikaricp.connections").meter(); + }); + } + + @Test + public void failureToInstrumentHikariDataSourceIsTolerated() { + this.contextRunner.withUserConfiguration(HikariSealingConfiguration.class) + .run((context) -> { + assertThat(context).hasNotFailed(); + context.getBean(DataSource.class).getConnection(); + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry.find("hikaricp.connections").meter()).isNull(); + }); + } + @Test public void hikariDataSourceInstrumentationCanBeDisabled() { this.contextRunner.withPropertyValues("management.metrics.enable.hikaricp=false") @@ -215,4 +243,37 @@ public class DataSourcePoolMetricsAutoConfigurationTests { } + @Configuration + static class HikariSealingConfiguration { + + @Bean + public static HikariSealer hikariSealer() { + return new HikariSealer(); + } + + static class HikariSealer implements BeanPostProcessor, PriorityOrdered { + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof HikariDataSource) { + try { + ((HikariDataSource) bean).getConnection().close(); + } + catch (SQLException ex) { + throw new IllegalStateException(ex); + } + } + return bean; + } + + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerPostProcessor.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerPostProcessor.java index 92426b2008..1f0c239d72 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerPostProcessor.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerPostProcessor.java @@ -33,11 +33,9 @@ import org.springframework.core.Ordered; */ class DataSourceInitializerPostProcessor implements BeanPostProcessor, Ordered { - private int order = Ordered.HIGHEST_PRECEDENCE; - @Override public int getOrder() { - return this.order; + return Ordered.HIGHEST_PRECEDENCE + 1; } @Autowired