From 14c09083e75b807837d5b1da80688c01d0ff1b73 Mon Sep 17 00:00:00 2001 From: Mickael Maison Date: Mon, 30 Sep 2024 16:37:07 +0200 Subject: [PATCH] Make JvmMetrics.register idempotent with the default registry (#987) * Make JvmMetrics.register idempotent with the default registry Signed-off-by: Mickael Maison * Make JvmMetrics.register() methods idempotent Signed-off-by: Mickael Maison --------- Signed-off-by: Mickael Maison --- .../instrumentation/jvm/JvmMetrics.java | 42 +++++++++---------- .../instrumentation/jvm/JvmMetricsTest.java | 19 +++++++++ 2 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java index fa909f629..54d937688 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java @@ -3,7 +3,8 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.model.registry.PrometheusRegistry; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Registers all JVM metrics. Example usage: @@ -13,15 +14,14 @@ */ public class JvmMetrics { - private static AtomicBoolean registeredWithTheDefaultRegistry = new AtomicBoolean(false); - + private static final Set REGISTERED = ConcurrentHashMap.newKeySet(); public static Builder builder() { return new Builder(PrometheusProperties.get()); } // Note: Currently there is no configuration for JVM metrics, so it doesn't matter whether you pass a config or not. // However, we will add config options in the future, like whether you want to use Prometheus naming conventions - //'or OpenTelemetry semantic conventions for JVM metrics. + // or OpenTelemetry semantic conventions for JVM metrics. public static Builder builder(PrometheusProperties config) { return new Builder(config); } @@ -37,32 +37,32 @@ private Builder(PrometheusProperties config) { /** * Register all JVM metrics with the default registry. *

- * It's safe to call this multiple times: - * Only the first call will register the metrics, all subsequent calls will be ignored. + * It's safe to call this multiple times, only the first call will register the metrics, all subsequent calls + * will be ignored. */ public void register() { - if (!registeredWithTheDefaultRegistry.getAndSet(true)) { - register(PrometheusRegistry.defaultRegistry); - } + register(PrometheusRegistry.defaultRegistry); } /** * Register all JVM metrics with the {@code registry}. *

- * You must make sure to call this only once per {@code registry}, otherwise it will - * throw an Exception because you are trying to register duplicate metrics. + * It's safe to call this multiple times, only the first call will register the metrics, all subsequent calls + * will be ignored. */ public void register(PrometheusRegistry registry) { - JvmThreadsMetrics.builder(config).register(registry); - JvmBufferPoolMetrics.builder(config).register(registry); - JvmClassLoadingMetrics.builder(config).register(registry); - JvmCompilationMetrics.builder(config).register(registry); - JvmGarbageCollectorMetrics.builder(config).register(registry); - JvmMemoryPoolAllocationMetrics.builder(config).register(registry); - JvmMemoryMetrics.builder(config).register(registry); - JvmNativeMemoryMetrics.builder(config).register(registry); - JvmRuntimeInfoMetric.builder(config).register(registry); - ProcessMetrics.builder(config).register(registry); + if (REGISTERED.add(registry)) { + JvmThreadsMetrics.builder(config).register(registry); + JvmBufferPoolMetrics.builder(config).register(registry); + JvmClassLoadingMetrics.builder(config).register(registry); + JvmCompilationMetrics.builder(config).register(registry); + JvmGarbageCollectorMetrics.builder(config).register(registry); + JvmMemoryPoolAllocationMetrics.builder(config).register(registry); + JvmMemoryMetrics.builder(config).register(registry); + JvmNativeMemoryMetrics.builder(config).register(registry); + JvmRuntimeInfoMetric.builder(config).register(registry); + ProcessMetrics.builder(config).register(registry); + } } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java new file mode 100644 index 000000000..d93b1682d --- /dev/null +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java @@ -0,0 +1,19 @@ +package io.prometheus.metrics.instrumentation.jvm; + +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JvmMetricsTest { + + @Test + public void testRegisterIdempotent() { + PrometheusRegistry registry = new PrometheusRegistry(); + assertEquals(0, registry.scrape().size()); + JvmMetrics.builder().register(registry); + assertTrue(registry.scrape().size() > 0); + JvmMetrics.builder().register(registry); + } +}