diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java index 87e8429f1..71428221a 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java @@ -10,6 +10,7 @@ import io.prometheus.metrics.model.snapshots.MetricSnapshot; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -136,6 +137,11 @@ public void remove(String... labelValues) { data.remove(Arrays.asList(labelValues)); } + /** Remove the data points when the given function. */ + public void removeIf(Function, Boolean> f) { + data.entrySet().removeIf(entry -> f.apply(Collections.unmodifiableList(entry.getKey()))); + } + /** Reset the metric (remove all data points). */ public void clear() { data.clear(); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java index e12618436..00aa53bbd 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java @@ -4,6 +4,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -35,6 +37,29 @@ public void testLabelRemoveWhileCollecting() throws Exception { } } + @Test + @SuppressWarnings("unchecked") + public void testLabelRemoveIf() throws Exception { + Counter counter = + Counter.builder().name("testLabelRemoveIf").labelNames("label1", "label2").build(); + Field data = counter.getClass().getSuperclass().getDeclaredField("data"); + data.setAccessible(true); + + counter.labelValues("a", "b").inc(1.0); + counter.labelValues("a", "c").inc(3.0); + counter.labelValues("a", "d").inc(7.0); + counter.labelValues("e", "f").inc(8.0); + + counter.removeIf(labels -> labels.size() == 2 && labels.get(0).equals("a")); + + Map, Counter.DataPoint> dataPoints = + (Map, Counter.DataPoint>) data.get(counter); + + assertThat(dataPoints).hasSize(1); + assertThat(dataPoints.get(Arrays.asList("e", "f"))).isNotNull(); + assertThat(dataPoints.get(Arrays.asList("e", "f")).get()).isEqualTo(8.0D); + } + @Test public void testClear() { Counter counter = Counter.builder().name("test").labelNames("label1", "label2").build();