This problem causing hikariDataSource return null
because target.isInterface()
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration.HikariDataSourceMetricsConfiguration.bindMetricsRegistryToHikariDataSources(Collection)
@Autowired
void bindMetricsRegistryToHikariDataSources(Collection dataSources) {
for (DataSource dataSource : dataSources) {
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class);
if (hikariDataSource != null) {
bindMetricsRegistryToHikariDataSource(hikariDataSource);
}
}
}
Comment From: ifrozenice
yes, in 2.3.7Version, there is no hikaricp metrics in actuator/prometheus endpoint。 in2.3.4Version, it's work well。
Comment From: philwebb
@ankeway Can you provide some more details about your setup, or even better a sample application that replicates the issue. I'd like to know the DataSource class that gets passed to the unwrap method.
Comment From: ankeway
@ankeway Can you provide some more details about your setup, or even better a sample application that replicates the issue. I'd like to know the
DataSourceclass that gets passed to theunwrapmethod.
The most simple example that use HikariDataSource and Request actuator/prometheus endpoint Both oracle and mysql, can not get the related data of DataSource HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class); because hikariDataSource return null; you can debug org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration.HikariDataSourceMetricsConfiguration class, bindMetricsRegistryToHikariDataSources method Spring Boot 2.3.6 don't have this problem, The only difference is target.isInterface()
Comment From: snicoll
The most simple example that use HikariDataSource and Request actuator/prometheus endpoint
@ankeway unfortunately, that doesn't help. We're asking for a sample because we have several tests that exercise this scenario and they pass. As Phil has requested, can you please share a sample that showcases the problem? You can do so by attaching a zip to this issue or share a link to a GitHub repository.
Comment From: ankeway
The most simple example that use HikariDataSource and Request actuator/prometheus endpoint
@ankeway unfortunately, that doesn't help. We're asking for a sample because we have several tests that exercise this scenario and they pass. As Phil has requested, can you please share a sample that showcases the problem? You can do so by attaching a zip to this issue or share a link to a GitHub repository.
https://github.com/ankeway/DsDemo.git
if add such as javamelody-spring-boot-starter , dataSource will become net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler or like JdkDynamicAopProxy io.opentracing.contrib.spring.cloud.jdbc.JdbcAspect. a dynamic proxy, so try to safeUnwrap JdbcWrapper or JdkDynamicAopProxy and all of them are not a isInterface but spring boot 2.3.4, don't have target.isInterface(), DataSourceUnwrapper.unwrap(JdbcWrapper, DynamicRoutingDataSource.class) return DynamicRoutingDataSource; spring boot 2.3.7 DataSourceUnwrapper.unwrap(JdbcWrapper, DynamicRoutingDataSource.class) return null; I have to use custome DynamicRoutingDataSourceUnwrapper solve this problem
thanks
Comment From: snicoll
@ankeway thanks for the sample although it does not reproduce the problem for me. The reference to net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler is helping though.
Comment From: snicoll
We discussed this one today with two options:
- Try to unwrap
HikariConfigMXBeanrather as it may expose everything that we need. - Handle the Oracle case explicitly and revert the interface check
If the first option works we'd have to report an issue against the HikariCP project to suggest an interface to be offered by the project for datasource unwrap needs like this one.
Comment From: oburgosm
But with the new implementation, call to DataSourceUnwrapper.unwrap with a class, for example DataSourceUnwrapper.unwrap(myds, AtomikosDataSourceBean.class), always return null.
As workaround I can call DataSourceUnwrapper.unwrap(myds, DataSource.class, AtomikosDataSourceBean.class), but I think it's a bug.
Comment From: wilkinsona
Unfortunately, the contract for Wrapper.unwrap(Class<?>) states that the argument must be an interface. Prior to the change made in #24200 we were not adhering to the contract which caused problems with some DataSource implementations.
Using DataSourceUnwrapper.unwrap(DataSource, Class<I>, Class<T>) isn't a workaround and is what you should do when you want the result of unwrap to be a class rather than an interface. For Atomikos, I would call unwrap(myds, ConnectionPoolProperties.class, AtomikosDataSourceBean.class). This uses Atomikos's ConnectionPoolProperties interface to do the unwrapping and then casts it to AtomikosDataSourceBean.
Comment From: baogutang
you can use instead of org.springframework.boot.jdbc.DataSourceUnwrapper#unwrap(javax.sql.DataSource, java.lang.Class, java.lang.Class
Comment From: baogutang
you can use instead of org.springframework.boot.jdbc.DataSourceUnwrapper#unwrap(javax.sql.DataSource, java.lang.Class, java.lang.Class),it works!
for example: HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariConfigMXBean.class, HikariDataSource.class);