Skip to content

Commit

Permalink
Separate metric names for different pool types to avoid Prometheus ta…
Browse files Browse the repository at this point in the history
…g collision
  • Loading branch information
HYEONSEOK1 committed Jul 28, 2024
1 parent 3df85e2 commit b1c4c01
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,49 +87,53 @@ private static MBeanServer getMBeanServer() {
public void bindTo(@NonNull MeterRegistry registry) {
for (String type : TYPES) {
registerMetricsEventually(type, (o, tags) -> {
registerGaugeForObject(registry, o, "NumIdle", "num.idle", tags,
String metricNamePrefix = METRIC_NAME_PREFIX
+ (type.equals("GenericObjectPool") ? "objectpool." : "keyedobjectpool.");

registerGaugeForObject(metricNamePrefix, registry, o, "NumIdle", "num.idle", tags,
"The number of instances currently idle in this pool", BaseUnits.OBJECTS);
registerGaugeForObject(registry, o, "NumActive", "num.active", tags,
registerGaugeForObject(metricNamePrefix, registry, o, "NumActive", "num.active", tags,
"The number of instances currently active in this pool", BaseUnits.OBJECTS);
registerGaugeForObject(registry, o, "NumWaiters", "num.waiters", tags,
registerGaugeForObject(metricNamePrefix, registry, o, "NumWaiters", "num.waiters", tags,
"The estimate of the number of threads currently blocked waiting for an object from the pool",
BaseUnits.THREADS);

registerFunctionCounterForObject(registry, o, "CreatedCount", "created", tags,
registerFunctionCounterForObject(metricNamePrefix, registry, o, "CreatedCount", "created", tags,
"The total number of objects created for this pool over the lifetime of the pool",
BaseUnits.OBJECTS);
registerFunctionCounterForObject(registry, o, "BorrowedCount", "borrowed", tags,
registerFunctionCounterForObject(metricNamePrefix, registry, o, "BorrowedCount", "borrowed", tags,
"The total number of objects successfully borrowed from this pool over the lifetime of the pool",
BaseUnits.OBJECTS);
registerFunctionCounterForObject(registry, o, "ReturnedCount", "returned", tags,
registerFunctionCounterForObject(metricNamePrefix, registry, o, "ReturnedCount", "returned", tags,
"The total number of objects returned to this pool over the lifetime of the pool",
BaseUnits.OBJECTS);
registerFunctionCounterForObject(registry, o, "DestroyedCount", "destroyed", tags,
registerFunctionCounterForObject(metricNamePrefix, registry, o, "DestroyedCount", "destroyed", tags,
"The total number of objects destroyed by this pool over the lifetime of the pool",
BaseUnits.OBJECTS);
registerFunctionCounterForObject(registry, o, "DestroyedByEvictorCount", "destroyed.by.evictor", tags,
registerFunctionCounterForObject(metricNamePrefix, registry, o, "DestroyedByEvictorCount",
"destroyed.by.evictor", tags,
"The total number of objects destroyed by the evictor associated with this pool over the lifetime of the pool",
BaseUnits.OBJECTS);
registerFunctionCounterForObject(registry, o, "DestroyedByBorrowValidationCount",
registerFunctionCounterForObject(metricNamePrefix, registry, o, "DestroyedByBorrowValidationCount",
"destroyed.by.borrow.validation", tags,
"The total number of objects destroyed by this pool as a result of failing validation during borrowObject() over the lifetime of the pool",
BaseUnits.OBJECTS);

registerTimeGaugeForObject(registry, o, "MaxBorrowWaitTimeMillis", "max.borrow.wait", tags,
"The maximum time a thread has waited to borrow objects from the pool");
registerTimeGaugeForObject(registry, o, "MeanActiveTimeMillis", "mean.active", tags,
registerTimeGaugeForObject(metricNamePrefix, registry, o, "MaxBorrowWaitTimeMillis", "max.borrow.wait",
tags, "The maximum time a thread has waited to borrow objects from the pool");
registerTimeGaugeForObject(metricNamePrefix, registry, o, "MeanActiveTimeMillis", "mean.active", tags,
"The mean time objects are active");
registerTimeGaugeForObject(registry, o, "MeanIdleTimeMillis", "mean.idle", tags,
registerTimeGaugeForObject(metricNamePrefix, registry, o, "MeanIdleTimeMillis", "mean.idle", tags,
"The mean time objects are idle");
registerTimeGaugeForObject(registry, o, "MeanBorrowWaitTimeMillis", "mean.borrow.wait", tags,
"The mean time threads wait to borrow an object");
registerTimeGaugeForObject(metricNamePrefix, registry, o, "MeanBorrowWaitTimeMillis",
"mean.borrow.wait", tags, "The mean time threads wait to borrow an object");
});
}
}

private Iterable<Tag> nameTag(ObjectName name, String type)
throws AttributeNotFoundException, MBeanException, ReflectionException, InstanceNotFoundException {
Tags tags = Tags.of("name", name.getKeyProperty("name"), "type", type);
Tags tags = Tags.of("name", name.getKeyProperty("name"));
if (Objects.equals(type, "GenericObjectPool")) {
// for GenericObjectPool, we want to include the name and factoryType as tags
String factoryType = mBeanServer.getAttribute(name, "FactoryType").toString();
Expand Down Expand Up @@ -227,33 +231,33 @@ public void close() {
executor.shutdown();
}

private void registerGaugeForObject(MeterRegistry registry, ObjectName o, String jmxMetricName, String meterName,
Tags allTags, String description, @Nullable String baseUnit) {
private void registerGaugeForObject(String metricNamePrefix, MeterRegistry registry, ObjectName o,
String jmxMetricName, String meterName, Tags allTags, String description, @Nullable String baseUnit) {
final AtomicReference<Gauge> gauge = new AtomicReference<>();
gauge.set(Gauge
.builder(METRIC_NAME_PREFIX + meterName, mBeanServer, getJmxAttribute(registry, gauge, o, jmxMetricName))
.builder(metricNamePrefix + meterName, mBeanServer, getJmxAttribute(registry, gauge, o, jmxMetricName))
.description(description)
.baseUnit(baseUnit)
.tags(allTags)
.register(registry));
}

private void registerFunctionCounterForObject(MeterRegistry registry, ObjectName o, String jmxMetricName,
String meterName, Tags allTags, String description, @Nullable String baseUnit) {
private void registerFunctionCounterForObject(String metricNamePrefix, MeterRegistry registry, ObjectName o,
String jmxMetricName, String meterName, Tags allTags, String description, @Nullable String baseUnit) {
final AtomicReference<FunctionCounter> counter = new AtomicReference<>();
counter.set(FunctionCounter
.builder(METRIC_NAME_PREFIX + meterName, mBeanServer, getJmxAttribute(registry, counter, o, jmxMetricName))
.builder(metricNamePrefix + meterName, mBeanServer, getJmxAttribute(registry, counter, o, jmxMetricName))
.description(description)
.baseUnit(baseUnit)
.tags(allTags)
.register(registry));
}

private void registerTimeGaugeForObject(MeterRegistry registry, ObjectName o, String jmxMetricName,
String meterName, Tags allTags, String description) {
private void registerTimeGaugeForObject(String metricNamePrefix, MeterRegistry registry, ObjectName o,
String jmxMetricName, String meterName, Tags allTags, String description) {
final AtomicReference<TimeGauge> timeGauge = new AtomicReference<>();
timeGauge.set(TimeGauge
.builder(METRIC_NAME_PREFIX + meterName, mBeanServer, TimeUnit.MILLISECONDS,
.builder(metricNamePrefix + meterName, mBeanServer, TimeUnit.MILLISECONDS,
getJmxAttribute(registry, timeGauge, o, jmxMetricName))
.description(description)
.tags(allTags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,19 @@ void verifyMetricsWithExpectedTags() {
MeterRegistry registry = new SimpleMeterRegistry();
commonsObjectPool2Metrics.bindTo(registry);

registry.get("commons.pool2.num.idle").tags(tags).gauge();
registry.get("commons.pool2.num.waiters").tags(tags).gauge();
registry.get("commons.pool2.objectpool.num.idle").tags(tags).gauge();
registry.get("commons.pool2.objectpool.num.waiters").tags(tags).gauge();

Arrays
.asList("commons.pool2.created", "commons.pool2.borrowed", "commons.pool2.returned",
"commons.pool2.destroyed", "commons.pool2.destroyed.by.evictor",
"commons.pool2.destroyed.by.borrow.validation")
.asList("commons.pool2.objectpool.created", "commons.pool2.objectpool.borrowed",
"commons.pool2.objectpool.returned", "commons.pool2.objectpool.destroyed",
"commons.pool2.objectpool.destroyed.by.evictor",
"commons.pool2.objectpool.destroyed.by.borrow.validation")
.forEach(name -> registry.get(name).tags(tags).functionCounter());

Arrays
.asList("commons.pool2.max.borrow.wait", "commons.pool2.mean.active", "commons.pool2.mean.idle",
"commons.pool2.mean.borrow.wait")
.asList("commons.pool2.objectpool.max.borrow.wait", "commons.pool2.objectpool.mean.active",
"commons.pool2.objectpool.mean.idle", "commons.pool2.objectpool.mean.borrow.wait")
.forEach(name -> registry.get(name).tags(tags).timeGauge());
}
// end::generic_pool[]
Expand All @@ -83,22 +84,22 @@ void verifyMetricsWithExpectedTags() {
void verifyGenericKeyedObjectPoolMetricsWithExpectedTags() {
// tag::generic_keyed_pool[]
try (GenericKeyedObjectPool<Object, Object> p = createGenericKeyedObjectPool()) {
Tags tagsToMatch = tags.and("type", "GenericKeyedObjectPool");
commonsObjectPool2Metrics.bindTo(registry);

Arrays.asList("commons.pool2.num.idle", "commons.pool2.num.waiters")
.forEach(name -> registry.get(name).tags(tagsToMatch).gauge());
Arrays.asList("commons.pool2.keyedobjectpool.num.idle", "commons.pool2.keyedobjectpool.num.waiters")
.forEach(name -> registry.get(name).gauge());

Arrays
.asList("commons.pool2.created", "commons.pool2.borrowed", "commons.pool2.returned",
"commons.pool2.destroyed", "commons.pool2.destroyed.by.evictor",
"commons.pool2.destroyed.by.borrow.validation")
.forEach(name -> registry.get(name).tags(tagsToMatch).functionCounter());
.asList("commons.pool2.keyedobjectpool.created", "commons.pool2.keyedobjectpool.borrowed",
"commons.pool2.keyedobjectpool.returned", "commons.pool2.keyedobjectpool.destroyed",
"commons.pool2.keyedobjectpool.destroyed.by.evictor",
"commons.pool2.keyedobjectpool.destroyed.by.borrow.validation")
.forEach(name -> registry.get(name).functionCounter());

Arrays
.asList("commons.pool2.max.borrow.wait", "commons.pool2.mean.active", "commons.pool2.mean.idle",
"commons.pool2.mean.borrow.wait")
.forEach(name -> registry.get(name).tags(tagsToMatch).timeGauge());
.asList("commons.pool2.keyedobjectpool.max.borrow.wait", "commons.pool2.keyedobjectpool.mean.active",
"commons.pool2.keyedobjectpool.mean.idle", "commons.pool2.keyedobjectpool.mean.borrow.wait")
.forEach(name -> registry.get(name).timeGauge());
}
// end::generic_keyed_pool[]
}
Expand All @@ -108,21 +109,21 @@ void verifyIdleAndActiveInstancesAreReported() throws Exception {
commonsObjectPool2Metrics.bindTo(registry);
CountDownLatch latch = new CountDownLatch(1);
registry.config().onMeterAdded(m -> {
if (m.getId().getName().contains("commons.pool2"))
if (m.getId().getName().contains("commons.pool2.objectpool"))
latch.countDown();
});

try (GenericObjectPool<Object> genericObjectPool = createGenericObjectPool()) {
latch.await(10, TimeUnit.SECONDS);
final Object o = genericObjectPool.borrowObject(10_000L);

assertThat(registry.get("commons.pool2.num.active").gauge().value()).isEqualTo(1.0);
assertThat(registry.get("commons.pool2.num.idle").gauge().value()).isEqualTo(0.0);
assertThat(registry.get("commons.pool2.objectpool.num.active").gauge().value()).isEqualTo(1.0);
assertThat(registry.get("commons.pool2.objectpool.num.idle").gauge().value()).isEqualTo(0.0);

genericObjectPool.returnObject(o);

assertThat(registry.get("commons.pool2.num.active").gauge().value()).isEqualTo(0.0);
assertThat(registry.get("commons.pool2.num.idle").gauge().value()).isEqualTo(1.0);
assertThat(registry.get("commons.pool2.objectpool.num.active").gauge().value()).isEqualTo(0.0);
assertThat(registry.get("commons.pool2.objectpool.num.idle").gauge().value()).isEqualTo(1.0);
}
}

Expand All @@ -135,8 +136,10 @@ void metricsReportedPerMultiplePools() {
MeterRegistry registry = new SimpleMeterRegistry();
commonsObjectPool2Metrics.bindTo(registry);

registry.get("commons.pool2.num.waiters").tag("name", "pool" + genericObjectPoolCount).gauge();
registry.get("commons.pool2.num.waiters").tag("name", "pool" + (genericObjectPoolCount - 1)).gauge();
registry.get("commons.pool2.objectpool.num.waiters").tag("name", "pool" + genericObjectPoolCount).gauge();
registry.get("commons.pool2.objectpool.num.waiters")
.tag("name", "pool" + (genericObjectPoolCount - 1))
.gauge();
}
}

Expand All @@ -147,7 +150,7 @@ void newPoolsAreDiscoveredByListener() throws InterruptedException {

CountDownLatch latch = new CountDownLatch(1);
registry.config().onMeterAdded(m -> {
if (m.getId().getName().contains("commons.pool2"))
if (m.getId().getName().contains("commons.pool2.objectpool"))
latch.countDown();
});

Expand Down

0 comments on commit b1c4c01

Please sign in to comment.