Monitoring applications is essential for ensuring performance, diagnosing issues, and optimizing resources. In the realm of Spring Boot, integrating Prometheus and MicroMeter for monitoring purposes offers powerful insights into application metrics and health. This article delves into the process of setting up Prometheus to monitor Spring Boot applications effectively.
Why Monitor Spring Boot with Prometheus?
Prometheus, an open-source monitoring system, excels in collecting and querying time-series data. Integrating Prometheus with Spring Boot provides real-time visibility into various metrics such as HTTP requests, memory usage, response times, and more. This invaluable data empowers developers and administrators to proactively manage, analyze, and optimize their Spring Boot applications.
In order to monitor Spring Boot with Prometheus we firstly need to enable Metrics in your Spring Boot application. Let’s do that!
Enable Spring Boot Metrics
Spring Boot provides a library called Actuator which helps you to monitor and manage your applications. If you want a quick introduction to Spring Boot Actuator, we recommend checking this article: Configuring Spring Boot Actuator
Behind the hoods, Spring Boot Actuator uses Micrometer to instrument and capture different
metrics from the code, such as: JVM Memory usage, CPU usage, Connection Pool information, HTTP requests and so on.
To enable monitoring, as first step you have to include the following dependencies in your Spring Boot project:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
The artifact micrometer-registry-prometheus
integrates Micrometer (which acts as an abstraction layer for application metrics) with Prometheus (a monitoring system).
Out of the box Spring Boot does not emit metrics (except for Health metrics). Therefore, you have to enable at minimum “prometheus” (for Spring Boot core metrics) and “metrics” for application metrics in application.properties:
management.endpoints.web.exposure.include=prometheus,metrics
On the other hand, if you want to capture all available metrics, you can just include the following exposure in application.properties:
management.endpoints.web.exposure.include=*
Adding a Custom Metric
Besides the standard Spring Boot Metrics, we will also capture a custom application metric. For this purpose, we will add a Controller which includes a @Timed
annotation in one of its methods:
@RestController public class TaskController { private final MeterRegistry registry; public TaskController(MeterRegistry registry) { this.registry = registry; } /** * The @Timed annotation adds timing support, so we can see how long * it takes to execute in Prometheus * percentiles */ @GetMapping("/task") @Timed(value = "task.time", description = "Time taken to return greeting", percentiles = {0.5, 0.90}) public String greeting() { registry.counter("task.counter").increment(); // Simulating a time-consuming task try { Thread.sleep(new java.util.Random().nextInt(1000) + 1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return "Task interrupted"; } return "Task completed!"; } }
@Timed
is an annotation from Micrometer that measures the execution time of the greeting()
method. It records the time taken and adds this metric to the monitoring system (e.g., Prometheus). The value
attribute defines the name of the metric, while percentiles
specifies which percentile values to track.
Configuring Prometheus
The simplest way to start Prometheus with a configuration file is to run it as Docker image. The Docker-compose tool allows us to simplify the execution of the Docker Image of Prometheus.
For this purpose, create the following docker-compose.yml file:
version: '3' services: prometheus: container_name: prometheus image: prom/prometheus extra_hosts: [ 'host.docker.internal:host-gateway' ] restart: always command: - --config.file=/etc/prometheus/prometheus.yml volumes: - ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro ports: - 9090:9090
The above file, will start the prom/prometheus official Image of Prometheus. Additionally, it will use the configuration we will create in the config/prometheus.yml
file:
global: scrape_interval: 10s evaluation_interval: 10s scrape_configs: - job_name: 'spring boot scrape' metrics_path: '/actuator/prometheus' scrape_interval: 5s static_configs: - targets: ['host.docker.internal:8080'] labels: application: 'My Spring Boot Application'
The above configuration basically says to collect every 10 seconds metrics which are available at localhost:8080 under the Path “actuator/prometheus”.
Running Spring Boot and Prometheus
Next, we will start both Prometheus and the Spring Boot application to verify that metrics are captured.
Firstly, start Prometheus using docker-compose as follows:
docker-compose up
Then, verify that Prometheus successfully started:
prometheus | ts=2023-12-07T17:18:21.991Z caller=main.go:1009 level=info msg="Server is ready to receive web requests." prometheus | ts=2023-12-07T17:18:21.991Z caller=manager.go:1012 level=info component="rule manager" msg="Starting rule manager...
Finally, start the Spring Boot application as usual with:
mvn install spring-boot:run
Then, open another shell and execute:
$ curl http://localhost:8080/actuator/prometheus # HELP process_uptime_seconds The uptime of the Java virtual machine # TYPE process_uptime_seconds gauge process_uptime_seconds 141.871 # HELP jvm_gc_memory_promoted_bytes_total Count of positive increases in the size of the old generation memory pool before GC to after GC # TYPE jvm_gc_memory_promoted_bytes_total counter jvm_gc_memory_promoted_bytes_total 0.0 # HELP process_start_time_seconds Start time of the process since unix epoch. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.641307416934E9 # HELP executor_pool_core_threads The core number of threads for the pool # TYPE executor_pool_core_threads gauge . . . . .
Great. The core metrics are available. Then, let’s test our application
curl http://localhost:8080/task Task completed!
Our application is working correctly. We will now move to Prometheus Console to check that metrics are correctly captured.
A look at Prometheus Console
According to our configuration, Prometheus Web console is available on port 9090. Therefore, head to the following URL to see all registered endpoints: http://localhost:9090/targets
As you can see, the “spring boot scrape” Target is UP and running.. As next exercise, we will monitor some metrics from our Spring Boot application. Click on the Graph upper tab and enter an expression to monitor.
For example, process_cpu_usage:
Then, let’s give a few more hits to our Spring Boot Controller:
curl http://localhost:8080/task Task completed!
Next, pick up the “task.time” available metrics. For example:
As you can see, capturing Spring Boot metrics is quite straightforward. Implementing this monitoring strategy helps streamline the process of monitoring, analyzing, and optimizing Spring Boot applications, enhancing their overall efficiency and resilience in production environments.
Conclusion
Integrating Prometheus with Spring Boot Actuator facilitates robust monitoring capabilities, empowering developers and administrators to gain insights into application performance. The combined power of Actuator’s exposed metrics and Prometheus’s monitoring capabilities enables efficient detection of issues, performance optimization, and proactive management of Spring Boot applications.
Source code: https://github.com/fmarchioni/masterspringboot/tree/master/prometheus
Found the article helpful? if so please follow us on Socials