-
Notifications
You must be signed in to change notification settings - Fork 804
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add multi-target pattern support Signed-off-by: Guido Anzuoni <ganzuoni@gmail.com>
- Loading branch information
Showing
14 changed files
with
503 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
--- | ||
title: Multi-Target Pattern | ||
weight: 7 | ||
--- | ||
|
||
{{< hint type=note >}} | ||
This is for the upcoming release 1.1.0. | ||
{{< /hint >}} | ||
|
||
To support multi-target pattern you can create a custom collector overriding the purposed internal method in ExtendedMultiCollector | ||
see SampleExtendedMultiCollector in io.prometheus.metrics.examples.httpserver | ||
|
||
```java | ||
public class SampleExtendedMultiCollector extends ExtendedMultiCollector { | ||
|
||
public SampleExtendedMultiCollector() { | ||
super(); | ||
} | ||
|
||
@Override | ||
protected MetricSnapshots collectMetricSnapshots(PrometheusScrapeRequest scrapeRequest) { | ||
|
||
GaugeSnapshot.Builder gaugeBuilder = GaugeSnapshot.builder(); | ||
gaugeBuilder.name("x_load").help("process load"); | ||
|
||
CounterSnapshot.Builder counterBuilder = CounterSnapshot.builder(); | ||
counterBuilder.name(PrometheusNaming.sanitizeMetricName("x_calls_total")).help("invocations"); | ||
|
||
String[] targetNames = scrapeRequest.getParameterValues("target"); | ||
String targetName; | ||
String[] procs = scrapeRequest.getParameterValues("proc"); | ||
if (targetNames == null || targetNames.length == 0) { | ||
targetName = "defaultTarget"; | ||
procs = null; //ignore procs param | ||
} else { | ||
targetName = targetNames[0]; | ||
} | ||
Builder counterDataPointBuilder = CounterSnapshot.CounterDataPointSnapshot.builder(); | ||
io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot.Builder gaugeDataPointBuilder = GaugeSnapshot.GaugeDataPointSnapshot.builder(); | ||
Labels lbls = Labels.of("target", targetName); | ||
|
||
if (procs == null || procs.length == 0) { | ||
counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc"))); | ||
gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc"))); | ||
counterDataPointBuilder.value(70); | ||
gaugeDataPointBuilder.value(Math.random()); | ||
|
||
counterBuilder.dataPoint(counterDataPointBuilder.build()); | ||
gaugeBuilder.dataPoint(gaugeDataPointBuilder.build()); | ||
|
||
} else { | ||
for (int i = 0; i < procs.length; i++) { | ||
counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i]))); | ||
gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i]))); | ||
counterDataPointBuilder.value(Math.random()); | ||
gaugeDataPointBuilder.value(Math.random()); | ||
|
||
counterBuilder.dataPoint(counterDataPointBuilder.build()); | ||
gaugeBuilder.dataPoint(gaugeDataPointBuilder.build()); | ||
} | ||
} | ||
Collection<MetricSnapshot> snaps = new ArrayList<MetricSnapshot>(); | ||
snaps.add(counterBuilder.build()); | ||
snaps.add(gaugeBuilder.build()); | ||
MetricSnapshots msnaps = new MetricSnapshots(snaps); | ||
return msnaps; | ||
} | ||
|
||
public List<String> getPrometheusNames() { | ||
List<String> names = new ArrayList<String>(); | ||
names.add("x_calls_total"); | ||
names.add("x_load"); | ||
return names; | ||
} | ||
|
||
} | ||
|
||
``` | ||
`PrometheusScrapeRequest` provides methods to access http-related infos from the request originally received by the endpoint | ||
|
||
```java | ||
public interface PrometheusScrapeRequest { | ||
String getRequestURI(); | ||
|
||
String[] getParameterValues(String name); | ||
} | ||
|
||
``` | ||
|
||
|
||
Sample Prometheus scrape_config | ||
|
||
``` | ||
- job_name: "multi-target" | ||
# metrics_path defaults to '/metrics' | ||
# scheme defaults to 'http'. | ||
params: | ||
proc: [proc1, proc2] | ||
relabel_configs: | ||
- source_labels: [__address__] | ||
target_label: __param_target | ||
- source_labels: [__param_target] | ||
target_label: instance | ||
- target_label: __address__ | ||
replacement: localhost:9401 | ||
static_configs: | ||
- targets: ["target1", "target2"] | ||
``` | ||
It's up to the specific MultiCollector implementation how to interpret the _target_ parameter. | ||
It might be an explicit real target (i.e. via host name/ip address) or as an alias in some internal configuration. | ||
The latter is more suitable when the MultiCollector implementation is a proxy (see https://github.com/prometheus/snmp_exporter) | ||
In this case, invoking real target might require extra parameters (e.g. credentials) that might be complex to manage in Prometheus configuration | ||
(not considering the case where the proxy might become an "open relay") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Multi-Target pattern example | ||
|
||
## Build | ||
|
||
This example is built as part of the `client_java` project. | ||
|
||
``` | ||
./mvnw package | ||
``` | ||
|
||
## Run | ||
|
||
The build creates a JAR file with the example application in `./examples/example-exporter-multi-target/target/`. | ||
|
||
``` | ||
java -jar ./examples/example-exporter-multi-target/target/example-exporter-multi-target.jar | ||
``` | ||
|
||
## Manually testing the Metrics Endpoint | ||
|
||
Accessing [http://localhost:9400/metrics](http://localhost:9400/metrics) with a Web browser should yield an example of a counter metric. | ||
|
||
``` | ||
# HELP uptime_seconds_total total number of seconds since this application was started | ||
# TYPE uptime_seconds_total counter | ||
uptime_seconds_total 301.0 | ||
``` | ||
|
||
The exporter supports a `debug` URL parameter to quickly view other formats in your Web browser: | ||
|
||
* [http://localhost:9400/metrics?debug=text](http://localhost:9400/metrics?debug=text): Prometheus text format, same as without the `debug` option. | ||
* [http://localhost:9400/metrics?debug=openmetrics](http://localhost:9400/metrics?debug=openmetrics): OpenMetrics text format. | ||
* [http://localhost:9400/metrics?debug=prometheus-protobuf](http://localhost:9400/metrics?debug=prometheus-protobuf): Text representation of the Prometheus protobuf format. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>examples</artifactId> | ||
<version>1.1.0-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>example-exporter-multi-target</artifactId> | ||
|
||
<name>Example - HTTPServer Exporter Multi Target</name> | ||
<description> | ||
Prometheus Metrics Example for multi-target pattern implementation | ||
</description> | ||
|
||
<licenses> | ||
<license> | ||
<name>The Apache Software License, Version 2.0</name> | ||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> | ||
<distribution>repo</distribution> | ||
</license> | ||
</licenses> | ||
|
||
<developers> | ||
<developer> | ||
<id>fstab</id> | ||
<name>Guido Anzuoni</name> | ||
<email>ganzuoni@gmail.com</email> | ||
</developer> | ||
</developers> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-core</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-instrumentation-jvm</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-exporter-httpserver</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<finalName>${project.artifactId}</finalName> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<transformers> | ||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | ||
<mainClass>io.prometheus.metrics.examples.multitarget.Main</mainClass> | ||
</transformer> | ||
</transformers> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
23 changes: 23 additions & 0 deletions
23
...-exporter-multi-target/src/main/java/io/prometheus/metrics/examples/multitarget/Main.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package io.prometheus.metrics.examples.multitarget; | ||
|
||
import java.io.IOException; | ||
|
||
import io.prometheus.metrics.exporter.httpserver.HTTPServer; | ||
import io.prometheus.metrics.model.registry.PrometheusRegistry; | ||
|
||
/** | ||
* Simple example of an application exposing metrics via Prometheus' built-in HTTPServer. | ||
*/ | ||
public class Main { | ||
|
||
public static void main(String[] args) throws IOException, InterruptedException { | ||
|
||
SampleMultiCollector xmc = new SampleMultiCollector(); | ||
PrometheusRegistry.defaultRegistry.register(xmc); | ||
HTTPServer server = HTTPServer.builder() | ||
.port(9401) | ||
.buildAndStart(); | ||
|
||
System.out.println("HTTPServer listening on port http://localhost:" + server.getPort() + "/metrics"); | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
...target/src/main/java/io/prometheus/metrics/examples/multitarget/SampleMultiCollector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package io.prometheus.metrics.examples.multitarget; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
import io.prometheus.metrics.model.registry.MultiCollector; | ||
import io.prometheus.metrics.model.registry.PrometheusScrapeRequest; | ||
import io.prometheus.metrics.model.snapshots.CounterSnapshot; | ||
import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot.Builder; | ||
import io.prometheus.metrics.model.snapshots.GaugeSnapshot; | ||
import io.prometheus.metrics.model.snapshots.Labels; | ||
import io.prometheus.metrics.model.snapshots.MetricSnapshot; | ||
import io.prometheus.metrics.model.snapshots.MetricSnapshots; | ||
import io.prometheus.metrics.model.snapshots.PrometheusNaming; | ||
|
||
public class SampleMultiCollector implements MultiCollector { | ||
|
||
public SampleMultiCollector() { | ||
super(); | ||
} | ||
|
||
@Override | ||
public MetricSnapshots collect() { | ||
return new MetricSnapshots(); | ||
} | ||
|
||
@Override | ||
public MetricSnapshots collect(PrometheusScrapeRequest scrapeRequest) { | ||
return collectMetricSnapshots(scrapeRequest); | ||
} | ||
|
||
protected MetricSnapshots collectMetricSnapshots(PrometheusScrapeRequest scrapeRequest) { | ||
|
||
GaugeSnapshot.Builder gaugeBuilder = GaugeSnapshot.builder(); | ||
gaugeBuilder.name("x_load").help("process load"); | ||
|
||
CounterSnapshot.Builder counterBuilder = CounterSnapshot.builder(); | ||
counterBuilder.name(PrometheusNaming.sanitizeMetricName("x_calls_total")).help("invocations"); | ||
|
||
String[] targetNames = scrapeRequest.getParameterValues("target"); | ||
String targetName; | ||
String[] procs = scrapeRequest.getParameterValues("proc"); | ||
if (targetNames == null || targetNames.length == 0) { | ||
targetName = "defaultTarget"; | ||
procs = null; //ignore procs param | ||
} else { | ||
targetName = targetNames[0]; | ||
} | ||
Builder counterDataPointBuilder = CounterSnapshot.CounterDataPointSnapshot.builder(); | ||
io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot.Builder gaugeDataPointBuilder = GaugeSnapshot.GaugeDataPointSnapshot.builder(); | ||
Labels lbls = Labels.of("target", targetName); | ||
|
||
if (procs == null || procs.length == 0) { | ||
counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc"))); | ||
gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc"))); | ||
counterDataPointBuilder.value(70); | ||
gaugeDataPointBuilder.value(Math.random()); | ||
|
||
counterBuilder.dataPoint(counterDataPointBuilder.build()); | ||
gaugeBuilder.dataPoint(gaugeDataPointBuilder.build()); | ||
|
||
} else { | ||
for (int i = 0; i < procs.length; i++) { | ||
counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i]))); | ||
gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i]))); | ||
counterDataPointBuilder.value(Math.random()); | ||
gaugeDataPointBuilder.value(Math.random()); | ||
|
||
counterBuilder.dataPoint(counterDataPointBuilder.build()); | ||
gaugeBuilder.dataPoint(gaugeDataPointBuilder.build()); | ||
} | ||
} | ||
Collection<MetricSnapshot> snaps = new ArrayList<MetricSnapshot>(); | ||
snaps.add(counterBuilder.build()); | ||
snaps.add(gaugeBuilder.build()); | ||
MetricSnapshots msnaps = new MetricSnapshots(snaps); | ||
return msnaps; | ||
} | ||
|
||
public List<String> getPrometheusNames() { | ||
List<String> names = new ArrayList<String>(); | ||
names.add("x_calls_total"); | ||
names.add("x_load"); | ||
return names; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.