How to use Spring Actuator with Grafana & Prometheus
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.
That’s it. Wait for some minutes and you will see the data flowing in Grafana.