Skip to content

Commit 66f4dc8

Browse files
authored
make Protobuf optional (#1190)
* make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * make protobuf optional Signed-off-by: Gregor Zeitlinger <[email protected]> * plugin management Signed-off-by: Gregor Zeitlinger <[email protected]> * smoke test Signed-off-by: Gregor Zeitlinger <[email protected]> * smoke test Signed-off-by: Gregor Zeitlinger <[email protected]> * smoke test Signed-off-by: Gregor Zeitlinger <[email protected]> * smoke test Signed-off-by: Gregor Zeitlinger <[email protected]> * release automation Signed-off-by: Gregor Zeitlinger <[email protected]> * cache delegate Signed-off-by: Gregor Zeitlinger <[email protected]> * annotations should be provided Signed-off-by: Gregor Zeitlinger <[email protected]> * fix rebase Signed-off-by: Gregor Zeitlinger <[email protected]> * fix rebase Signed-off-by: Gregor Zeitlinger <[email protected]> * checkstyle Signed-off-by: Gregor Zeitlinger <[email protected]> * add docs Signed-off-by: Gregor Zeitlinger <[email protected]> --------- Signed-off-by: Gregor Zeitlinger <[email protected]>
1 parent 03609eb commit 66f4dc8

File tree

57 files changed

+987
-342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+987
-342
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ jobs:
2525
PROTO_GENERATION: true
2626
REQUIRE_PROTO_UP_TO_DATE: true
2727
run: |
28-
echo "Java version: $(java -version) in $(which java), Maven version: $(mvn -v)"
29-
echo "JAVA_HOME: $JAVA_HOME"
28+
mvn -v
3029
./mvnw clean install
3130
./mvnw javadoc:javadoc -P javadoc # just to check if javadoc is generated

.github/workflows/native-tests.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: GraalVM Native Tests
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
native-tests:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- name: Set up JDK
15+
uses: actions/setup-java@v4
16+
with:
17+
java-version: '21'
18+
distribution: graalvm
19+
cache: 'maven'
20+
- name: Run the Maven verify phase
21+
run: ./scripts/run-native-tests.sh

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
cache: 'maven'
2929

3030
- name: Build with Maven
31-
run: mvn -B package -P release -Dmaven.test.skip=true
31+
run: ./scripts/build-release.sh ${{ github.ref_name }}
3232

3333
- name: Set up Apache Maven Central
3434
uses: actions/setup-java@v4

RELEASING.md

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
## Update Version
2-
3-
In a new PR, update the version in `pom.xml` using
4-
5-
```shell
6-
mvn versions:set -DnewVersion=<VERSION>
7-
```
8-
9-
Commit the changes and open a PR.
10-
111
## Create a Release
122

133
1. Go to https://github.com/prometheus/client_java/releases

docs/content/exporters/formats.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,35 @@ All exporters the following exposition formats:
1111

1212
Moreover, gzip encoding is supported for each of these formats.
1313

14-
Scraping with a Prometheus server
15-
---------------------------------
14+
## Scraping with a Prometheus server
1615

1716
The Prometheus server sends an `Accept` header to specify which format is requested. By default, the Prometheus server will scrape OpenMetrics text format with gzip encoding. If the Prometheus server is started with `--enable-feature=native-histograms`, it will scrape Prometheus protobuf format instead.
1817

19-
Viewing with a Web Browser
20-
--------------------------
18+
## Viewing with a Web Browser
2119

2220
If you view the `/metrics` endpoint with your Web browser you will see Prometheus text format. For quick debugging of the other formats, exporters provide a `debug` URL parameter:
2321

2422
* `/metrics?debug=openmetrics`: View OpenMetrics text format.
2523
* `/metrics?debug=text`: View Prometheus text format.
2624
* `/metrics?debug=prometheus-protobuf`: View a text representation of the Prometheus protobuf format.
25+
26+
## Exclude protobuf exposition format
27+
28+
You can exclude the protobuf exposition format by including the
29+
`prometheus-metrics-exposition-textformats` module and excluding the
30+
`prometheus-metrics-exposition-formats` module in your build file.
31+
32+
For example, in Maven:
33+
34+
```xml
35+
<dependency>
36+
<groupId>io.prometheus</groupId>
37+
<artifactId>prometheus-metrics-exporter-httpserver</artifactId>
38+
<exclusions>
39+
<exclusion>
40+
<groupId>io.prometheus</groupId>
41+
<artifactId>prometheus-metrics-exposition-formats</artifactId>
42+
</exclusion>
43+
</exclusions>
44+
</dependency>
45+
```

docs/content/getting-started/quickstart.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ implementation 'io.prometheus:prometheus-metrics-exporter-httpserver:$version'
4545

4646
There are alternative exporters as well, for example if you are using a Servlet container like Tomcat or Undertow you might want to use `prometheus-exporter-servlet-jakarta` rather than a standalone HTTP server.
4747

48+
{{< hint type=note >}}
49+
50+
If you do not use the protobuf exposition format, you can
51+
[exclude](../../exporters/formats#exclude-protobuf-exposition-format)
52+
it from the dependencies.
53+
54+
{{< /hint >}}
55+
4856
# Dependency management
4957

5058
A Bill of Material

docs/content/internals/model.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,23 @@ The illustration below shows the internal architecture of the Prometheus Java cl
77

88
![Internal architecture of the Prometheus Java client library](/client_java/images/model.png)
99

10-
prometheus-metrics-core
11-
-----------------------
10+
## prometheus-metrics-core
1211

1312
This is the user facing metrics library, implementing the core metric types, like [Counter](/client_java/api/io/prometheus/metrics/core/metrics/Counter.html), [Gauge](/client_java/api/io/prometheus/metrics/core/metrics/Gauge.html) [Histogram](/client_java/api/io/prometheus/metrics/core/metrics/Histogram.html), and so on.
1413

1514
All metric types implement the [Collector](/client_java/api/io/prometheus/metrics/model/registry/Collector.html) interface, i.e. they provide a [collect()](/client_java/api/io/prometheus/metrics/model/registry/Collector.html#collect()) method to produce snapshots.
1615

17-
prometheus-metrics-model
18-
------------------------
16+
## prometheus-metrics-model
1917

2018
The model is an internal library, implementing read-only immutable snapshots. These snapshots are returned by the [Collector.collect()](/client_java/api/io/prometheus/metrics/model/registry/Collector.html#collect()) method.
2119

2220
There is no need for users to use `prometheus-metrics-model` directly. Users should use the API provided by `prometheus-metrics-core`, which includes the core metrics as well as callback metrics.
2321

2422
However, maintainers of 3rd party metrics libraries might want to use `prometheus-metrics-model` if they want to add Prometheus exposition formats to their metrics library.
2523

26-
exporters and exposition formats
27-
--------------------------------
24+
## Exporters and exposition formats
2825

2926
The `prometheus-metrics-exposition-formats` module converts snapshots to Prometheus exposition formats, like text format, OpenMetrics text format, or Prometheus protobuf format.
3027

3128
The exporters like `prometheus-metrics-exporter-httpserver` or `prometheus-metrics-exporter-servlet-jakarta` use this to convert snapshots into the right format depending on the `Accept` header in the scrape request.
29+

integration-tests/it-common/pom.xml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<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">
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
34
<modelVersion>4.0.0</modelVersion>
45

56
<parent>
@@ -11,11 +12,18 @@
1112
<artifactId>it-common</artifactId>
1213

1314
<name>Integration Tests - Common Utilities</name>
14-
<url>http://github.com/prometheus/client_java</url>
1515
<description>
1616
Common utilities for integration tests
1717
</description>
1818

19+
<dependencies>
20+
<dependency>
21+
<groupId>io.prometheus</groupId>
22+
<artifactId>prometheus-metrics-exposition-formats</artifactId>
23+
<version>${project.version}</version>
24+
</dependency>
25+
</dependencies>
26+
1927
<build>
2028
<testResources>
2129
<testResource>
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package io.prometheus.client.it.common;
2+
3+
import static java.nio.charset.StandardCharsets.UTF_8;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.assertj.core.api.Assertions.fail;
6+
7+
import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_28_3.Metrics;
8+
import java.io.ByteArrayInputStream;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.net.HttpURLConnection;
12+
import java.net.URISyntaxException;
13+
import java.net.URL;
14+
import java.util.ArrayList;
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Locale;
18+
import java.util.Map;
19+
import java.util.concurrent.TimeUnit;
20+
import java.util.zip.GZIPInputStream;
21+
import org.apache.commons.io.IOUtils;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.testcontainers.containers.BindMode;
24+
import org.testcontainers.containers.GenericContainer;
25+
26+
public abstract class ExporterTest {
27+
private final GenericContainer<?> sampleAppContainer;
28+
private final Volume sampleAppVolume;
29+
protected final String sampleApp;
30+
31+
public ExporterTest(String sampleApp) throws IOException, URISyntaxException {
32+
this.sampleApp = sampleApp;
33+
this.sampleAppVolume =
34+
Volume.create("it-exporter")
35+
.copy("../../it-" + sampleApp + "/target/" + sampleApp + ".jar");
36+
this.sampleAppContainer =
37+
new GenericContainer<>("openjdk:17")
38+
.withFileSystemBind(sampleAppVolume.getHostPath(), "/app", BindMode.READ_ONLY)
39+
.withWorkingDirectory("/app")
40+
.withLogConsumer(LogConsumer.withPrefix(sampleApp))
41+
.withExposedPorts(9400);
42+
}
43+
44+
// @BeforeEach?
45+
protected void start() {
46+
start("success");
47+
}
48+
49+
protected void start(String outcome) {
50+
sampleAppContainer
51+
.withCommand("java", "-jar", "/app/" + sampleApp + ".jar", "9400", outcome)
52+
.start();
53+
}
54+
55+
@AfterEach
56+
public void tearDown() throws IOException {
57+
sampleAppContainer.stop();
58+
sampleAppVolume.remove();
59+
}
60+
61+
public static void assertContentType(String expected, String actual) {
62+
if (!expected.replace(" ", "").equals(actual)) {
63+
assertThat(actual).isEqualTo(expected);
64+
}
65+
}
66+
67+
protected Response scrape(String method, String queryString, String... requestHeaders)
68+
throws IOException {
69+
return scrape(
70+
method,
71+
new URL(
72+
"http://localhost:"
73+
+ sampleAppContainer.getMappedPort(9400)
74+
+ "/metrics?"
75+
+ queryString),
76+
requestHeaders);
77+
}
78+
79+
public static Response scrape(String method, URL url, String... requestHeaders)
80+
throws IOException {
81+
long timeoutMillis = TimeUnit.SECONDS.toMillis(5);
82+
HttpURLConnection con = (HttpURLConnection) url.openConnection();
83+
con.setRequestMethod(method);
84+
for (int i = 0; i < requestHeaders.length; i += 2) {
85+
con.setRequestProperty(requestHeaders[i], requestHeaders[i + 1]);
86+
}
87+
long start = System.currentTimeMillis();
88+
Exception exception = null;
89+
while (System.currentTimeMillis() - start < timeoutMillis) {
90+
try {
91+
if (con.getResponseCode() == 200) {
92+
return new Response(
93+
con.getResponseCode(),
94+
con.getHeaderFields(),
95+
IOUtils.toByteArray(con.getInputStream()));
96+
} else {
97+
return new Response(
98+
con.getResponseCode(),
99+
con.getHeaderFields(),
100+
IOUtils.toByteArray(con.getErrorStream()));
101+
}
102+
} catch (Exception e) {
103+
exception = e;
104+
try {
105+
Thread.sleep(100);
106+
} catch (InterruptedException ignored) {
107+
// ignore
108+
}
109+
}
110+
}
111+
if (exception != null) {
112+
exception.printStackTrace();
113+
}
114+
fail("timeout while getting metrics from " + url);
115+
return null; // will not happen
116+
}
117+
118+
public static class Response {
119+
public final int status;
120+
private final Map<String, String> headers;
121+
public final byte[] body;
122+
123+
private Response(int status, Map<String, List<String>> headers, byte[] body) {
124+
this.status = status;
125+
this.headers = new HashMap<>(headers.size());
126+
this.body = body;
127+
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
128+
if (entry.getKey()
129+
!= null) { // HttpUrlConnection uses pseudo key "null" for the status line
130+
this.headers.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue().get(0));
131+
}
132+
}
133+
}
134+
135+
public String getHeader(String name) {
136+
// HTTP headers are case-insensitive
137+
return headers.get(name.toLowerCase(Locale.ROOT));
138+
}
139+
140+
public String stringBody() {
141+
return new String(body, UTF_8);
142+
}
143+
144+
public String gzipBody() throws IOException {
145+
return new String(
146+
IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(body))), UTF_8);
147+
}
148+
149+
public List<Metrics.MetricFamily> protoBody() throws IOException {
150+
List<Metrics.MetricFamily> metrics = new ArrayList<>();
151+
InputStream in = new ByteArrayInputStream(body);
152+
while (in.available() > 0) {
153+
metrics.add(Metrics.MetricFamily.parseDelimitedFrom(in));
154+
}
155+
return metrics;
156+
}
157+
}
158+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>io.prometheus</groupId>
8+
<artifactId>it-exporter</artifactId>
9+
<version>1.3.3</version>
10+
</parent>
11+
12+
<artifactId>it-exporter-no-protobuf</artifactId>
13+
14+
<name>Integration Tests - HTTPServer Exporter Sample - no protobuf</name>
15+
<description>
16+
HTTPServer Sample for the Exporter Integration Test without protobuf
17+
</description>
18+
19+
<dependencies>
20+
<dependency>
21+
<groupId>io.prometheus</groupId>
22+
<artifactId>prometheus-metrics-exporter-httpserver</artifactId>
23+
<version>${project.version}</version>
24+
<exclusions>
25+
<exclusion>
26+
<groupId>io.prometheus</groupId>
27+
<artifactId>prometheus-metrics-exposition-formats</artifactId>
28+
</exclusion>
29+
</exclusions>
30+
</dependency>
31+
<dependency>
32+
<groupId>io.prometheus</groupId>
33+
<artifactId>prometheus-metrics-core</artifactId>
34+
<version>${project.version}</version>
35+
<exclusions>
36+
<exclusion>
37+
<groupId>io.prometheus</groupId>
38+
<artifactId>prometheus-metrics-exposition-formats</artifactId>
39+
</exclusion>
40+
</exclusions>
41+
</dependency>
42+
</dependencies>
43+
44+
<build>
45+
<finalName>exporter-no-protobuf</finalName>
46+
<plugins>
47+
<plugin>
48+
<groupId>org.apache.maven.plugins</groupId>
49+
<artifactId>maven-shade-plugin</artifactId>
50+
<executions>
51+
<execution>
52+
<phase>package</phase>
53+
<goals>
54+
<goal>shade</goal>
55+
</goals>
56+
<configuration>
57+
<transformers>
58+
<transformer
59+
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
60+
<mainClass>io.prometheus.metrics.it.exporter.httpserver.HTTPServerSample</mainClass>
61+
</transformer>
62+
</transformers>
63+
</configuration>
64+
</execution>
65+
</executions>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
</project>

0 commit comments

Comments
 (0)