Add prometheus support (#632)
parent
7d1fb2ea3a
commit
76cf343c8b
@ -0,0 +1,39 @@
|
||||
package com.zaxxer.hikari.metrics.prometheus;
|
||||
|
||||
import com.zaxxer.hikari.metrics.PoolStats;
|
||||
import io.prometheus.client.Collector;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
class HikariCPCollector extends Collector {
|
||||
private final PoolStats poolStats;
|
||||
private final List<String> labelNames;
|
||||
private final List<String> labelValues;
|
||||
|
||||
HikariCPCollector(String poolName, PoolStats poolStats) {
|
||||
this.poolStats = poolStats;
|
||||
this.labelNames = Collections.singletonList("pool");
|
||||
this.labelValues = Collections.singletonList(poolName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricFamilySamples> collect() {
|
||||
return Arrays.asList(
|
||||
createSample("hikaricp_active_connections", "Active connections", poolStats.getActiveConnections()),
|
||||
createSample("hikaricp_idle_connections", "Idle connections", poolStats.getIdleConnections()),
|
||||
createSample("hikaricp_pending_threads", "Pending threads", poolStats.getPendingThreads()),
|
||||
createSample("hikaricp_connections", "The number of current connections", poolStats.getTotalConnections())
|
||||
);
|
||||
}
|
||||
|
||||
private MetricFamilySamples createSample(String name, String helpMessage, double value) {
|
||||
List<MetricFamilySamples.Sample> samples = Collections.singletonList(new MetricFamilySamples.Sample(name,
|
||||
labelNames,
|
||||
labelValues,
|
||||
value));
|
||||
|
||||
return new MetricFamilySamples(name, Type.GAUGE, helpMessage, samples);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.zaxxer.hikari.metrics.prometheus;
|
||||
|
||||
import com.zaxxer.hikari.metrics.MetricsTracker;
|
||||
import io.prometheus.client.Counter;
|
||||
import io.prometheus.client.Summary;
|
||||
|
||||
class PrometheusMetricsTracker extends MetricsTracker {
|
||||
private final Counter.Child connectionTimeoutCounter;
|
||||
private final Summary.Child elapsedAcquiredSummary;
|
||||
private final Summary.Child elapsedBorrowedSummary;
|
||||
|
||||
PrometheusMetricsTracker(String poolName) {
|
||||
super();
|
||||
|
||||
Counter counter = Counter.build()
|
||||
.name("hikaricp_connection_timeout_count")
|
||||
.labelNames("pool")
|
||||
.help("Connection timeout count")
|
||||
.register();
|
||||
|
||||
this.connectionTimeoutCounter = counter.labels(poolName);
|
||||
|
||||
Summary elapsedAcquiredSummary = Summary.build()
|
||||
.name("hikaricp_connection_acquired_nanos")
|
||||
.labelNames("pool")
|
||||
.help("Connection acquired time")
|
||||
.register();
|
||||
this.elapsedAcquiredSummary = elapsedAcquiredSummary.labels(poolName);
|
||||
|
||||
Summary elapsedBorrowedSummary = Summary.build()
|
||||
.name("hikaricp_connection_usage_millis")
|
||||
.labelNames("pool")
|
||||
.help("Connection usage")
|
||||
.register();
|
||||
this.elapsedBorrowedSummary = elapsedBorrowedSummary.labels(poolName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) {
|
||||
elapsedAcquiredSummary.observe(elapsedAcquiredNanos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordConnectionUsageMillis(long elapsedBorrowedMillis) {
|
||||
elapsedBorrowedSummary.observe(elapsedBorrowedMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordConnectionTimeout() {
|
||||
connectionTimeoutCounter.inc();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.zaxxer.hikari.metrics.prometheus;
|
||||
|
||||
import com.zaxxer.hikari.metrics.MetricsTracker;
|
||||
import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
|
||||
import com.zaxxer.hikari.metrics.PoolStats;
|
||||
|
||||
/**
|
||||
* <pre>{@code
|
||||
* HikariConfig config = new HikariConfig();
|
||||
* config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
* }</pre>
|
||||
*/
|
||||
public class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory {
|
||||
@Override
|
||||
public MetricsTracker create(String poolName, PoolStats poolStats) {
|
||||
new HikariCPCollector(poolName, poolStats).register();
|
||||
return new PrometheusMetricsTracker(poolName);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.zaxxer.hikari.metrics.prometheus;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.prometheus.client.CollectorRegistry;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class HikariCPCollectorTest {
|
||||
@Test
|
||||
public void noConnection() throws Exception {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName("no_connection");
|
||||
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
config.setJdbcUrl("jdbc:h2:mem:");
|
||||
|
||||
new HikariDataSource(config);
|
||||
|
||||
assertThat(getValue("hikaricp_active_connections", "no_connection"), is(0.0));
|
||||
assertThat(getValue("hikaricp_idle_connections", "no_connection"), is(0.0));
|
||||
assertThat(getValue("hikaricp_pending_threads", "no_connection"), is(0.0));
|
||||
assertThat(getValue("hikaricp_connections", "no_connection"), is(0.0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noConnectionWithoutPoolName() throws Exception {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
config.setJdbcUrl("jdbc:h2:mem:");
|
||||
|
||||
new HikariDataSource(config);
|
||||
|
||||
assertThat(getValue("hikaricp_active_connections", "HikariPool-1"), is(0.0));
|
||||
assertThat(getValue("hikaricp_idle_connections", "HikariPool-1"), is(0.0));
|
||||
assertThat(getValue("hikaricp_pending_threads", "HikariPool-1"), is(0.0));
|
||||
assertThat(getValue("hikaricp_connections", "HikariPool-1"), is(0.0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connection1() throws Exception {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName("connection1");
|
||||
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
config.setJdbcUrl("jdbc:h2:mem:");
|
||||
|
||||
HikariDataSource ds = new HikariDataSource(config);
|
||||
Connection connection1 = ds.getConnection();
|
||||
|
||||
assertThat(getValue("hikaricp_active_connections", "connection1"), is(1.0));
|
||||
assertThat(getValue("hikaricp_idle_connections", "connection1"), is(0.0));
|
||||
assertThat(getValue("hikaricp_pending_threads", "connection1"), is(0.0));
|
||||
assertThat(getValue("hikaricp_connections", "connection1"), is(1.0));
|
||||
|
||||
connection1.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionClosed() throws Exception {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName("connectionClosed");
|
||||
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
config.setJdbcUrl("jdbc:h2:mem:");
|
||||
config.setMaximumPoolSize(20);
|
||||
|
||||
HikariDataSource ds = new HikariDataSource(config);
|
||||
Connection connection1 = ds.getConnection();
|
||||
connection1.close();
|
||||
|
||||
assertThat(getValue("hikaricp_active_connections", "connectionClosed"), is(0.0));
|
||||
assertThat(getValue("hikaricp_idle_connections", "connectionClosed"), is(1.0));
|
||||
assertThat(getValue("hikaricp_pending_threads", "connectionClosed"), is(0.0));
|
||||
assertThat(getValue("hikaricp_connections", "connectionClosed"), is(1.0));
|
||||
}
|
||||
|
||||
private double getValue(String name, String poolName) {
|
||||
String[] labelNames = {"pool"};
|
||||
String[] labelValues = {poolName};
|
||||
return CollectorRegistry.defaultRegistry.getSampleValue(name, labelNames, labelValues);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.zaxxer.hikari.metrics.prometheus;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.prometheus.client.CollectorRegistry;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLTransientConnectionException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PrometheusMetricsTrackerTest {
|
||||
@Test
|
||||
public void recordConnectionTimeout() throws Exception {
|
||||
String poolName = "record";
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName(poolName);
|
||||
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
|
||||
config.setJdbcUrl("jdbc:h2:mem:");
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(250);
|
||||
|
||||
String[] labelNames = {"pool"};
|
||||
String[] labelValues = {poolName};
|
||||
|
||||
HikariDataSource hikariDataSource = new HikariDataSource(config);
|
||||
Connection connection = hikariDataSource.getConnection();
|
||||
try {
|
||||
hikariDataSource.getConnection();
|
||||
} catch (SQLTransientConnectionException ignored) {
|
||||
}
|
||||
connection.close();
|
||||
|
||||
assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
|
||||
"hikaricp_connection_timeout_count",
|
||||
labelNames,
|
||||
labelValues), is(1.0));
|
||||
assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
|
||||
"hikaricp_connection_acquired_nanos_count",
|
||||
labelNames,
|
||||
labelValues), is(equalTo(1.0)));
|
||||
assertTrue(CollectorRegistry.defaultRegistry.getSampleValue(
|
||||
"hikaricp_connection_acquired_nanos_sum",
|
||||
labelNames,
|
||||
labelValues) > 0.0);
|
||||
assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
|
||||
"hikaricp_connection_usage_millis_count",
|
||||
labelNames,
|
||||
labelValues), is(equalTo(1.0)));
|
||||
assertTrue(CollectorRegistry.defaultRegistry.getSampleValue(
|
||||
"hikaricp_connection_usage_millis_sum",
|
||||
labelNames,
|
||||
labelValues) > 0.0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue