Guide to Prometheus Java Client
Prometheus is an open-source monitoring solution designed for reliability and scalability. Let us delve into understanding the Java Prometheus client and how it can be used to expose and manage metrics in your applications.
1. Introduction
Prometheus is a powerful, open-source systems monitoring and alerting toolkit originally built at SoundCloud. It has become a cornerstone for monitoring modern cloud-native architectures and microservices due to its robust feature set and adaptability. Prometheus is widely adopted for its ability to provide deep insights into the performance, availability, and health of systems.
At its core, Prometheus operates by collecting metrics from configured targets at regular intervals. These metrics are exposed as HTTP endpoints by applications or services and stored in a time-series database for querying and analysis. The collected data can be visualized using tools like Grafana, enabling teams to make informed decisions based on real-time performance metrics.
1.1 Advantages
The primary advantages of Prometheus include:
- Rich Query Language (PromQL): A powerful language for querying and analyzing collected metrics.
- Efficient Data Model: Optimized for time-series data with built-in support for multi-dimensional labels.
- Alerting: Integration with Alertmanager for notifications based on pre-defined rules.
- Extensibility: Support for custom exporters to gather metrics from various sources.
1.2 Metrics Type
Metrics in Prometheus are classified into the following types:
- Counter: A monotonically increasing value used to count occurrences or events. Examples include total HTTP requests served or the number of failed login attempts.
- Gauge: A value that can fluctuate over time, such as CPU usage, memory consumption, or active connections in a system.
- Histogram: Measures the statistical distribution of values over a range, such as request durations or sizes of payloads. It provides insights into patterns and trends.
- Summary: Similar to histograms, but additionally computes quantiles (e.g., median or 95th percentile), making it ideal for identifying outliers and trends in performance.
Prometheus’s ability to collect and process these metrics allows teams to ensure application reliability, detect performance bottlenecks, and maintain high availability.
2. Prometheus on Docker and Setting up the Project
2.1 Prometheus Setup
To use Prometheus effectively, you need to configure it to scrape metrics from your target applications. The configuration is specified in a file called prometheus.yml
, which defines global parameters, scrape intervals, and scrape targets.
Create a prometheus.yml
file with the following configuration:
global: scrape_interval: 15s # The frequency at which metrics are scraped from targets scrape_configs: - job_name: 'java-app' # A logical name for the scrape target static_configs: - targets: ['host.docker.internal:8080'] # The HTTP endpoint exposing metrics
The above configuration defines a global scrape interval of 15 seconds and specifies a single target with the logical job name java-app
. The target is expected to expose its metrics on http://host.docker.internal:8080
.
Run Prometheus with Docker:
docker run -d -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
This command performs the following actions:
- Runs Prometheus in a detached state (
-d
). - Maps port 9090 on your host to the Prometheus container, enabling access to the Prometheus web interface at
http://localhost:9090
. - Mounts the configuration file from the current directory (
$(pwd)/prometheus.yml
) to the Prometheus container.
Once Prometheus is running, you can access its dashboard to view metrics and write queries using PromQL. This forms the foundation for monitoring your Java applications and visualizing system performance.
2.2 Project Setup
Create a new Java project and include the Prometheus Java Client library in your pom.xml
:
<dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient</artifactId> <version>your__jar__version</version> </dependency> <dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_hotspot</artifactId> <version>your__jar__version</version> </dependency> <dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_httpserver</artifactId> <version>your__jar__version</version> </dependency>
3. Exposing JVM Metrics in Java
To expose JVM metrics, use the simpleclient_hotspot
module:
import io.prometheus.client.hotspot.DefaultExports; import io.prometheus.client.exporter.HTTPServer; import java.io.IOException; public class JVMExporter { public static void main(String[] args) throws IOException { DefaultExports.initialize(); HTTPServer server = new HTTPServer(8080); System.out.println("JVM metrics exposed at http://localhost:8080/metrics"); } }
3.1 Code Explanation
The provided Java code sets up a simple application that exposes JVM (Java Virtual Machine) metrics for Prometheus to scrape. The DefaultExports.initialize()
method initializes default JVM metrics, such as memory usage, garbage collection statistics, and thread counts, which are collected by Prometheus. Next, an HTTP server is started on port 8080
using the HTTPServer
class, allowing the application to expose these metrics at the endpoint http://localhost:8080/metrics
. The System.out.println
statement confirms that the metrics are successfully exposed and provides the URL for access. This setup is commonly used to monitor the health and performance of Java applications.
3.2 Code Output
The code gives the following output when executed:
JVM metrics exposed at http://localhost:8080/metrics
4. Metric Types in Java
The MetricsExample
class demonstrates how to expose and update three types of Prometheus metrics using Java.
import io.prometheus.client.Counter; import io.prometheus.client.Gauge; import io.prometheus.client.Histogram; import io.prometheus.client.exporter.HTTPServer; public class MetricsExample { // Define a Counter metric to count HTTP requests static final Counter requests = Counter.build() .name("http_requests_total") // Metric name .help("Total HTTP requests") // Description of the metric .register(); // Register the counter with Prometheus // Define a Gauge metric to represent current temperature in Celsius static final Gauge temperature = Gauge.build() .name("current_temperature_celsius") // Metric name .help("Current temperature in Celsius") // Description of the metric .register(); // Register the gauge with Prometheus // Define a Histogram metric to track request latency in seconds static final Histogram requestLatency = Histogram.build() .name("request_latency_seconds") // Metric name .help("Request latency in seconds") // Description of the metric .register(); // Register the histogram with Prometheus public static void main(String[] args) throws Exception { // Start an HTTP server to expose metrics on port 8080 HTTPServer server = new HTTPServer(8080); System.out.println("Metrics are exposed at http://localhost:8080/metrics"); // Simulate a metric update for the Counter (incrementing HTTP requests) requests.inc(); // Increment the counter by 1 System.out.println("Counter incremented."); // Simulate a metric update for the Gauge (setting temperature) temperature.set(22.5); // Set the current temperature to 22.5 Celsius System.out.println("Gauge value set to 22.5 Celsius."); // Simulate a metric update for the Histogram (recording request latency) Histogram.Timer timer = requestLatency.startTimer(); // Start a timer to track the duration // Simulate some processing time (e.g., handling a request) Thread.sleep(500); // Simulate a 500ms delay timer.observeDuration(); // Record the observed duration of the request System.out.println("Request latency recorded."); } }
4.1 Code Explanation
The metrics used in the above code are: Counter, Gauge, and Histogram, each serving a different purpose in monitoring application behavior.
- The Counter metric is used to track cumulative events that increase over time. In this case, the code defines a
requests
counter to count HTTP requests. The counter is created using theCounter.build()
method, which sets the metric’s name ashttp_requests_total
and provides a description of its purpose as"Total HTTP requests"
. The counter is then registered with Prometheus using.register()
. Every time an HTTP request is handled, the counter is incremented by 1 usingrequests.inc()
. - The Gauge metric represents a value that can go up or down, such as a current measurement. In this example, a
temperature
gauge represents the current temperature in Celsius. The gauge is created with the namecurrent_temperature_celsius
and a description of"Current temperature in Celsius"
. It is also registered with Prometheus. The temperature is set to a specific value (22.5 Celsius) usingtemperature.set(22.5)
. - The Histogram metric measures the distribution of events over a specified range, such as the latency of requests. The code defines a
requestLatency
histogram to track the time it takes to process HTTP requests. The histogram is created with the namerequest_latency_seconds
and a description"Request latency in seconds"
. A timer is started usingrequestLatency.startTimer()
to measure the time taken for a simulated HTTP request. After a brief delay of 500 milliseconds (simulated processing time) usingThread.sleep(500)
, the duration of the request is recorded usingtimer.observeDuration()
.
The program starts an HTTP server on port 8080
using the HTTPServer
class from the Prometheus Java client. This allows Prometheus to scrape the exposed metrics at the URL http://localhost:8080/metrics
. The System.out.println()
statements in the code inform the user that the metrics have been incremented or set, and the metrics can be accessed via the Prometheus endpoint.
In summary, this Java program demonstrates how to expose Prometheus-compatible metrics, including counting HTTP requests, tracking dynamic values like temperature, and measuring the duration of requests using counters, gauges, and histograms. Prometheus can scrape these metrics to monitor the application’s performance and health over time.
4.2 Code Output
The code gives the following output when executed:
Metrics are exposed at http://localhost:8080/metrics Counter incremented. Gauge value set to 22.5 Celsius. Request latency recorded.
5. Conclusion
The Prometheus Java Client library provides an easy way to integrate custom and JVM metrics into your Java applications. By understanding metric types and using them effectively, you can build robust monitoring for your applications.