3838import org .apache .commons .dbcp2 .PoolableConnection ;
3939import org .apache .commons .dbcp2 .PoolableConnectionFactory ;
4040import org .apache .commons .dbcp2 .PoolingDataSource ;
41+ import org .apache .commons .lang3 .BooleanUtils ;
4142import org .apache .commons .lang3 .ObjectUtils ;
4243import org .apache .commons .lang3 .StringUtils ;
4344import org .apache .commons .pool2 .ObjectPool ;
@@ -1065,6 +1066,8 @@ public static void initDataSource(Properties dbProps) {
10651066 final Integer cloudMinIdleConnections = parseNumber (dbProps .getProperty ("db.cloud.minIdleConnections" ), Integer .class );
10661067 final Long cloudConnectionTimeout = parseNumber (dbProps .getProperty ("db.cloud.connectionTimeout" ), Long .class );
10671068 final Long cloudKeepAliveTimeout = parseNumber (dbProps .getProperty ("db.cloud.keepAliveTime" ), Long .class );
1069+ final Long cloudLeakDetectionThreshold = parseNumber (dbProps .getProperty ("db.cloud.leakDetectionThreshold" ), Long .class );
1070+ final Boolean cloudRegisterMbeans = BooleanUtils .toBooleanObject (dbProps .getProperty ("db.cloud.registerMbeans" ));
10681071 final String cloudUsername = dbProps .getProperty ("db.cloud.username" );
10691072 final String cloudPassword = dbProps .getProperty ("db.cloud.password" );
10701073 final String cloudValidationQuery = dbProps .getProperty ("db.cloud.validationQuery" );
@@ -1107,7 +1110,7 @@ public static void initDataSource(Properties dbProps) {
11071110 cloudUsername , cloudPassword , cloudMaxActive , cloudMaxIdle , cloudMaxWait ,
11081111 cloudTimeBtwEvictionRunsMillis , cloudMinEvcitableIdleTimeMillis , cloudTestWhileIdle ,
11091112 cloudTestOnBorrow , cloudValidationQuery , cloudMinIdleConnections , cloudConnectionTimeout ,
1110- cloudKeepAliveTimeout , isolationLevel , "cloud" );
1113+ cloudKeepAliveTimeout , cloudLeakDetectionThreshold , cloudRegisterMbeans , isolationLevel , "cloud" );
11111114
11121115 // Configure the usage db
11131116 final Integer usageMaxActive = parseNumber (dbProps .getProperty ("db.usage.maxActive" ), Integer .class );
@@ -1116,6 +1119,8 @@ public static void initDataSource(Properties dbProps) {
11161119 final Integer usageMinIdleConnections = parseNumber (dbProps .getProperty ("db.usage.minIdleConnections" ), Integer .class );
11171120 final Long usageConnectionTimeout = parseNumber (dbProps .getProperty ("db.usage.connectionTimeout" ), Long .class );
11181121 final Long usageKeepAliveTimeout = parseNumber (dbProps .getProperty ("db.usage.keepAliveTime" ), Long .class );
1122+ final Long usageLeakDetectionThreshold = parseNumber (dbProps .getProperty ("db.usage.leakDetectionThreshold" ), Long .class );
1123+ final Boolean usageRegisterMbeans = BooleanUtils .toBooleanObject (dbProps .getProperty ("db.usage.registerMbeans" ));
11191124 final String usageUsername = dbProps .getProperty ("db.usage.username" );
11201125 final String usagePassword = dbProps .getProperty ("db.usage.password" );
11211126
@@ -1127,7 +1132,8 @@ public static void initDataSource(Properties dbProps) {
11271132 s_usageDS = createDataSource (dbProps .getProperty ("db.usage.connectionPoolLib" ), usageUriAndDriver .first (),
11281133 usageUsername , usagePassword , usageMaxActive , usageMaxIdle , usageMaxWait , null ,
11291134 null , null , null , null ,
1130- usageMinIdleConnections , usageConnectionTimeout , usageKeepAliveTimeout , isolationLevel , "usage" );
1135+ usageMinIdleConnections , usageConnectionTimeout , usageKeepAliveTimeout , usageLeakDetectionThreshold ,
1136+ usageRegisterMbeans , isolationLevel , "usage" );
11311137
11321138 try {
11331139 // Configure the simulator db
@@ -1137,6 +1143,8 @@ public static void initDataSource(Properties dbProps) {
11371143 final Integer simulatorMinIdleConnections = parseNumber (dbProps .getProperty ("db.simulator.minIdleConnections" ), Integer .class );
11381144 final Long simulatorConnectionTimeout = parseNumber (dbProps .getProperty ("db.simulator.connectionTimeout" ), Long .class );
11391145 final Long simulatorKeepAliveTimeout = parseNumber (dbProps .getProperty ("db.simulator.keepAliveTime" ), Long .class );
1146+ final Long simulatorLeakDetectionThreshold = parseNumber (dbProps .getProperty ("db.simulator.leakDetectionThreshold" ), Long .class );
1147+ final Boolean simulatorRegisterMbeans = BooleanUtils .toBooleanObject (dbProps .getProperty ("db.simulator.registerMbeans" ));
11401148 final String simulatorUsername = dbProps .getProperty ("db.simulator.username" );
11411149 final String simulatorPassword = dbProps .getProperty ("db.simulator.password" );
11421150
@@ -1167,7 +1175,8 @@ public static void initDataSource(Properties dbProps) {
11671175 simulatorConnectionUri , simulatorUsername , simulatorPassword , simulatorMaxActive ,
11681176 simulatorMaxIdle , simulatorMaxWait , null , null , null , null ,
11691177 cloudValidationQuery , simulatorMinIdleConnections , simulatorConnectionTimeout ,
1170- simulatorKeepAliveTimeout , isolationLevel , "simulator" );
1178+ simulatorKeepAliveTimeout , simulatorLeakDetectionThreshold , simulatorRegisterMbeans ,
1179+ isolationLevel , "simulator" );
11711180 } catch (Exception e ) {
11721181 LOGGER .debug ("Simulator DB properties are not available. Not initializing simulator DS" );
11731182 }
@@ -1269,20 +1278,22 @@ protected static String buildConnectionUri(String loadBalanceStrategy, String dr
12691278 private static DataSource createDataSource (String connectionPoolLib , String uri , String username , String password ,
12701279 Integer maxActive , Integer maxIdle , Long maxWait , Long timeBtwnEvictionRuns , Long minEvictableIdleTime ,
12711280 Boolean testWhileIdle , Boolean testOnBorrow , String validationQuery , Integer minIdleConnections ,
1272- Long connectionTimeout , Long keepAliveTime , Integer isolationLevel , String dsName ) {
1281+ Long connectionTimeout , Long keepAliveTime , Long leakDetectionThreshold , Boolean registerMbeans ,
1282+ Integer isolationLevel , String dsName ) {
12731283 LOGGER .debug ("Creating datasource for database: {} with connection pool lib: {}" , dsName ,
12741284 connectionPoolLib );
12751285 if (CONNECTION_POOL_LIB_DBCP .equals (connectionPoolLib )) {
12761286 return createDbcpDataSource (uri , username , password , maxActive , maxIdle , maxWait , timeBtwnEvictionRuns ,
12771287 minEvictableIdleTime , testWhileIdle , testOnBorrow , validationQuery , isolationLevel );
12781288 }
12791289 return createHikaricpDataSource (uri , username , password , maxActive , maxIdle , maxWait , minIdleConnections ,
1280- connectionTimeout , keepAliveTime , isolationLevel , dsName );
1290+ connectionTimeout , keepAliveTime , leakDetectionThreshold , registerMbeans , isolationLevel , dsName );
12811291 }
12821292
12831293 private static DataSource createHikaricpDataSource (String uri , String username , String password ,
12841294 Integer maxActive , Integer maxIdle , Long maxWait ,
12851295 Integer minIdleConnections , Long connectionTimeout , Long keepAliveTime ,
1296+ Long leakDetectionThreshold , Boolean registerMbeans ,
12861297 Integer isolationLevel , String dsName ) {
12871298 HikariConfig config = new HikariConfig ();
12881299 config .setJdbcUrl (uri );
@@ -1299,6 +1310,8 @@ private static DataSource createHikaricpDataSource(String uri, String username,
12991310 config .setConnectionTimeout (ObjectUtils .defaultIfNull (connectionTimeout , 30000L ));
13001311 config .setKeepaliveTime (ObjectUtils .defaultIfNull (keepAliveTime , 600000L ));
13011312
1313+ applyHikariDebugSettings (config , leakDetectionThreshold , registerMbeans , dsName );
1314+
13021315 String isolationLevelString = "TRANSACTION_READ_COMMITTED" ;
13031316 if (isolationLevel == Connection .TRANSACTION_SERIALIZABLE ) {
13041317 isolationLevelString = "TRANSACTION_SERIALIZABLE" ;
@@ -1326,6 +1339,21 @@ private static DataSource createHikaricpDataSource(String uri, String username,
13261339 return dataSource ;
13271340 }
13281341
1342+ /**
1343+ * Applies optional HikariCP debugging aids (leak detection and JMX MBeans). Both are disabled by
1344+ * default; leakDetectionThreshold is only applied when set to a positive value (HikariCP treats 0
1345+ * as disabled and ignores values below 2000ms). Package-private for unit testing.
1346+ */
1347+ static void applyHikariDebugSettings (HikariConfig config , Long leakDetectionThreshold , Boolean registerMbeans , String dsName ) {
1348+ if (leakDetectionThreshold != null && leakDetectionThreshold > 0 ) {
1349+ config .setLeakDetectionThreshold (leakDetectionThreshold );
1350+ }
1351+ config .setRegisterMbeans (ObjectUtils .defaultIfNull (registerMbeans , false ));
1352+ LOGGER .debug ("HikariCP pool {}: leakDetectionThreshold={} ms, registerMbeans={}" , dsName ,
1353+ ObjectUtils .defaultIfNull (leakDetectionThreshold , 0L ),
1354+ ObjectUtils .defaultIfNull (registerMbeans , false ));
1355+ }
1356+
13291357 private static DataSource createDbcpDataSource (String uri , String username , String password ,
13301358 Integer maxActive , Integer maxIdle , Long maxWait ,
13311359 Long timeBtwnEvictionRuns , Long minEvictableIdleTime ,
0 commit comments