Skip to content

Commit 2cbeb1d

Browse files
committed
Apply metrics and health check to all DataSources
Before this commit, non default and autowire candidate DataSources are not applied. Closes spring-projectsGH-43481 Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
1 parent ea89e18 commit 2cbeb1d

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import javax.sql.DataSource;
2828

2929
import org.springframework.beans.factory.InitializingBean;
30+
import org.springframework.beans.factory.ListableBeanFactory;
3031
import org.springframework.beans.factory.ObjectProvider;
3132
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
3233
import org.springframework.boot.actuate.health.CompositeHealthContributor;
@@ -59,6 +60,7 @@
5960
* @author Arthur Kalimullin
6061
* @author Julio Gomez
6162
* @author Safeer Ansari
63+
* @author Yanming Zhou
6264
* @since 2.0.0
6365
*/
6466
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@@ -84,8 +86,9 @@ public void afterPropertiesSet() {
8486

8587
@Bean
8688
@ConditionalOnMissingBean(name = { "dbHealthIndicator", "dbHealthContributor" })
87-
public HealthContributor dbHealthContributor(Map<String, DataSource> dataSources,
89+
public HealthContributor dbHealthContributor(ListableBeanFactory beanFactory,
8890
DataSourceHealthIndicatorProperties dataSourceHealthIndicatorProperties) {
91+
Map<String, DataSource> dataSources = beanFactory.getBeansOfType(DataSource.class, false, false);
8992
if (dataSourceHealthIndicatorProperties.isIgnoreRoutingDataSources()) {
9093
Map<String, DataSource> filteredDatasources = dataSources.entrySet()
9194
.stream()

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.apache.commons.logging.Log;
3232
import org.apache.commons.logging.LogFactory;
3333

34+
import org.springframework.beans.factory.ListableBeanFactory;
3435
import org.springframework.beans.factory.ObjectProvider;
3536
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
3637
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
@@ -52,6 +53,7 @@
5253
* {@link DataSource datasources}.
5354
*
5455
* @author Stephane Nicoll
56+
* @author Yanming Zhou
5557
* @since 2.0.0
5658
*/
5759
@AutoConfiguration(after = { MetricsAutoConfiguration.class, DataSourceAutoConfiguration.class,
@@ -67,8 +69,9 @@ static class DataSourcePoolMetadataMetricsConfiguration {
6769
private static final String DATASOURCE_SUFFIX = "dataSource";
6870

6971
@Bean
70-
DataSourcePoolMetadataMeterBinder dataSourcePoolMetadataMeterBinder(Map<String, DataSource> dataSources,
72+
DataSourcePoolMetadataMeterBinder dataSourcePoolMetadataMeterBinder(ListableBeanFactory beanFactory,
7173
ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders) {
74+
Map<String, DataSource> dataSources = beanFactory.getBeansOfType(DataSource.class, false, false);
7275
return new DataSourcePoolMetadataMeterBinder(dataSources, metadataProviders);
7376
}
7477

@@ -120,17 +123,17 @@ private String getDataSourceName(String beanName) {
120123
static class HikariDataSourceMetricsConfiguration {
121124

122125
@Bean
123-
HikariDataSourceMeterBinder hikariDataSourceMeterBinder(ObjectProvider<DataSource> dataSources) {
124-
return new HikariDataSourceMeterBinder(dataSources);
126+
HikariDataSourceMeterBinder hikariDataSourceMeterBinder(ListableBeanFactory beanFactory) {
127+
return new HikariDataSourceMeterBinder(beanFactory.getBeansOfType(DataSource.class).values());
125128
}
126129

127130
static class HikariDataSourceMeterBinder implements MeterBinder {
128131

129132
private static final Log logger = LogFactory.getLog(HikariDataSourceMeterBinder.class);
130133

131-
private final ObjectProvider<DataSource> dataSources;
134+
private final Collection<DataSource> dataSources;
132135

133-
HikariDataSourceMeterBinder(ObjectProvider<DataSource> dataSources) {
136+
HikariDataSourceMeterBinder(Collection<DataSource> dataSources) {
134137
this.dataSources = dataSources;
135138
}
136139

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfigurationTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.sql.SQLException;
2020
import java.util.HashMap;
2121
import java.util.Map;
22+
import java.util.UUID;
2223

2324
import javax.sql.DataSource;
2425

@@ -53,6 +54,7 @@
5354
* @author Phillip Webb
5455
* @author Julio Gomez
5556
* @author Safeer Ansari
57+
* @author Yanming Zhou
5658
*/
5759
class DataSourceHealthContributorAutoConfigurationTests {
5860

@@ -211,6 +213,16 @@ void runWhenDataSourceHasNullRoutingKeyShouldProduceUnnamedComposedIndicator() {
211213
});
212214
}
213215

216+
@Test
217+
void runWhenAdditionalDataSourceBeansShouldCreateCompositeIndicator() {
218+
this.contextRunner.withUserConfiguration(AdditionalDataSourceConfig.class).run((context) -> {
219+
assertThat(context).hasSingleBean(CompositeHealthContributor.class);
220+
CompositeHealthContributor contributor = context.getBean(CompositeHealthContributor.class);
221+
String[] names = contributor.stream().map(NamedContributor::getName).toArray(String[]::new);
222+
assertThat(names).containsExactlyInAnyOrder("dataSource", "additionalDataSource");
223+
});
224+
}
225+
214226
@Configuration(proxyBeanMethods = false)
215227
@EnableConfigurationProperties
216228
static class DataSourceConfig {
@@ -245,6 +257,22 @@ AbstractRoutingDataSource routingDataSource() throws SQLException {
245257

246258
}
247259

260+
@Configuration(proxyBeanMethods = false)
261+
@EnableConfigurationProperties
262+
static class AdditionalDataSourceConfig {
263+
264+
@Bean(defaultCandidate = false)
265+
DataSource additionalDataSource() {
266+
return DataSourceBuilder.create()
267+
.type(org.apache.tomcat.jdbc.pool.DataSource.class)
268+
.driverClassName("org.hsqldb.jdbc.JDBCDriver")
269+
.url("jdbc:hsqldb:mem:test-" + UUID.randomUUID())
270+
.username("sa")
271+
.build();
272+
}
273+
274+
}
275+
248276
static class ProxyDataSourceBeanPostProcessor implements BeanPostProcessor {
249277

250278
@Override

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfigurationTests.java

+25
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* @author Stephane Nicoll
5252
* @author Andy Wilkinson
5353
* @author Tommy Ludwig
54+
* @author Yanming Zhou
5455
*/
5556
class DataSourcePoolMetricsAutoConfigurationTests {
5657

@@ -219,6 +220,20 @@ void hikariDataSourceIsInstrumentedWithoutMetadataProvider() {
219220
});
220221
}
221222

223+
@Test
224+
void additionalHikariDataSourcesCanBeInstrumented() {
225+
this.contextRunner.withUserConfiguration(AdditionalHikariDataSourceConfiguration.class)
226+
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
227+
.run((context) -> {
228+
assertThat(context).getBeanNames(DataSource.class)
229+
.containsExactlyInAnyOrder("dataSource", "additionalHikariDataSource");
230+
context.getBean("additionalHikariDataSource", DataSource.class).getConnection();
231+
MeterRegistry registry = context.getBean(MeterRegistry.class);
232+
assertThat(registry.get("hikaricp.connections").meter().getId().getTags())
233+
.containsExactly(Tag.of("pool", "additionalHikariDataSource"));
234+
});
235+
}
236+
222237
private static HikariDataSource createHikariDataSource(String poolName) {
223238
String url = "jdbc:hsqldb:mem:test-" + UUID.randomUUID();
224239
HikariDataSource hikariDataSource = DataSourceBuilder.create().url(url).type(HikariDataSource.class).build();
@@ -271,6 +286,16 @@ DataSource secondOne() {
271286

272287
}
273288

289+
@Configuration(proxyBeanMethods = false)
290+
static class AdditionalHikariDataSourceConfiguration {
291+
292+
@Bean(defaultCandidate = false)
293+
DataSource additionalHikariDataSource() {
294+
return createHikariDataSource("additionalHikariDataSource");
295+
}
296+
297+
}
298+
274299
@Configuration(proxyBeanMethods = false)
275300
static class ProxiedHikariDataSourcesConfiguration {
276301

0 commit comments

Comments
 (0)