Stop DataSource initialization from preventing Hikari instrumentation

Closes gh-12129
pull/12156/head
Andy Wilkinson 7 years ago
parent 33be78a91e
commit e7176c63f5

@ -19,9 +19,12 @@ package org.springframework.boot.actuate.autoconfigure.metrics.jdbc;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory; import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory;
import io.micrometer.core.instrument.MeterRegistry; 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.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
/** /**
* {@link BeanPostProcessor} that configures Hikari metrics. Such arrangement is necessary * {@link BeanPostProcessor} that configures Hikari metrics. Such arrangement is necessary
@ -30,7 +33,10 @@ import org.springframework.context.ApplicationContext;
* *
* @author Stephane Nicoll * @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; private final ApplicationContext context;
@ -53,9 +59,14 @@ class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor {
HikariDataSource dataSource) { HikariDataSource dataSource) {
if (dataSource.getMetricRegistry() == null if (dataSource.getMetricRegistry() == null
&& dataSource.getMetricsTrackerFactory() == null) { && dataSource.getMetricsTrackerFactory() == null) {
try {
dataSource.setMetricsTrackerFactory( dataSource.setMetricsTrackerFactory(
new MicrometerMetricsTrackerFactory(registry)); new MicrometerMetricsTrackerFactory(registry));
} }
catch (Exception ex) {
logger.warn("Failed to bind Hikari metrics: " + ex.getMessage());
}
}
} }
private MeterRegistry getMeterRegistry() { private MeterRegistry getMeterRegistry() {
@ -65,4 +76,9 @@ class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor {
return this.meterRegistry; return this.meterRegistry;
} }
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
} }

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.autoconfigure.metrics.jdbc; package org.springframework.boot.actuate.autoconfigure.metrics.jdbc;
import java.sql.SQLException;
import java.util.UUID; import java.util.UUID;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -26,6 +27,8 @@ import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Test; 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.actuate.autoconfigure.metrics.test.MetricsRun;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 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.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import static org.assertj.core.api.Assertions.assertThat; 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 @Test
public void hikariDataSourceInstrumentationCanBeDisabled() { public void hikariDataSourceInstrumentationCanBeDisabled() {
this.contextRunner.withPropertyValues("management.metrics.enable.hikaricp=false") 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;
}
}
}
} }

@ -33,11 +33,9 @@ import org.springframework.core.Ordered;
*/ */
class DataSourceInitializerPostProcessor implements BeanPostProcessor, Ordered { class DataSourceInitializerPostProcessor implements BeanPostProcessor, Ordered {
private int order = Ordered.HIGHEST_PRECEDENCE;
@Override @Override
public int getOrder() { public int getOrder() {
return this.order; return Ordered.HIGHEST_PRECEDENCE + 1;
} }
@Autowired @Autowired

Loading…
Cancel
Save