diff --git a/pom.xml b/pom.xml index 6db493f10..033e89331 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,7 @@ prometheus-metrics-exporter-pushgateway prometheus-metrics-instrumentation-jvm prometheus-metrics-instrumentation-dropwizard5 + prometheus-metrics-instrumentation-guava prometheus-metrics-simpleclient-bridge examples diff --git a/simpleclient-archive/simpleclient_guava/pom.xml b/prometheus-metrics-instrumentation-guava/pom.xml similarity index 64% rename from simpleclient-archive/simpleclient_guava/pom.xml rename to prometheus-metrics-instrumentation-guava/pom.xml index 076491963..a4103e051 100644 --- a/simpleclient-archive/simpleclient_guava/pom.xml +++ b/prometheus-metrics-instrumentation-guava/pom.xml @@ -5,17 +5,21 @@ io.prometheus client_java - 1.0.0-beta-2-SNAPSHOT + 1.4.0-SNAPSHOT - simpleclient_guava + prometheus-metrics-instrumentation-guava bundle - Prometheus Java Simpleclient guava + Prometheus Metrics Instrumentation - Guava - Metrics collector for guava based caches + Instrumentation library guava based caches + + io.prometheus.metrics.instrumentation.guava + + The Apache Software License, Version 2.0 @@ -30,18 +34,25 @@ Clint Checketts checketts@gmail.com + + + pheyken + Petar Heyken + mail@petar-heyken.de + io.prometheus - simpleclient + prometheus-metrics-core ${project.version} com.google.guava guava - 31.1-jre + 33.2.1-jre + provided @@ -55,15 +66,21 @@ org.mockito mockito-core - 4.6.1 + 5.12.0 test org.assertj assertj-core - 3.23.1 + 3.26.3 test + + io.prometheus + prometheus-metrics-exposition-formats + ${project.version} + test + diff --git a/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java b/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java new file mode 100644 index 000000000..71ffea01c --- /dev/null +++ b/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java @@ -0,0 +1,203 @@ +package io.prometheus.metrics.instrumentation.guava; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.cache.LoadingCache; +import io.prometheus.metrics.model.registry.MultiCollector; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import io.prometheus.metrics.model.snapshots.SummarySnapshot; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Collect metrics from Guava's com.google.common.cache.Cache. + *

+ *

