diff --git a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTracker.java b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTracker.java
index 4b7befce5..d7ee62730 100644
--- a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTracker.java
+++ b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTracker.java
@@ -20,6 +20,12 @@
import io.prometheus.client.Counter;
import io.prometheus.client.Histogram;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.*;
+import static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.REGISTERED;
+
/**
* Alternative Prometheus metrics tracker using a Histogram instead of Summary
*
@@ -56,12 +62,19 @@ private static Histogram registerHistogram(String name, String help, double buck
.create();
}
+ private final static Map registrationStatuses = new ConcurrentHashMap<>();
+
+ private final String poolName;
+ private final HikariCPCollector hikariCPCollector;
+
private final Histogram.Child elapsedAcquiredHistogramChild;
private final Histogram.Child elapsedBorrowedHistogramChild;
private final Histogram.Child elapsedCreationHistogramChild;
- PrometheusHistogramMetricsTracker(String poolName, CollectorRegistry collectorRegistry) {
+ PrometheusHistogramMetricsTracker(String poolName, CollectorRegistry collectorRegistry, HikariCPCollector hikariCPCollector) {
registerMetrics(collectorRegistry);
+ this.poolName = poolName;
+ this.hikariCPCollector = hikariCPCollector;
this.connectionTimeoutCounterChild = CONNECTION_TIMEOUT_COUNTER.labels(poolName);
this.elapsedAcquiredHistogramChild = ELAPSED_ACQUIRED_HISTOGRAM.labels(poolName);
this.elapsedBorrowedHistogramChild = ELAPSED_BORROWED_HISTOGRAM.labels(poolName);
@@ -69,10 +82,12 @@ private static Histogram registerHistogram(String name, String help, double buck
}
private void registerMetrics(CollectorRegistry collectorRegistry) {
- CONNECTION_TIMEOUT_COUNTER.register(collectorRegistry);
- ELAPSED_ACQUIRED_HISTOGRAM.register(collectorRegistry);
- ELAPSED_BORROWED_HISTOGRAM.register(collectorRegistry);
- ELAPSED_CREATION_HISTOGRAM.register(collectorRegistry);
+ if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {
+ CONNECTION_TIMEOUT_COUNTER.register(collectorRegistry);
+ ELAPSED_ACQUIRED_HISTOGRAM.register(collectorRegistry);
+ ELAPSED_BORROWED_HISTOGRAM.register(collectorRegistry);
+ ELAPSED_CREATION_HISTOGRAM.register(collectorRegistry);
+ }
}
@Override
@@ -94,4 +109,13 @@ public void recordConnectionCreatedMillis(long connectionCreatedMillis) {
public void recordConnectionTimeout() {
connectionTimeoutCounterChild.inc();
}
+
+ @Override
+ public void close() {
+ hikariCPCollector.remove(poolName);
+ CONNECTION_TIMEOUT_COUNTER.remove(poolName);
+ ELAPSED_ACQUIRED_HISTOGRAM.remove(poolName);
+ ELAPSED_BORROWED_HISTOGRAM.remove(poolName);
+ ELAPSED_CREATION_HISTOGRAM.remove(poolName);
+ }
}
diff --git a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactory.java b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactory.java
index 6ace160f8..612b4b2ce 100644
--- a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactory.java
+++ b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactory.java
@@ -19,8 +19,15 @@
import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
import com.zaxxer.hikari.metrics.PoolStats;
+import com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus;
+import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.*;
+
/**
* {@code
* HikariConfig config = new HikariConfig();
@@ -29,16 +36,18 @@
*/
public class PrometheusHistogramMetricsTrackerFactory implements MetricsTrackerFactory {
- private HikariCPCollector collector;
+ private final static Map registrationStatuses = new ConcurrentHashMap<>();
+
+ private final HikariCPCollector collector = new HikariCPCollector();
- private CollectorRegistry collectorRegistry;
+ private final CollectorRegistry collectorRegistry;
/**
* Default Constructor. The Hikari metrics are registered to the default
* collector registry ({@code CollectorRegistry.defaultRegistry}).
*/
public PrometheusHistogramMetricsTrackerFactory() {
- this.collectorRegistry = CollectorRegistry.defaultRegistry;
+ this(CollectorRegistry.defaultRegistry);
}
/**
@@ -51,17 +60,14 @@ public PrometheusHistogramMetricsTrackerFactory(CollectorRegistry collectorRegis
@Override
public IMetricsTracker create(String poolName, PoolStats poolStats) {
- getCollector().add(poolName, poolStats);
- return new PrometheusHistogramMetricsTracker(poolName, this.collectorRegistry);
+ registerCollector(this.collector, this.collectorRegistry);
+ this.collector.add(poolName, poolStats);
+ return new PrometheusHistogramMetricsTracker(poolName, this.collectorRegistry, this.collector);
}
- /**
- * initialize and register collector if it isn't initialized yet
- */
- private HikariCPCollector getCollector() {
- if (collector == null) {
- collector = new HikariCPCollector().register(this.collectorRegistry);
+ private void registerCollector(Collector collector, CollectorRegistry collectorRegistry) {
+ if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {
+ collector.register(collectorRegistry);
}
- return collector;
}
}
diff --git a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactory.java b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactory.java
index f0dbb6c30..f24ec3595 100644
--- a/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactory.java
+++ b/src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactory.java
@@ -49,9 +49,9 @@ public class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory
private final CollectorRegistry collectorRegistry;
- public enum RegistrationStatus
+ enum RegistrationStatus
{
- REGISTERED;
+ REGISTERED
}
/**
diff --git a/src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerTest.java b/src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerTest.java
index 418c317b0..e26940742 100644
--- a/src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerTest.java
+++ b/src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerTest.java
@@ -32,24 +32,26 @@
public class PrometheusHistogramMetricsTrackerTest {
- private CollectorRegistry collectorRegistry;
+ private CollectorRegistry defaultCollectorRegistry;
+ private CollectorRegistry customCollectorRegistry;
private static final String POOL_LABEL_NAME = "pool";
+ private static final String[] LABEL_NAMES = {POOL_LABEL_NAME};
@Before
- public void setupCollectorRegistry(){
- this.collectorRegistry = new CollectorRegistry();
+ public void setupCollectorRegistry() {
+ this.defaultCollectorRegistry = new CollectorRegistry();
+ this.customCollectorRegistry = new CollectorRegistry();
}
@Test
public void recordConnectionTimeout() throws Exception {
HikariConfig config = newHikariConfig();
- config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(collectorRegistry));
+ config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));
config.setJdbcUrl("jdbc:h2:mem:");
config.setMaximumPoolSize(2);
config.setConnectionTimeout(250);
- String[] labelNames = {POOL_LABEL_NAME};
String[] labelValues = {config.getPoolName()};
try (HikariDataSource hikariDataSource = new HikariDataSource(config)) {
@@ -60,9 +62,9 @@ public void recordConnectionTimeout() throws Exception {
}
}
- Double total = collectorRegistry.getSampleValue(
+ Double total = defaultCollectorRegistry.getSampleValue(
"hikaricp_connection_timeout_total",
- labelNames,
+ LABEL_NAMES,
labelValues
);
assertThat(total, is(1.0));
@@ -85,57 +87,87 @@ public void connectionCreationMetrics() {
}
@Test
- public void testMultiplePoolName() throws Exception {
- String[] labelNames = {POOL_LABEL_NAME};
-
- HikariConfig config = newHikariConfig();
- config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(collectorRegistry));
- config.setPoolName("first");
- config.setJdbcUrl("jdbc:h2:mem:");
- config.setMaximumPoolSize(2);
- config.setConnectionTimeout(250);
- String[] labelValues1 = {config.getPoolName()};
+ public void testMultiplePoolNameWithOneCollectorRegistry()
+ {
+ HikariConfig configFirstPool = newHikariConfig();
+ configFirstPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));
+ configFirstPool.setPoolName("first");
+ configFirstPool.setJdbcUrl("jdbc:h2:mem:");
+ configFirstPool.setMaximumPoolSize(2);
+ configFirstPool.setConnectionTimeout(250);
+
+ HikariConfig configSecondPool = newHikariConfig();
+ configSecondPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));
+ configSecondPool.setPoolName("second");
+ configSecondPool.setJdbcUrl("jdbc:h2:mem:");
+ configSecondPool.setMaximumPoolSize(4);
+ configSecondPool.setConnectionTimeout(250);
+
+ String[] labelValuesFirstPool = {configFirstPool.getPoolName()};
+ String[] labelValuesSecondPool = {configSecondPool.getPoolName()};
+
+ try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {
+ assertThat(defaultCollectorRegistry.getSampleValue(
+ "hikaricp_connection_timeout_total", LABEL_NAMES, labelValuesFirstPool),
+ is(0.0));
+
+ try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {
+ assertThat(defaultCollectorRegistry.getSampleValue(
+ "hikaricp_connection_timeout_total", LABEL_NAMES, labelValuesSecondPool),
+ is(0.0));
+ }
+ }
+ }
- try (HikariDataSource ignored = new HikariDataSource(config)) {
- assertThat(collectorRegistry.getSampleValue(
- "hikaricp_connection_timeout_total",
- labelNames,
- labelValues1), is(0.0));
-
- CollectorRegistry collectorRegistry2 = new CollectorRegistry();
- HikariConfig config2 = newHikariConfig();
- config2.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(collectorRegistry2));
- config2.setPoolName("second");
- config2.setJdbcUrl("jdbc:h2:mem:");
- config2.setMaximumPoolSize(4);
- config2.setConnectionTimeout(250);
- String[] labelValues2 = {config2.getPoolName()};
-
- try (HikariDataSource ignored2 = new HikariDataSource(config2)) {
- assertThat(collectorRegistry2.getSampleValue(
- "hikaricp_connection_timeout_total",
- labelNames,
- labelValues2), is(0.0));
+ @Test
+ public void testMultiplePoolNameWithDifferentCollectorRegistries()
+ {
+ HikariConfig configFirstPool = newHikariConfig();
+ configFirstPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));
+ configFirstPool.setPoolName("first");
+ configFirstPool.setJdbcUrl("jdbc:h2:mem:");
+ configFirstPool.setMaximumPoolSize(2);
+ configFirstPool.setConnectionTimeout(250);
+
+ HikariConfig configSecondPool = newHikariConfig();
+ configSecondPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(customCollectorRegistry));
+ configSecondPool.setPoolName("second");
+ configSecondPool.setJdbcUrl("jdbc:h2:mem:");
+ configSecondPool.setMaximumPoolSize(4);
+ configSecondPool.setConnectionTimeout(250);
+
+ String[] labelValuesFirstPool = {configFirstPool.getPoolName()};
+ String[] labelValuesSecondPool = {configSecondPool.getPoolName()};
+
+ try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {
+ assertThat(defaultCollectorRegistry.getSampleValue(
+ "hikaricp_connection_timeout_total", LABEL_NAMES, labelValuesFirstPool),
+ is(0.0));
+
+ try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {
+ assertThat(customCollectorRegistry.getSampleValue(
+ "hikaricp_connection_timeout_total", LABEL_NAMES, labelValuesSecondPool),
+ is(0.0));
}
}
}
private void checkSummaryMetricFamily(String metricName) {
HikariConfig config = newHikariConfig();
- config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(collectorRegistry));
+ config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));
config.setJdbcUrl("jdbc:h2:mem:");
try (HikariDataSource ignored = new HikariDataSource(config)) {
- Double count = collectorRegistry.getSampleValue(
+ Double count = defaultCollectorRegistry.getSampleValue(
metricName + "_count",
- new String[]{POOL_LABEL_NAME},
+ LABEL_NAMES,
new String[]{config.getPoolName()}
);
assertNotNull(count);
- Double sum = collectorRegistry.getSampleValue(
+ Double sum = defaultCollectorRegistry.getSampleValue(
metricName + "_sum",
- new String[]{POOL_LABEL_NAME},
+ LABEL_NAMES,
new String[]{config.getPoolName()}
);
assertNotNull(sum);