How to use Spring Actuator with Grafana & Prometheus

Lejdi Prifti
3 min readNov 26, 2023

--

This post will walk you through setting up a Spring application with Prometheus to submit metrics in Grafana. All this will be done in Docker.

First of all, let’s create our metrics-publisher microservice. It will consist of the following dependencies:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

Something new that you may have seen is micrometer-registry-prometheus. micrometer-registry-prometheus is a Micrometer registry for Prometheus. Micrometer is a dimensional metrics instrumentation library that provides a simple facade over various monitoring systems, including Prometheus. By using it, we simplify the process of integrating Prometheus with our Spring Boot application. The library handles the translation of metrics and provides a convenient way to expose them in a format that Prometheus can scrape.

The Prometheus endpoints are not exposed by default. For such reason, we need to add two properties in the application.properties file.

management.endpoints.web.exposure.include=*
management.endpoint.prometheus.enabled=true

Perfect! If you start your application using mvn spring-boot:run and go to the following url http://localhost:8080/actuator/prometheus, you should be able to see a similar content.

# HELP jvm_compilation_time_ms_total The approximate accumulated elapsed time spent in compilation
# TYPE jvm_compilation_time_ms_total counter
jvm_compilation_time_ms_total{compiler="HotSpot 64-Bit Tiered Compilers",} 624.0
# HELP jvm_gc_live_data_size_bytes Size of long-lived heap memory pool after reclamation
# TYPE jvm_gc_live_data_size_bytes gauge
jvm_gc_live_data_size_bytes 0.0
# HELP disk_total_bytes Total space for path
# TYPE disk_total_bytes gauge
disk_total_bytes{path="medium/metrics-publisher/.",} 5.01646073856E11
# HELP jvm_memory_committed_bytes The amount of memory in bytes that is committed for the Java virtual machine to use
# TYPE jvm_memory_committed_bytes gauge
jvm_memory_committed_bytes{area="heap",id="G1 Survivor Space",} 2097152.0
jvm_memory_committed_bytes{area="heap",id="G1 Old Gen",} 3.3554432E7
jvm_memory_committed_bytes{area="nonheap",id="Metaspace",} 3.178496E7
jvm_memory_committed_bytes{area="nonheap",id="CodeCache",} 9371648.0
jvm_memory_committed_bytes{area="heap",id="G1 Eden Space",} 2.7262976E7
jvm_memory_committed_bytes{area="nonheap",id="Compressed Class Space",} 4653056.0
# HELP tomcat_sessions_expired_sessions_total
# TYPE tomcat_sessions_expired_sessions_total counter
tomcat_sessions_expired_sessions_total 0.0
# ...

It is now necessary to set up our small Docker cluster. To accomplish this, we must first develop a Docker image of the ms-metrics-publisher.

docker-maven-plugin from io.fabric8 is an excellent way to make things quick and simple. Change the application.properties’s build section such that it contains the information below.

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.40.3</version>
<configuration>
<images>
<image>
<name>ms-metrics-publisher</name>
<build>
<from>openjdk:17-oracle</from>
<maintainer>freelancer@lejdiprifti.com</maintainer>
<tags>
<tag>latest</tag>
<tag>${project.version}</tag>
</tags>
<ports>
<port>8080</port>
</ports>
<volumes>
<volume>/tmp</volume>
</volumes>
<cmd>
<shell>java $JVM_OPTS $TIMEZONE $JAVA_OPTS \
-Djava.security.egd=file:/dev/./urandom -jar \
/opt/springboot/${project.build.finalName}.jar</shell>
</cmd>
<assembly>
<targetDir>/opt/springboot</targetDir>
<descriptorRef>artifact</descriptorRef>
</assembly>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>

Afterwards, we can generate the docker image named ms-metrics-publisher .

mvn clean install docker:build

To setup the cluster, we will use this docker-compose.yml file. It defines a devops network and three services, prometheus that scrapes data from our microservice, grafana that displays these data, and our microservice ms-metrics-publisher .

version: '3'

networks:
devops:

services:
prometheus:
image: prom/prometheus:v2.30.3
volumes:
- ./prometheus:/etc/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'
networks:
- devops

grafana:
image: grafana/grafana:8.3.1
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
ports:
- '3000:3000'
depends_on:
- prometheus
networks:
- devops

ms-metrics-publisher:
image: ms-metrics-publisher:latest
ports:
- '8080:8080'
networks:
- devops

The configuration file that defines the scraping jobs must be created in order to set up Prometheus.

global:
scrape_interval: 30s


scrape_configs:
# Prometheus itself
# This uses the static method to get metrics endpoints
- job_name: "prometheus"
honor_labels: true
static_configs:
- targets: ["prometheus:9090"]
- job_name: "spring"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["ms-metrics-publisher:8080"]

Open Grafana at http://localhost:3000 and add Prometheus as a data source. Use http://prometheus:9090 as the url because it is referenced using the Docker DNS.

Data Sources in Grafana

That’s it. Wait for some minutes and you will see the data flowing in Grafana.

Explore in Grafana

--

--

Lejdi Prifti

Software Developer | ML Enthusiast | AWS Practitioner | Kubernetes Administrator