Dashs with Grafana, Prometheus and Actuator for Spring Boot using Docker

Marcos
4 min readJan 27, 2024

--

Hello, I’m Marcos and today I will use Grafana and Prometheus to start to monitor a Spring Boot application.

We can use the spring initializr site to create the application and add these dependencies:

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

In order to create some requests I made two simple controller to verify HTTP 200 and HTTP 400, like this:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

@GetMapping("/home")
public ResponseEntity<?> getHome() {
return ResponseEntity.ok().build();
}

@GetMapping("/home-error")
public ResponseEntity<?> getHomeWithError() {
return ResponseEntity.badRequest().build();
}

}

Ok, just start the application and use http:localhost:8080/home and http:localhost:8080/home-error.

To see the metrics we can use the route http://localhost:8080/actuator and see all the routes:

{
"_links":{
"self":{
"href":"http://localhost:8080/actuator",
"templated":false
},
"beans":{
"href":"http://localhost:8080/actuator/beans",
"templated":false
},
"caches-cache":{
"href":"http://localhost:8080/actuator/caches/{cache}",
"templated":true
},
"caches":{
"href":"http://localhost:8080/actuator/caches",
"templated":false
},
"health":{
"href":"http://localhost:8080/actuator/health",
"templated":false
},
"health-path":{
"href":"http://localhost:8080/actuator/health/{*path}",
"templated":true
},
"info":{
"href":"http://localhost:8080/actuator/info",
"templated":false
},
"conditions":{
"href":"http://localhost:8080/actuator/conditions",
"templated":false
},
"shutdown":{
"href":"http://localhost:8080/actuator/shutdown",
"templated":false
},
"configprops-prefix":{
"href":"http://localhost:8080/actuator/configprops/{prefix}",
"templated":true
},
"configprops":{
"href":"http://localhost:8080/actuator/configprops",
"templated":false
},
"prometheus":{
"href":"http://localhost:8080/actuator/prometheus",
"templated":false
},
"env":{
"href":"http://localhost:8080/actuator/env",
"templated":false
},
"env-toMatch":{
"href":"http://localhost:8080/actuator/env/{toMatch}",
"templated":true
},
"loggers":{
"href":"http://localhost:8080/actuator/loggers",
"templated":false
},
"loggers-name":{
"href":"http://localhost:8080/actuator/loggers/{name}",
"templated":true
},
"heapdump":{
"href":"http://localhost:8080/actuator/heapdump",
"templated":false
},
"threaddump":{
"href":"http://localhost:8080/actuator/threaddump",
"templated":false
},
"metrics-requiredMetricName":{
"href":"http://localhost:8080/actuator/metrics/{requiredMetricName}",
"templated":true
},
"metrics":{
"href":"http://localhost:8080/actuator/metrics",
"templated":false
},
"scheduledtasks":{
"href":"http://localhost:8080/actuator/scheduledtasks",
"templated":false
},
"mappings":{
"href":"http://localhost:8080/actuator/mappings",
"templated":false
}
}
}

Now, in the application.properties we can configure which routes we want do make available:

management.endpoints.web.exposure.include=health, prometheus

Using the route /actuator again:

{
"_links":{
"self":{
"href":"http://localhost:8080/actuator",
"templated":false
},
"health":{
"href":"http://localhost:8080/actuator/health",
"templated":false
},
"health-path":{
"href":"http://localhost:8080/actuator/health/{*path}",
"templated":true
},
"prometheus":{
"href":"http://localhost:8080/actuator/prometheus",
"templated":false
}
}
}

Ok, the spring application is ready. Let’s create the Grafana and Prometheus containers.

At first we must create a docker-compose.yml file, like this example:

version: '3.2'
networks:
m-network:
driver: bridge

services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- '9090:9090'
command:
- --config.file=/etc/prometheus/prometheus.yml
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- m-network
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- '3000:3000'
environment:
- GF_SECURITY_ADMIN_PASSWORD=pass
depends_on:
- prometheus
networks:
- m-network

Obs:

  • In this example above I put prometheus and grafana in the same network (m-network)
  • We have to create another file called prometheus.yml used to config prometheus. Here it is:
global:
scrape_interval: 5s

rule_files:

scrape_configs:

- job_name: 'spring-actuator'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets: ['host.docker.internal:8080']
labels:
application: 'spring-actuator'

Another obs:

  • In order to monitoring a localhost application, I put the target as host.docker.internal

Use these commands to create the containers:

docker-compose build
docker-compose up

Grafana will be available here: http://localhost:3000/ and the password is “pass”.

Prometheus will be available here: http://localhost:9090/

The first thing is add Prometheus as a datasource:

Now, let’s create a dashboard, for this I will import a micrometer dashboard (id 4701):

And it’s ready:

Change to 5 minutes to see the metrics in case the time is 24 hours.

Grafana has a lot of dashboards ready, let’s create a dash for Spring. For this we can import the dash with ID 14430.

After import this dash, we have to configure, so click on settings and put the application in first:

Now, change the query like this example:

Ok, we have another dash:

The code is here.

--

--