Skip to content

Commit ccfdc38

Browse files
BAEL-8410 - Guide to Prometheus Java Client (#17823)
* BAEL-7255 - Implementing GraphQL Mutation without Returning Data * BAEL-7615 - Implement the Builder Pattern in Java 8 * BAEL-7615 - Implement the Builder Pattern in Java 8 * BAEL-7615 - review * BAEL-7780 - A Guide to Micrometer in Quarkus * fix build * fix build * editor review * editor review * fix build * typo * Revert "typo" This reverts commit fabb043. * typo * add version * add version * BAEL-8091 - Getting started with MongoDB and Quarkus * BAEL-8301 - How to Consume REST API in Quarkus * BAEL-7615 - Implement the Builder Pattern in Java 8 * BAEL-7615 - review * BAEL-7780 - A Guide to Micrometer in Quarkus * fix build * fix build * editor review * editor review * typo * Revert "typo" This reverts commit fabb043. * typo * BAEL-8301 - How to Consume REST API in Quarkus * BAEL-8301 - How to Consume REST API in Quarkus * BAEL-8301 - How to Consume REST API in Quarkus * BAEL-8301 - How to Consume REST API in Quarkus * comment module * fix build * downgrade version * downgrade version * format & added tests * format 2 * format 4 * BAEL-8410 - Guide to Prometheus Java Client * BAEL-8410 - rename test
1 parent 3640bb0 commit ccfdc38

File tree

3 files changed

+306
-0
lines changed

3 files changed

+306
-0
lines changed

metrics/pom.xml

+21
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,27 @@
8080
<artifactId>spectator-api</artifactId>
8181
<version>${spectator-api.version}</version>
8282
</dependency>
83+
<dependency>
84+
<groupId>io.prometheus</groupId>
85+
<artifactId>prometheus-metrics-core</artifactId>
86+
<version>1.0.0</version>
87+
</dependency>
88+
<dependency>
89+
<groupId>io.prometheus</groupId>
90+
<artifactId>prometheus-metrics-instrumentation-jvm</artifactId>
91+
<version>1.0.0</version>
92+
</dependency>
93+
<dependency>
94+
<groupId>io.prometheus</groupId>
95+
<artifactId>prometheus-metrics-exporter-httpserver</artifactId>
96+
<version>1.0.0</version>
97+
</dependency>
98+
<dependency>
99+
<groupId>org.junit.jupiter</groupId>
100+
<artifactId>junit-jupiter-api</artifactId>
101+
<version>5.11.0-M2</version>
102+
<scope>test</scope>
103+
</dependency>
83104
</dependencies>
84105

85106
<properties>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.baeldung.metrics.prometheus;
2+
3+
import java.io.IOException;
4+
import java.util.Random;
5+
6+
import io.prometheus.metrics.core.metrics.Counter;
7+
import io.prometheus.metrics.core.metrics.Gauge;
8+
import io.prometheus.metrics.core.metrics.Histogram;
9+
import io.prometheus.metrics.core.metrics.Info;
10+
import io.prometheus.metrics.core.metrics.StateSet;
11+
import io.prometheus.metrics.core.metrics.Summary;
12+
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
13+
import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
14+
15+
public class PrometheusApp {
16+
17+
public static void main(String[] args) throws InterruptedException, IOException {
18+
19+
JvmMetrics.builder().register();
20+
21+
HTTPServer server = HTTPServer.builder()
22+
.port(9400)
23+
.buildAndStart();
24+
25+
Counter requestCounter = Counter.builder()
26+
.name("http_requests_total")
27+
.help("Total number of HTTP requests")
28+
.labelNames("method", "status")
29+
.register();
30+
31+
requestCounter.labelValues("GET", "200").inc();
32+
33+
Gauge memoryUsage = Gauge.builder()
34+
.name("memory_usage_bytes")
35+
.help("Current memory usage in bytes")
36+
.register();
37+
38+
memoryUsage.set(5000000);
39+
40+
Histogram requestLatency = Histogram.builder()
41+
.name("http_request_latency_seconds")
42+
.help("Tracks HTTP request latency in seconds")
43+
.labelNames("method")
44+
.register();
45+
46+
Random random = new Random();
47+
for (int i = 0; i < 100; i++) {
48+
double latency = 0.1 + (3 * random.nextDouble());
49+
requestLatency.labelValues("GET").observe(latency);
50+
}
51+
52+
Summary requestDuration = Summary.builder()
53+
.name("http_request_duration_seconds")
54+
.help("Tracks the duration of HTTP requests in seconds")
55+
.quantile(0.5, 0.05)
56+
.quantile(0.9, 0.01)
57+
.register();
58+
59+
for (int i = 0; i < 100; i++) {
60+
double duration = 0.05 + (2 * random.nextDouble());
61+
requestDuration.observe(duration);
62+
}
63+
64+
Info appInfo = Info.builder()
65+
.name("app_info")
66+
.help("Application version information")
67+
.labelNames("version", "build")
68+
.register();
69+
70+
appInfo.addLabelValues("1.0.0", "12345");
71+
72+
StateSet stateSet = StateSet.builder()
73+
.name("feature_flags")
74+
.help("Feature flags")
75+
.labelNames("env")
76+
.states("feature1")
77+
.register();
78+
79+
stateSet.labelValues("dev").setFalse("feature1");
80+
81+
System.out.println("HTTPServer listening on http://localhost:" + server.getPort() + "/metrics");
82+
83+
Thread.currentThread().join();
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package com.baeldung.metrics.prometheus;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import java.io.BufferedReader;
6+
import java.io.IOException;
7+
import java.io.InputStreamReader;
8+
import java.net.HttpURLConnection;
9+
import java.net.URL;
10+
11+
import org.junit.jupiter.api.AfterEach;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
import io.prometheus.metrics.core.metrics.Counter;
16+
import io.prometheus.metrics.core.metrics.Gauge;
17+
import io.prometheus.metrics.core.metrics.Histogram;
18+
import io.prometheus.metrics.core.metrics.Info;
19+
import io.prometheus.metrics.core.metrics.StateSet;
20+
import io.prometheus.metrics.core.metrics.Summary;
21+
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
22+
import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
23+
import io.prometheus.metrics.model.registry.PrometheusRegistry;
24+
25+
class PrometheusAppUnitTest {
26+
27+
private Counter requestCounter;
28+
29+
private Gauge memoryUsage;
30+
31+
private Histogram requestLatency;
32+
33+
private Summary requestDuration;
34+
35+
private Info appInfo;
36+
37+
private StateSet stateSet;
38+
39+
private HTTPServer httpServer;
40+
41+
@BeforeEach
42+
void setUp() throws IOException {
43+
44+
// Initialize JVM Metrics
45+
JvmMetrics.builder().register();
46+
47+
// Initialize HTTP Server
48+
httpServer = HTTPServer.builder().port(9400).buildAndStart();
49+
50+
51+
// Initialize all the metrics within the new registry
52+
requestCounter = Counter.builder()
53+
.name("http_requests_total")
54+
.help("Total number of HTTP requests")
55+
.labelNames("method", "status")
56+
.register();
57+
58+
memoryUsage = Gauge.builder()
59+
.name("memory_usage_bytes")
60+
.help("Current memory usage in bytes")
61+
.register();
62+
63+
requestLatency = Histogram.builder()
64+
.name("http_request_latency_seconds")
65+
.help("Tracks HTTP request latency in seconds")
66+
.labelNames("method")
67+
.register();
68+
69+
requestDuration = Summary.builder()
70+
.name("http_request_duration_seconds")
71+
.help("Tracks the duration of HTTP requests in seconds")
72+
.quantile(0.5, 0.05)
73+
.quantile(0.9, 0.01)
74+
.register();
75+
76+
appInfo = Info.builder()
77+
.name("app_info")
78+
.help("Application version information")
79+
.labelNames("version", "build")
80+
.register();
81+
82+
stateSet = StateSet.builder()
83+
.name("feature_flags")
84+
.help("Feature flags")
85+
.labelNames("env")
86+
.states("feature1")
87+
.register();
88+
}
89+
90+
91+
@AfterEach
92+
void tearDown() {
93+
if (httpServer != null) {
94+
httpServer.stop(); // Stop the server after each test
95+
}
96+
PrometheusRegistry.defaultRegistry.unregister(requestCounter);
97+
PrometheusRegistry.defaultRegistry.unregister(memoryUsage);
98+
PrometheusRegistry.defaultRegistry.unregister(requestLatency);
99+
PrometheusRegistry.defaultRegistry.unregister(requestDuration);
100+
PrometheusRegistry.defaultRegistry.unregister(appInfo);
101+
PrometheusRegistry.defaultRegistry.unregister(stateSet);
102+
}
103+
104+
@Test
105+
void givenCounter_whenIncremented_thenMetricExposedCorrectly() throws IOException {
106+
// given
107+
requestCounter.labelValues("GET", "200").inc();
108+
109+
// when
110+
String metrics = fetchMetricsFromEndpoint();
111+
112+
// then
113+
assertTrue(metrics.contains("http_requests_total{method=\"GET\",status=\"200\"}"));
114+
}
115+
116+
@Test
117+
void givenGauge_whenSet_thenMetricExposedCorrectly() throws IOException {
118+
// given
119+
memoryUsage.set(5000000);
120+
121+
// when
122+
String metrics = fetchMetricsFromEndpoint();
123+
124+
// then
125+
assertTrue(metrics.contains("memory_usage_bytes 5000000"));
126+
}
127+
128+
@Test
129+
void givenHistogram_whenObserved_thenMetricExposedCorrectly() throws IOException {
130+
// given
131+
requestLatency.labelValues("GET").observe(0.25);
132+
133+
// when
134+
String metrics = fetchMetricsFromEndpoint();
135+
136+
// then
137+
assertTrue(metrics.contains("http_request_latency_seconds"));
138+
assertTrue(metrics.contains("http_request_latency_seconds_sum"));
139+
assertTrue(metrics.contains("http_request_latency_seconds_count"));
140+
}
141+
142+
@Test
143+
void givenSummary_whenObserved_thenMetricExposedCorrectly() throws IOException {
144+
// given
145+
requestDuration.observe(0.15);
146+
147+
// when
148+
String metrics = fetchMetricsFromEndpoint();
149+
150+
// then
151+
assertTrue(metrics.contains("http_request_duration_seconds"));
152+
assertTrue(metrics.contains("http_request_duration_seconds_sum"));
153+
assertTrue(metrics.contains("http_request_duration_seconds_count"));
154+
}
155+
156+
@Test
157+
void givenInfo_whenSet_thenMetricExposedCorrectly() throws IOException {
158+
// given
159+
appInfo.addLabelValues("1.0.0", "12345");
160+
161+
// when
162+
String metrics = fetchMetricsFromEndpoint();
163+
164+
// then
165+
assertTrue(metrics.contains("app_info{build=\"12345\",version=\"1.0.0\"} 1"));
166+
}
167+
168+
@Test
169+
void givenStateSet_whenSetFalse_thenMetricExposedCorrectly() throws IOException {
170+
// given
171+
stateSet.labelValues("dev").setFalse("feature1");
172+
173+
// when
174+
String metrics = fetchMetricsFromEndpoint();
175+
176+
// then
177+
assertTrue(metrics.contains("feature_flags{env=\"dev\",feature_flags=\"feature1\"} 0"));
178+
}
179+
180+
private String fetchMetricsFromEndpoint() throws IOException {
181+
URL url = new URL("http://localhost:9400/metrics");
182+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
183+
connection.setRequestMethod("GET");
184+
connection.setConnectTimeout(5000);
185+
connection.setReadTimeout(5000);
186+
187+
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
188+
String inputLine;
189+
StringBuilder content = new StringBuilder();
190+
191+
while ((inputLine = in.readLine()) != null) {
192+
content.append(inputLine).append("\n");
193+
}
194+
195+
in.close();
196+
connection.disconnect();
197+
198+
return content.toString();
199+
}
200+
}

0 commit comments

Comments
 (0)