{@code
+ *
+ * // Note that `recordStats()` is required to gather non-zero statistics
+ * Cache cache = CacheBuilder.newBuilder().recordStats().build();
+ * CacheMetricsCollector cacheMetrics = new CacheMetricsCollector().register();
+ * cacheMetrics.addCache("mycache", cache);
+ *
+ * }
+ * + * Exposed metrics are labeled with the provided cache name. + * + * With the example above, sample metric names would be: + *
+ *     guava_cache_hit_total{cache="mycache"} 10.0
+ *     guava_cache_miss_total{cache="mycache"} 3.0
+ *     guava_cache_requests_total{cache="mycache"} 13.0
+ *     guava_cache_eviction_total{cache="mycache"} 1.0
+ *     guava_cache_size{cache="mycache"} 5.0
+ * 
+ * + * Additionally, if the cache includes a loader, the following metrics would be provided: + *
+ *     guava_cache_load_failure_total{cache="mycache"} 2.0
+ *     guava_cache_loads_total{cache="mycache"} 7.0
+ *     guava_cache_load_duration_seconds_count{cache="mycache"} 7.0
+ *     guava_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
+ * 
+ * + */ +public class CacheMetricsCollector implements MultiCollector { + + private static final double NANOSECONDS_PER_SECOND = 1_000_000_000.0; + + protected final ConcurrentMap children = new ConcurrentHashMap<>(); + + /** + * Add or replace the cache with the given name. + *

+ * Any references any previous cache with this name is invalidated. + * + * @param cacheName The name of the cache, will be the metrics label value + * @param cache The cache being monitored + */ + public void addCache(String cacheName, Cache cache) { + children.put(cacheName, cache); + } + + /** + * Remove the cache with the given name. + *

+ * Any references to the cache are invalidated. + * + * @param cacheName cache to be removed + */ + public Cache removeCache(String cacheName) { + return children.remove(cacheName); + } + + /** + * Remove all caches. + *

+ * Any references to all caches are invalidated. + */ + public void clear(){ + children.clear(); + } + + @Override + public MetricSnapshots collect() { + final MetricSnapshots.Builder metricSnapshotsBuilder = MetricSnapshots.builder(); + final List labelNames = Arrays.asList("cache"); + + final CounterSnapshot.Builder cacheHitTotal = CounterSnapshot.builder() + .name("guava_cache_hit") + .help("Cache hit totals"); + + final CounterSnapshot.Builder cacheMissTotal = CounterSnapshot.builder() + .name("guava_cache_miss") + .help("Cache miss totals"); + + final CounterSnapshot.Builder cacheRequestsTotal = CounterSnapshot.builder() + .name("guava_cache_requests") + .help("Cache request totals"); + + final CounterSnapshot.Builder cacheEvictionTotal = CounterSnapshot.builder() + .name("guava_cache_eviction") + .help("Cache eviction totals, doesn't include manually removed entries"); + + final CounterSnapshot.Builder cacheLoadFailure = CounterSnapshot.builder() + .name("guava_cache_load_failure") + .help("Cache load failures"); + + final CounterSnapshot.Builder cacheLoadTotal = CounterSnapshot.builder() + .name("guava_cache_loads") + .help("Cache loads: both success and failures"); + + final GaugeSnapshot.Builder cacheSize = GaugeSnapshot.builder() + .name("guava_cache_size") + .help("Cache size"); + + final SummarySnapshot.Builder cacheLoadSummary = SummarySnapshot.builder() + .name("guava_cache_load_duration_seconds") + .help("Cache load duration: both success and failures"); + + for (final Map.Entry c: children.entrySet()) { + final List cacheName = Arrays.asList(c.getKey()); + final Labels labels = Labels.of(labelNames, cacheName); + + final CacheStats stats = c.getValue().stats(); + + cacheHitTotal.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.hitCount()) + .build() + ); + + cacheMissTotal.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.missCount()) + .build() + ); + + cacheRequestsTotal.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.requestCount()) + .build() + ); + + cacheEvictionTotal.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.evictionCount()) + .build() + ); + + cacheSize.dataPoint( + GaugeSnapshot.GaugeDataPointSnapshot.builder() + .labels(labels) + .value(c.getValue().size()) + .build() + ); + + if (c.getValue() instanceof LoadingCache) { + cacheLoadFailure.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.loadExceptionCount()) + .build() + ); + + cacheLoadTotal.dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(labels) + .value(stats.loadCount()) + .build() + ); + + cacheLoadSummary.dataPoint( + SummarySnapshot.SummaryDataPointSnapshot.builder() + .labels(labels) + .count(stats.loadCount()) + .sum(stats.totalLoadTime() / NANOSECONDS_PER_SECOND) + .build() + ); + } + } + + metricSnapshotsBuilder.metricSnapshot(cacheHitTotal.build()); + metricSnapshotsBuilder.metricSnapshot(cacheMissTotal.build()); + metricSnapshotsBuilder.metricSnapshot(cacheRequestsTotal.build()); + metricSnapshotsBuilder.metricSnapshot(cacheEvictionTotal.build()); + metricSnapshotsBuilder.metricSnapshot(cacheLoadFailure.build()); + metricSnapshotsBuilder.metricSnapshot(cacheLoadTotal.build()); + metricSnapshotsBuilder.metricSnapshot(cacheSize.build()); + metricSnapshotsBuilder.metricSnapshot(cacheLoadSummary.build()); + + return metricSnapshotsBuilder.build(); + } +} diff --git a/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java new file mode 100644 index 000000000..41b3bba8d --- /dev/null +++ b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java @@ -0,0 +1,142 @@ +package io.prometheus.metrics.instrumentation.guava; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.DataPointSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.SummarySnapshot; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CacheMetricsCollectorTest { + + @Test + public void cacheExposesMetricsForHitMissAndEviction() { + final Cache cache = CacheBuilder.newBuilder().maximumSize(2).recordStats().build(); + + final CacheMetricsCollector collector = new CacheMetricsCollector(); + collector.addCache("users", cache); + + final PrometheusRegistry registry = new PrometheusRegistry(); + registry.register(collector); + + cache.getIfPresent("user1"); + cache.getIfPresent("user1"); + cache.put("user1", "First User"); + cache.getIfPresent("user1"); + + // Add to cache to trigger eviction. + cache.put("user2", "Second User"); + cache.put("user3", "Third User"); + cache.put("user4", "Fourth User"); + + assertCounterMetric(registry, "guava_cache_hit", "users", 1.0); + assertCounterMetric(registry, "guava_cache_miss", "users", 2.0); + assertCounterMetric(registry, "guava_cache_requests", "users", 3.0); + assertCounterMetric(registry, "guava_cache_eviction", "users", 2.0); + + final String expected = "# TYPE guava_cache_eviction counter\n" + + "# HELP guava_cache_eviction Cache eviction totals, doesn't include manually removed entries\n" + + "guava_cache_eviction_total{cache=\"users\"} 2.0\n" + + "# TYPE guava_cache_hit counter\n" + + "# HELP guava_cache_hit Cache hit totals\n" + + "guava_cache_hit_total{cache=\"users\"} 1.0\n" + + "# TYPE guava_cache_miss counter\n" + + "# HELP guava_cache_miss Cache miss totals\n" + + "guava_cache_miss_total{cache=\"users\"} 2.0\n" + + "# TYPE guava_cache_requests counter\n" + + "# HELP guava_cache_requests Cache request totals\n" + + "guava_cache_requests_total{cache=\"users\"} 3.0\n" + + "# TYPE guava_cache_size gauge\n" + + "# HELP guava_cache_size Cache size\n" + + "guava_cache_size{cache=\"users\"} 2.0\n" + + "# EOF\n"; + + assertEquals(expected, convertToOpenMetricsFormat(registry)); + } + + @SuppressWarnings("unchecked") + @Test + public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { + final CacheLoader loader = mock(CacheLoader.class); + when(loader.load(anyString())) + .thenReturn("First User") + .thenThrow(new RuntimeException("Seconds time fails")) + .thenReturn("Third User"); + + final LoadingCache cache = CacheBuilder.newBuilder().recordStats().build(loader); + final CacheMetricsCollector collector = new CacheMetricsCollector(); + collector.addCache("loadingusers", cache); + + final PrometheusRegistry registry = new PrometheusRegistry(); + registry.register(collector); + + cache.get("user1"); + cache.get("user1"); + try { + cache.get("user2"); + } catch (Exception e) { + // ignoring. + } + cache.get("user3"); + + assertCounterMetric(registry, "guava_cache_hit", "loadingusers", 1.0); + assertCounterMetric(registry, "guava_cache_miss", "loadingusers", 3.0); + + assertCounterMetric(registry, "guava_cache_load_failure", "loadingusers", 1.0); + assertCounterMetric(registry, "guava_cache_loads", "loadingusers", 3.0); + + final SummarySnapshot.SummaryDataPointSnapshot loadDuration = (SummarySnapshot.SummaryDataPointSnapshot) getDataPointSnapshot( + registry, + "guava_cache_load_duration_seconds", + "loadingusers" + ); + + assertEquals(3, loadDuration.getCount()); + assertThat(loadDuration.getSum()).isGreaterThan(0); + } + + private void assertCounterMetric(PrometheusRegistry registry, String name, String cacheName, double value) { + final CounterSnapshot.CounterDataPointSnapshot dataPointSnapshot = + (CounterSnapshot.CounterDataPointSnapshot) getDataPointSnapshot(registry, name, cacheName); + + assertEquals(value, dataPointSnapshot.getValue(), 0); + } + + private DataPointSnapshot getDataPointSnapshot(PrometheusRegistry registry, String name, String cacheName) + { + final Labels labels = Labels.of(new String[]{"cache"}, new String[]{cacheName}); + + return registry.scrape(name::equals).stream() + .flatMap(metricSnapshot -> metricSnapshot.getDataPoints().stream()) + .filter(dataPoint -> dataPoint.getLabels().equals(labels)) + .findFirst() + .get(); + } + + private String convertToOpenMetricsFormat(PrometheusRegistry registry) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + try { + writer.write(out, registry.scrape()); + return out.toString(StandardCharsets.UTF_8.name()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/simpleclient-archive/simpleclient_guava/version-rules.xml b/prometheus-metrics-instrumentation-guava/version-rules.xml similarity index 100% rename from simpleclient-archive/simpleclient_guava/version-rules.xml rename to prometheus-metrics-instrumentation-guava/version-rules.xml diff --git a/simpleclient-archive/simpleclient_guava/src/main/java/io/prometheus/client/guava/cache/CacheMetricsCollector.java b/simpleclient-archive/simpleclient_guava/src/main/java/io/prometheus/client/guava/cache/CacheMetricsCollector.java deleted file mode 100644 index 5ed0276bb..000000000 --- a/simpleclient-archive/simpleclient_guava/src/main/java/io/prometheus/client/guava/cache/CacheMetricsCollector.java +++ /dev/null @@ -1,142 +0,0 @@ -package io.prometheus.client.guava.cache; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheStats; -import com.google.common.cache.LoadingCache; -import io.prometheus.client.Collector; -import io.prometheus.client.CounterMetricFamily; -import io.prometheus.client.GaugeMetricFamily; -import io.prometheus.client.SummaryMetricFamily; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * Collect metrics from Guava's com.google.common.cache.Cache. - *

- *

{@code
- *
- * // Note that `recordStats()` is required to gather non-zero statistics
- * Cache cache = CacheBuilder.newBuilder().recordStats().build();
- * CacheMetricsCollector cacheMetrics = new CacheMetricsCollector().register();
- * cacheMetrics.addCache("mycache", cache);
- *
- * }
- * - * Exposed metrics are labeled with the provided cache name. - * - * With the example above, sample metric names would be: - *
- *     guava_cache_hit_total{cache="mycache"} 10.0
- *     guava_cache_miss_total{cache="mycache"} 3.0
- *     guava_cache_requests_total{cache="mycache"} 13.0
- *     guava_cache_eviction_total{cache="mycache"} 1.0
- *     guava_cache_size{cache="mycache"} 5.0
- * 
- * - * Additionally if the cache includes a loader, the following metrics would be provided: - *
- *     guava_cache_load_failure_total{cache="mycache"} 2.0
- *     guava_cache_loads_total{cache="mycache"} 7.0
- *     guava_cache_load_duration_seconds_count{cache="mycache"} 7.0
- *     guava_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
- * 
- * - */ -public class CacheMetricsCollector extends Collector { - - protected final ConcurrentMap children = new ConcurrentHashMap(); - - /** - * Add or replace the cache with the given name. - *

- * Any references any previous cache with this name is invalidated. - * - * @param cacheName The name of the cache, will be the metrics label value - * @param cache The cache being monitored - */ - public void addCache(String cacheName, Cache cache) { - children.put(cacheName, cache); - } - - /** - * Remove the cache with the given name. - *

- * Any references to the cache are invalidated. - * - * @param cacheName cache to be removed - */ - public Cache removeCache(String cacheName) { - return children.remove(cacheName); - } - - /** - * Remove all caches. - *

- * Any references to all caches are invalidated. - */ - public void clear(){ - children.clear(); - } - - @Override - public List collect() { - List mfs = new ArrayList(); - List labelNames = Arrays.asList("cache"); - - CounterMetricFamily cacheHitTotal = new CounterMetricFamily("guava_cache_hit_total", - "Cache hit totals", labelNames); - mfs.add(cacheHitTotal); - - CounterMetricFamily cacheMissTotal = new CounterMetricFamily("guava_cache_miss_total", - "Cache miss totals", labelNames); - mfs.add(cacheMissTotal); - - CounterMetricFamily cacheRequestsTotal = new CounterMetricFamily("guava_cache_requests_total", - "Cache request totals, hits + misses", labelNames); - mfs.add(cacheRequestsTotal); - - CounterMetricFamily cacheEvictionTotal = new CounterMetricFamily("guava_cache_eviction_total", - "Cache eviction totals, doesn't include manually removed entries", labelNames); - mfs.add(cacheEvictionTotal); - - CounterMetricFamily cacheLoadFailure = new CounterMetricFamily("guava_cache_load_failure_total", - "Cache load failures", labelNames); - mfs.add(cacheLoadFailure); - - CounterMetricFamily cacheLoadTotal = new CounterMetricFamily("guava_cache_loads_total", - "Cache loads: both success and failures", labelNames); - mfs.add(cacheLoadTotal); - - GaugeMetricFamily cacheSize = new GaugeMetricFamily("guava_cache_size", - "Cache size", labelNames); - mfs.add(cacheSize); - - SummaryMetricFamily cacheLoadSummary = new SummaryMetricFamily("guava_cache_load_duration_seconds", - "Cache load duration: both success and failures", labelNames); - mfs.add(cacheLoadSummary); - - for(Map.Entry c: children.entrySet()) { - List cacheName = Arrays.asList(c.getKey()); - CacheStats stats = c.getValue().stats(); - - cacheHitTotal.addMetric(cacheName, stats.hitCount()); - cacheMissTotal.addMetric(cacheName, stats.missCount()); - cacheRequestsTotal.addMetric(cacheName, stats.requestCount()); - cacheEvictionTotal.addMetric(cacheName, stats.evictionCount()); - cacheSize.addMetric(cacheName, c.getValue().size()); - - if(c.getValue() instanceof LoadingCache) { - cacheLoadFailure.addMetric(cacheName, stats.loadExceptionCount()); - cacheLoadTotal.addMetric(cacheName, stats.loadCount()); - - cacheLoadSummary.addMetric(cacheName, stats.loadCount(), stats.totalLoadTime() / Collector.NANOSECONDS_PER_SECOND); - } - } - return mfs; - } -} diff --git a/simpleclient-archive/simpleclient_guava/src/test/java/io/prometheus/client/guava/cache/CacheMetricsCollectorTest.java b/simpleclient-archive/simpleclient_guava/src/test/java/io/prometheus/client/guava/cache/CacheMetricsCollectorTest.java deleted file mode 100644 index dab30b9fb..000000000 --- a/simpleclient-archive/simpleclient_guava/src/test/java/io/prometheus/client/guava/cache/CacheMetricsCollectorTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.prometheus.client.guava.cache; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import io.prometheus.client.CollectorRegistry; -import org.junit.Test; - -import static org.assertj.core.api.Java6Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CacheMetricsCollectorTest { - - @Test - public void cacheExposesMetricsForHitMissAndEviction() throws Exception { - Cache cache = CacheBuilder.newBuilder().maximumSize(2).recordStats().build(); - CollectorRegistry registry = new CollectorRegistry(); - - CacheMetricsCollector collector = new CacheMetricsCollector().register(registry); - collector.addCache("users", cache); - - cache.getIfPresent("user1"); - cache.getIfPresent("user1"); - cache.put("user1", "First User"); - cache.getIfPresent("user1"); - - // Add to cache to trigger eviction. - cache.put("user2", "Second User"); - cache.put("user3", "Third User"); - cache.put("user4", "Fourth User"); - - assertMetric(registry, "guava_cache_hit_total", "users", 1.0); - assertMetric(registry, "guava_cache_miss_total", "users", 2.0); - assertMetric(registry, "guava_cache_requests_total", "users", 3.0); - assertMetric(registry, "guava_cache_eviction_total", "users", 2.0); - } - - @SuppressWarnings("unchecked") - @Test - public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { - CacheLoader loader = mock(CacheLoader.class); - when(loader.load(anyString())) - .thenReturn("First User") - .thenThrow(new RuntimeException("Seconds time fails")) - .thenReturn("Third User"); - - LoadingCache cache = CacheBuilder.newBuilder().recordStats().build(loader); - CollectorRegistry registry = new CollectorRegistry(); - CacheMetricsCollector collector = new CacheMetricsCollector().register(registry); - collector.addCache("loadingusers", cache); - - cache.get("user1"); - cache.get("user1"); - try{ - cache.get("user2"); - } catch (Exception e) { - // ignoring. - } - cache.get("user3"); - - assertMetric(registry, "guava_cache_hit_total", "loadingusers", 1.0); - assertMetric(registry, "guava_cache_miss_total", "loadingusers", 3.0); - - assertMetric(registry, "guava_cache_load_failure_total", "loadingusers", 1.0); - assertMetric(registry, "guava_cache_loads_total", "loadingusers", 3.0); - - assertMetric(registry, "guava_cache_load_duration_seconds_count", "loadingusers", 3.0); - assertMetricGreatThan(registry, "guava_cache_load_duration_seconds_sum", "loadingusers", 0.0); - } - - - private void assertMetric(CollectorRegistry registry, String name, String cacheName, double value) { - assertThat(registry.getSampleValue(name, new String[]{"cache"}, new String[]{cacheName})).isEqualTo(value); - } - - - private void assertMetricGreatThan(CollectorRegistry registry, String name, String cacheName, double value) { - assertThat(registry.getSampleValue(name, new String[]{"cache"}, new String[]{cacheName})).isGreaterThan(value); - } - - -}