diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jdbc/DataSourcePoolMetrics.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jdbc/DataSourcePoolMetrics.java index 1e3676c4129..df75e70d1aa 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jdbc/DataSourcePoolMetrics.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jdbc/DataSourcePoolMetrics.java @@ -38,6 +38,7 @@ import org.springframework.util.ConcurrentReferenceHashMap; * * @author Jon Schneider * @author Phillip Webb + * @author Artsiom Yudovin * @since 2.0.0 */ public class DataSourcePoolMetrics implements MeterBinder { @@ -68,6 +69,7 @@ public class DataSourcePoolMetrics implements MeterBinder { bindPoolMetadata(registry, "active", DataSourcePoolMetadata::getActive); bindPoolMetadata(registry, "max", DataSourcePoolMetadata::getMax); bindPoolMetadata(registry, "min", DataSourcePoolMetadata::getMin); + bindPoolMetadata(registry, "idle", DataSourcePoolMetadata::getIdle); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/CommonsDbcp2DataSourcePoolMetadata.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/CommonsDbcp2DataSourcePoolMetadata.java index ca1508fc8b9..bd18ab32908 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/CommonsDbcp2DataSourcePoolMetadata.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/CommonsDbcp2DataSourcePoolMetadata.java @@ -24,6 +24,7 @@ import org.apache.commons.dbcp2.BasicDataSource; * {@link DataSourcePoolMetadata} for an Apache Commons DBCP2 {@link DataSource}. * * @author Stephane Nicoll + * @author Artsiom Yudovin * @since 2.0.0 */ public class CommonsDbcp2DataSourcePoolMetadata extends AbstractDataSourcePoolMetadata { @@ -57,4 +58,9 @@ public class CommonsDbcp2DataSourcePoolMetadata extends AbstractDataSourcePoolMe return getDataSource().getDefaultAutoCommit(); } + @Override + public Integer getIdle() { + return getDataSource().getNumIdle(); + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/DataSourcePoolMetadata.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/DataSourcePoolMetadata.java index d0e7028dbc9..a591fb63dba 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/DataSourcePoolMetadata.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/DataSourcePoolMetadata.java @@ -23,6 +23,7 @@ import javax.sql.DataSource; * {@link DataSource} implementations. * * @author Stephane Nicoll + * @author Artsiom Yudovin * @since 2.0.0 */ public interface DataSourcePoolMetadata { @@ -49,6 +50,16 @@ public interface DataSourcePoolMetadata { */ Integer getActive(); + /** + * Return the number of established but idle connections. Can also return {@code null} + * if that information is not available. + * @return the number of established but idle connections or {@code null} + * @since 2.2.0 + */ + default Integer getIdle() { + return null; + } + /** * Return the maximum number of active connections that can be allocated at the same * time or {@code -1} if there is no limit. Can also return {@code null} if that diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadata.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadata.java index bd9b1f93f3c..088f03c2016 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadata.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadata.java @@ -16,6 +16,8 @@ package org.springframework.boot.jdbc.metadata; +import java.util.Objects; + import javax.sql.DataSource; import com.zaxxer.hikari.HikariDataSource; @@ -27,6 +29,7 @@ import org.springframework.beans.DirectFieldAccessor; * {@link DataSourcePoolMetadata} for a Hikari {@link DataSource}. * * @author Stephane Nicoll + * @author Artsiom Yudovin * @since 2.0.0 */ public class HikariDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata { @@ -45,6 +48,16 @@ public class HikariDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata } } + @Override + public Integer getIdle() { + HikariPool pool = getHikariPool(); + if (Objects.nonNull(pool)) { + return pool.getIdleConnections(); + } + + return null; + } + private HikariPool getHikariPool() { return (HikariPool) new DirectFieldAccessor(getDataSource()).getPropertyValue("pool"); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadata.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadata.java index 4202315a5cb..dc6db942764 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadata.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadata.java @@ -23,6 +23,7 @@ import org.apache.tomcat.jdbc.pool.DataSource; * {@link DataSourcePoolMetadata} for a Tomcat DataSource. * * @author Stephane Nicoll + * @author Artsiom Yudovin * @since 2.0.0 */ public class TomcatDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata { @@ -57,4 +58,9 @@ public class TomcatDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata return getDataSource().isDefaultAutoCommit(); } + @Override + public Integer getIdle() { + return getDataSource().getNumIdle(); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/AbstractDataSourcePoolMetadataTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/AbstractDataSourcePoolMetadataTests.java index 5f43bf056b4..b53701ab1c0 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/AbstractDataSourcePoolMetadataTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/AbstractDataSourcePoolMetadataTests.java @@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @param the data source pool metadata type * @author Stephane Nicoll + * @author Artsiom Yudovin */ abstract class AbstractDataSourcePoolMetadataTests> { @@ -67,6 +68,11 @@ abstract class AbstractDataSourcePoolMetadataTests) (connection) -> null); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadataTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadataTests.java index 70d91b248d4..77a8a1e5a1d 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadataTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/HikariDataSourcePoolMetadataTests.java @@ -18,12 +18,16 @@ package org.springframework.boot.jdbc.metadata; import com.zaxxer.hikari.HikariDataSource; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.JdbcTemplate; + import static org.assertj.core.api.Assertions.assertThat; /** * Tests for {@link HikariDataSourcePoolMetadata}. * * @author Stephane Nicoll + * @author Artsiom Yudovin */ public class HikariDataSourcePoolMetadataTests extends AbstractDataSourcePoolMetadataTests { @@ -54,7 +58,15 @@ public class HikariDataSourcePoolMetadataTests HikariDataSource dataSource = initializeBuilder().type(HikariDataSource.class).build(); dataSource.setMinimumIdle(minSize); dataSource.setMaximumPoolSize(maxSize); + + this.initPool(dataSource); + return dataSource; } + private void initPool(HikariDataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.execute((ConnectionCallback) (connection) -> null); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadataTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadataTests.java index ca642b639fa..fe4e3a5771e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadataTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/TomcatDataSourcePoolMetadataTests.java @@ -18,6 +18,9 @@ package org.springframework.boot.jdbc.metadata; import org.apache.tomcat.jdbc.pool.DataSource; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.JdbcTemplate; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -58,7 +61,15 @@ public class TomcatDataSourcePoolMetadataTests // Avoid warnings dataSource.setInitialSize(minSize); dataSource.setMaxIdle(maxSize); + + this.initPool(dataSource); + return dataSource; } + private void initPool(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.execute((ConnectionCallback) (connection) -> null); + } + }