Monitoring Spring Boot with Prometheus

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

prometheus spring boot tutorial metrics

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:

prometheus with spring boot step-by-step tutorial

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
Twitter Icon       Facebook Icon       LinkedIn Icon       Mastodon Icon