Skip to content

Commit ede5cc3

Browse files
author
Marcin Kielar
committed
Redesign of Collector architecture (#901).
Signed-off-by: Marcin Kielar <[email protected]>
1 parent 60f72b6 commit ede5cc3

File tree

36 files changed

+820
-544
lines changed

36 files changed

+820
-544
lines changed

examples/example-exporter-multi-target/src/main/java/io/prometheus/metrics/examples/multitarget/Main.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class Main {
1212

1313
public static void main(String[] args) throws IOException, InterruptedException {
1414

15-
SampleMultiCollector xmc = new SampleMultiCollector();
15+
SampleCollector xmc = new SampleCollector();
1616
PrometheusRegistry.defaultRegistry.register(xmc);
1717
HTTPServer server = HTTPServer.builder()
1818
.port(9401)
+6-31
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,23 @@
11
package io.prometheus.metrics.examples.multitarget;
22

3-
import java.util.ArrayList;
4-
import java.util.Collection;
5-
import java.util.List;
3+
import java.util.function.Predicate;
64

7-
import io.prometheus.metrics.model.registry.MultiCollector;
5+
import io.prometheus.metrics.model.registry.Collector;
86
import io.prometheus.metrics.model.registry.PrometheusScrapeRequest;
97
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
108
import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot.Builder;
119
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
1210
import io.prometheus.metrics.model.snapshots.Labels;
13-
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
1411
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
1512
import io.prometheus.metrics.model.snapshots.PrometheusNaming;
1613

17-
public class SampleMultiCollector implements MultiCollector {
18-
19-
public SampleMultiCollector() {
20-
super();
21-
}
22-
23-
@Override
24-
public MetricSnapshots collect() {
25-
return new MetricSnapshots();
26-
}
27-
14+
public class SampleCollector implements Collector {
2815
@Override
29-
public MetricSnapshots collect(PrometheusScrapeRequest scrapeRequest) {
30-
return collectMetricSnapshots(scrapeRequest);
16+
public MetricSnapshots collect(Predicate<String> nameFilter, PrometheusScrapeRequest scrapeRequest) {
17+
return collectMetricSnapshots(scrapeRequest).filter(nameFilter);
3118
}
3219

3320
protected MetricSnapshots collectMetricSnapshots(PrometheusScrapeRequest scrapeRequest) {
34-
3521
GaugeSnapshot.Builder gaugeBuilder = GaugeSnapshot.builder();
3622
gaugeBuilder.name("x_load").help("process load");
3723

@@ -71,18 +57,7 @@ protected MetricSnapshots collectMetricSnapshots(PrometheusScrapeRequest scrapeR
7157
gaugeBuilder.dataPoint(gaugeDataPointBuilder.build());
7258
}
7359
}
74-
Collection<MetricSnapshot> snaps = new ArrayList<MetricSnapshot>();
75-
snaps.add(counterBuilder.build());
76-
snaps.add(gaugeBuilder.build());
77-
MetricSnapshots msnaps = new MetricSnapshots(snaps);
60+
MetricSnapshots msnaps = new MetricSnapshots(counterBuilder.build(), gaugeBuilder.build());
7861
return msnaps;
7962
}
80-
81-
public List<String> getPrometheusNames() {
82-
List<String> names = new ArrayList<String>();
83-
names.add("x_calls_total");
84-
names.add("x_load");
85-
return names;
86-
}
87-
8863
}

integration-tests/it-exporter/it-exporter-httpserver-sample/src/main/java/io/prometheus/metrics/it/exporter/httpserver/HTTPServerSample.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import io.prometheus.metrics.core.metrics.Gauge;
55
import io.prometheus.metrics.core.metrics.Info;
66
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
7+
import io.prometheus.metrics.model.registry.CollectorBuilder;
78
import io.prometheus.metrics.model.registry.Collector;
89
import io.prometheus.metrics.model.registry.PrometheusRegistry;
9-
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
1010
import io.prometheus.metrics.model.snapshots.Unit;
1111

1212
import java.io.IOException;
@@ -53,9 +53,9 @@ public static void main(String[] args) throws IOException, InterruptedException
5353
gauge.labelValues("outside").set(27.0);
5454

5555
if (mode == Mode.error) {
56-
Collector failingCollector = () -> {
56+
Collector failingCollector = CollectorBuilder.fromMetric(() -> {
5757
throw new RuntimeException("Simulating an error.");
58-
};
58+
});
5959

6060
PrometheusRegistry.defaultRegistry.register(failingCollector);
6161
}

integration-tests/it-exporter/it-exporter-servlet-jetty-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/jetty/ExporterServletJettySample.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import io.prometheus.metrics.core.metrics.Gauge;
55
import io.prometheus.metrics.core.metrics.Info;
66
import io.prometheus.metrics.exporter.servlet.jakarta.PrometheusMetricsServlet;
7+
import io.prometheus.metrics.model.registry.CollectorBuilder;
78
import io.prometheus.metrics.model.registry.Collector;
89
import io.prometheus.metrics.model.registry.PrometheusRegistry;
9-
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
1010
import io.prometheus.metrics.model.snapshots.Unit;
1111
import org.eclipse.jetty.server.Connector;
1212
import org.eclipse.jetty.server.Server;
@@ -57,9 +57,9 @@ public static void main(String[] args) throws Exception {
5757
gauge.labelValues("outside").set(27.0);
5858

5959
if (mode == Mode.error) {
60-
Collector failingCollector = () -> {
60+
Collector failingCollector = CollectorBuilder.fromMetrics(() -> {
6161
throw new RuntimeException("Simulating an error.");
62-
};
62+
});
6363

6464
PrometheusRegistry.defaultRegistry.register(failingCollector);
6565
}

integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/tomcat/ExporterServletTomcatSample.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import io.prometheus.metrics.core.metrics.Gauge;
55
import io.prometheus.metrics.core.metrics.Info;
66
import io.prometheus.metrics.exporter.servlet.jakarta.PrometheusMetricsServlet;
7+
import io.prometheus.metrics.model.registry.CollectorBuilder;
78
import io.prometheus.metrics.model.registry.Collector;
89
import io.prometheus.metrics.model.registry.PrometheusRegistry;
9-
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
1010
import io.prometheus.metrics.model.snapshots.Unit;
1111
import org.apache.catalina.Context;
1212
import org.apache.catalina.LifecycleException;
@@ -61,9 +61,9 @@ public static void main(String[] args) throws LifecycleException, IOException {
6161
gauge.labelValues("outside").set(27.0);
6262

6363
if (mode == Mode.error) {
64-
Collector failingCollector = () -> {
64+
Collector failingCollector = CollectorBuilder.fromMetrics(() -> {
6565
throw new RuntimeException("Simulating an error.");
66-
};
66+
});
6767

6868
PrometheusRegistry.defaultRegistry.register(failingCollector);
6969
}

prometheus-metrics-core/pom.xml

+12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919
<properties>
2020
<automatic.module.name>io.prometheus.metrics.core</automatic.module.name>
2121
</properties>
22+
<build>
23+
<plugins>
24+
<plugin>
25+
<groupId>org.apache.maven.plugins</groupId>
26+
<artifactId>maven-compiler-plugin</artifactId>
27+
<configuration>
28+
<source>16</source>
29+
<target>16</target>
30+
</configuration>
31+
</plugin>
32+
</plugins>
33+
</build>
2234

2335
<licenses>
2436
<license>

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Metric.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.prometheus.metrics.config.PrometheusProperties;
44
import io.prometheus.metrics.model.registry.Collector;
5+
import io.prometheus.metrics.model.registry.CollectorBuilder;
56
import io.prometheus.metrics.model.registry.PrometheusRegistry;
67
import io.prometheus.metrics.model.snapshots.Label;
78
import io.prometheus.metrics.model.snapshots.Labels;
@@ -21,9 +22,6 @@ protected Metric(Builder<?, ?> builder) {
2122
this.constLabels = builder.constLabels;
2223
}
2324

24-
@Override
25-
public abstract MetricSnapshot collect();
26-
2725
protected static abstract class Builder<B extends Builder<B, M>, M extends Metric> {
2826

2927
protected final List<String> illegalLabelNames;

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/MetricWithFixedMetadata.java

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.prometheus.metrics.core.metrics;
22

33
import io.prometheus.metrics.config.PrometheusProperties;
4-
import io.prometheus.metrics.model.snapshots.Labels;
5-
import io.prometheus.metrics.model.snapshots.MetricMetadata;
6-
import io.prometheus.metrics.model.snapshots.PrometheusNaming;
7-
import io.prometheus.metrics.model.snapshots.Unit;
4+
import io.prometheus.metrics.model.registry.Collector;
5+
import io.prometheus.metrics.model.registry.CollectorBuilder;
6+
import io.prometheus.metrics.model.registry.PrometheusRegistry;
7+
import io.prometheus.metrics.model.registry.PrometheusScrapeRequest;
8+
import io.prometheus.metrics.model.snapshots.*;
89

910
import java.util.Arrays;
1011
import java.util.List;
12+
import java.util.function.Predicate;
1113

1214
/**
1315
* Almost all metrics have fixed metadata, i.e. the metric name is known when the metric is created.
@@ -30,6 +32,15 @@ protected MetricMetadata getMetadata() {
3032
return metadata;
3133
}
3234

35+
protected abstract MetricSnapshot collect();
36+
37+
public MetricSnapshots collect(Predicate<String> includedNames, PrometheusScrapeRequest scrapeRequest) {
38+
if(includedNames.test(this.metadata.getPrometheusName()))
39+
return MetricSnapshots.of(collect());
40+
else
41+
return MetricSnapshots.empty();
42+
}
43+
3344
private String makeName(String name, Unit unit) {
3445
if (unit != null) {
3546
if (!name.endsWith(unit.toString())) {
@@ -39,11 +50,6 @@ private String makeName(String name, Unit unit) {
3950
return name;
4051
}
4152

42-
@Override
43-
public String getPrometheusName() {
44-
return metadata.getPrometheusName();
45-
}
46-
4753
public static abstract class Builder<B extends Builder<B, M>, M extends MetricWithFixedMetadata> extends Metric.Builder<B, M> {
4854

4955
protected String name;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package io.prometheus.metrics.core.metrics;
2+
3+
import io.prometheus.metrics.model.registry.MetricNameFilter;
4+
import io.prometheus.metrics.model.registry.PrometheusRegistry;
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import java.util.concurrent.atomic.AtomicInteger;
9+
10+
public class NameFilterTest {
11+
@Test
12+
public void testCounterWithCallback() {
13+
AtomicInteger accessCount = new AtomicInteger();
14+
CounterWithCallback metrics = CounterWithCallback.builder()
15+
.name("my_counter")
16+
.callback(cb -> {
17+
accessCount.incrementAndGet();
18+
cb.call(1.0);
19+
})
20+
.build();
21+
22+
23+
PrometheusRegistry registry = new PrometheusRegistry();
24+
registry.register(metrics);
25+
26+
var result1 = registry.scrape(MetricNameFilter.builder().nameMustBeEqualTo("XXX").build());
27+
Assert.assertEquals(accessCount.get(), 0);
28+
Assert.assertTrue(result1.stream().toList().isEmpty());
29+
30+
var result2 = registry.scrape(MetricNameFilter.builder().nameMustBeEqualTo("my_counter").build());
31+
Assert.assertEquals(accessCount.get(), 1);
32+
Assert.assertEquals(result2.stream().toList().size(), 1);
33+
Assert.assertEquals(result2.get(0).getMetadata().getPrometheusName(), "my_counter");
34+
}
35+
36+
@Test
37+
public void testGaugeWithCallback() {
38+
AtomicInteger accessCount = new AtomicInteger();
39+
GaugeWithCallback metrics = GaugeWithCallback.builder()
40+
.name("my_gauge")
41+
.callback(cb -> {
42+
accessCount.incrementAndGet();
43+
cb.call(1.0);
44+
})
45+
.build();
46+
47+
48+
PrometheusRegistry registry = new PrometheusRegistry();
49+
registry.register(metrics);
50+
51+
var result1 = registry.scrape(MetricNameFilter.builder().nameMustBeEqualTo("XXX").build());
52+
Assert.assertEquals(accessCount.get(), 0);
53+
Assert.assertTrue(result1.stream().toList().isEmpty());
54+
55+
var result2 = registry.scrape(MetricNameFilter.builder().nameMustBeEqualTo("my_gauge").build());
56+
Assert.assertEquals(accessCount.get(), 1);
57+
Assert.assertEquals(result2.stream().toList().size(), 1);
58+
Assert.assertEquals(result2.get(0).getMetadata().getPrometheusName(), "my_gauge");
59+
}
60+
61+
}

prometheus-metrics-exporter-common/src/main/java/io/prometheus/metrics/exporter/common/PrometheusScrapeHandler.java

+6-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.prometheus.metrics.config.PrometheusProperties;
55
import io.prometheus.metrics.expositionformats.ExpositionFormatWriter;
66
import io.prometheus.metrics.expositionformats.ExpositionFormats;
7+
import io.prometheus.metrics.model.registry.Collector;
78
import io.prometheus.metrics.model.registry.MetricNameFilter;
89
import io.prometheus.metrics.model.registry.PrometheusRegistry;
910
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
@@ -23,7 +24,7 @@
2324
*/
2425
public class PrometheusScrapeHandler {
2526

26-
private final PrometheusRegistry registry;
27+
private final Collector registry;
2728
private final ExpositionFormats expositionFormats;
2829
private final Predicate<String> nameFilter;
2930
private AtomicInteger lastResponseSize = new AtomicInteger(2 << 9); // 0.5 MB
@@ -32,15 +33,15 @@ public PrometheusScrapeHandler() {
3233
this(PrometheusProperties.get(), PrometheusRegistry.defaultRegistry);
3334
}
3435

35-
public PrometheusScrapeHandler(PrometheusRegistry registry) {
36+
public PrometheusScrapeHandler(Collector registry) {
3637
this(PrometheusProperties.get(), registry);
3738
}
3839

3940
public PrometheusScrapeHandler(PrometheusProperties config) {
4041
this(config, PrometheusRegistry.defaultRegistry);
4142
}
4243

43-
public PrometheusScrapeHandler(PrometheusProperties config, PrometheusRegistry registry) {
44+
public PrometheusScrapeHandler(PrometheusProperties config, Collector registry) {
4445
this.expositionFormats = ExpositionFormats.init(config.getExporterProperties());
4546
this.registry = registry;
4647
this.nameFilter = makeNameFilter(config.getExporterFilterProperties());
@@ -106,15 +107,11 @@ private Predicate<String> makeNameFilter(ExporterFilterProperties props) {
106107
private MetricSnapshots scrape(PrometheusHttpRequest request) {
107108

108109
Predicate<String> filter = makeNameFilter(request.getParameterValues("name[]"));
109-
if (filter != null) {
110-
return registry.scrape(filter, request);
111-
} else {
112-
return registry.scrape(request);
113-
}
110+
return registry.collect(filter, request);
114111
}
115112

116113
private Predicate<String> makeNameFilter(String[] includedNames) {
117-
Predicate<String> result = null;
114+
Predicate<String> result = MetricNameFilter.ALLOW_ALL;
118115
if (includedNames != null && includedNames.length > 0) {
119116
result = MetricNameFilter.builder().nameMustBeEqualTo(includedNames).build();
120117
}

prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/MetricsHandler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.sun.net.httpserver.HttpHandler;
55
import io.prometheus.metrics.config.PrometheusProperties;
66
import io.prometheus.metrics.exporter.common.PrometheusScrapeHandler;
7+
import io.prometheus.metrics.model.registry.Collector;
78
import io.prometheus.metrics.model.registry.PrometheusRegistry;
89

910
import java.io.ByteArrayOutputStream;
@@ -26,7 +27,7 @@ public MetricsHandler() {
2627
prometheusScrapeHandler = new PrometheusScrapeHandler();
2728
}
2829

29-
public MetricsHandler(PrometheusRegistry registry) {
30+
public MetricsHandler(Collector registry) {
3031
prometheusScrapeHandler = new PrometheusScrapeHandler(registry);
3132
}
3233

prometheus-metrics-instrumentation-jvm/pom.xml

+12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919
<properties>
2020
<automatic.module.name>io.prometheus.metrics.instrumentation.jvm</automatic.module.name>
2121
</properties>
22+
<build>
23+
<plugins>
24+
<plugin>
25+
<groupId>org.apache.maven.plugins</groupId>
26+
<artifactId>maven-compiler-plugin</artifactId>
27+
<configuration>
28+
<source>10</source>
29+
<target>10</target>
30+
</configuration>
31+
</plugin>
32+
</plugins>
33+
</build>
2234

2335
<licenses>
2436
<license>

0 commit comments

Comments
 (0)