Skip to content

Commit

Permalink
Fix metric name filter in MultiCollector #891 (#893)
Browse files Browse the repository at this point in the history
Signed-off-by: Fabian Stäber <fabian@fstab.de>
  • Loading branch information
fstab authored Nov 12, 2023
1 parent bc2244d commit 60c2553
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public MetricSnapshots scrape(Predicate<String> includedNames, PrometheusScrapeR
MetricSnapshots.Builder result = MetricSnapshots.builder();
for (Collector collector : collectors) {
String prometheusName = collector.getPrometheusName();
// prometheusName == null means the name is unknown, and we have to scrape to learn the name.
// prometheusName != null means we can skip the scrape if the name is excluded.
if (prometheusName == null || includedNames.test(prometheusName)) {
MetricSnapshot snapshot = scrapeRequest == null ? collector.collect(includedNames) : collector.collect(includedNames, scrapeRequest);
if (snapshot != null) {
Expand All @@ -103,17 +105,18 @@ public MetricSnapshots scrape(Predicate<String> includedNames, PrometheusScrapeR
}
for (MultiCollector collector : multiCollectors) {
List<String> prometheusNames = collector.getPrometheusNames();
boolean excluded = true; // the multi-collector is excluded unless
// at least one name matches
// empty prometheusNames means the names are unknown, and we have to scrape to learn the names.
// non-empty prometheusNames means we can exclude the collector if all names are excluded by the filter.
boolean excluded = !prometheusNames.isEmpty();
for (String prometheusName : prometheusNames) {
if (includedNames.test(prometheusName)) {
excluded = false;
break;
}
}
if (!excluded) {
MetricSnapshots snaphots = scrapeRequest == null ? collector.collect(includedNames) : collector.collect(includedNames, scrapeRequest);
for (MetricSnapshot snapshot : snaphots) {
MetricSnapshots snapshots = scrapeRequest == null ? collector.collect(includedNames) : collector.collect(includedNames, scrapeRequest);
for (MetricSnapshot snapshot : snapshots) {
if (snapshot != null) {
result.metricSnapshot(snapshot);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package io.prometheus.metrics.model.registry;

import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.Labels;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

public class MetricNameFilterTest {

private PrometheusRegistry registry;
Expand All @@ -21,12 +30,12 @@ public void testCounter() {
registry.register(() -> CounterSnapshot.builder()
.name("counter1")
.help("test counter 1")
.dataPoint(CounterSnapshot.CounterDataPointSnapshot.builder()
.dataPoint(CounterDataPointSnapshot.builder()
.labels(Labels.of("path", "/hello"))
.value(1.0)
.build()
)
.dataPoint(CounterSnapshot.CounterDataPointSnapshot.builder()
.dataPoint(CounterDataPointSnapshot.builder()
.labels(Labels.of("path", "/goodbye"))
.value(2.0)
.build()
Expand All @@ -36,7 +45,7 @@ public void testCounter() {
registry.register(() -> CounterSnapshot.builder()
.name("counter2")
.help("test counter 2")
.dataPoint(CounterSnapshot.CounterDataPointSnapshot.builder()
.dataPoint(CounterDataPointSnapshot.builder()
.value(1.0)
.build()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package io.prometheus.metrics.model.registry;

import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

public class MultiCollectorNameFilterTest {

private PrometheusRegistry registry;
private boolean[] collectCalled = {false};
private Predicate<String> includedNames = null;
List<String> prometheusNames = new ArrayList<>();

@Before
public void setUp() {
registry = new PrometheusRegistry();
collectCalled[0] = false;
includedNames = null;
prometheusNames = Collections.emptyList();

registry.register(new MultiCollector() {
@Override
public MetricSnapshots collect() {
collectCalled[0] = true;
return MetricSnapshots.builder()
.metricSnapshot(CounterSnapshot.builder()
.name("counter_1")
.dataPoint(CounterDataPointSnapshot.builder().value(1.0).build())
.build()
)
.metricSnapshot(GaugeSnapshot.builder()
.name("gauge_2")
.dataPoint(GaugeDataPointSnapshot.builder().value(1.0).build())
.build()
)
.build();
}

@Override
public List<String> getPrometheusNames() {
return prometheusNames;
}
});
}

@Test
public void testPartialFilter() {

includedNames = name -> name.equals("counter_1");

MetricSnapshots snapshots = registry.scrape(includedNames);
Assert.assertTrue(collectCalled[0]);
Assert.assertEquals(1, snapshots.size());
Assert.assertEquals("counter_1", snapshots.get(0).getMetadata().getName());
}

@Test
public void testPartialFilterWithPrometheusNames() {

includedNames = name -> name.equals("counter_1");
prometheusNames = Arrays.asList("counter_1", "gauge_2");

MetricSnapshots snapshots = registry.scrape(includedNames);
Assert.assertTrue(collectCalled[0]);
Assert.assertEquals(1, snapshots.size());
Assert.assertEquals("counter_1", snapshots.get(0).getMetadata().getName());
}

@Test
public void testCompleteFilter_CollectCalled() {

includedNames = name -> !name.equals("counter_1") && !name.equals("gauge_2");

MetricSnapshots snapshots = registry.scrape(includedNames);
Assert.assertTrue(collectCalled[0]);
Assert.assertEquals(0, snapshots.size());
}

@Test
public void testCompleteFilter_CollectNotCalled() {

includedNames = name -> !name.equals("counter_1") && !name.equals("gauge_2");
prometheusNames = Arrays.asList("counter_1", "gauge_2");

MetricSnapshots snapshots = registry.scrape(includedNames);
Assert.assertFalse(collectCalled[0]);
Assert.assertEquals(0, snapshots.size());
}
}

0 comments on commit 60c2553

Please sign in to comment.