
Prometheus is an open-source time-series database, which stores a sequence of data points, across time for monitoring and alerting. Prometheus is basically used to store analytics data from your applications and this allows you to perform time-series analysis of metrics. Prometheus is a standalone project, which means that it does not depend on other resources to run, like an external API or database.
Adding Prometheus to Spring Boot
To add Prometheus to our application need to add a dependency which is Spring Boot Actuator, this exposes some APIs, for health-checking and monitoring of your apps.
Now, we need to add the Micrometer registry dependency which specifically enables Prometheus support, because this allows the metrics collected by Micrometer to be exposed in a Prometheus way.
Next, to add a custom timer, we need to add a new dependency – the AOP dependency for Spring Boot because of the way that Micrometer times methods, it depends on AspectJ, which is provided in AOP. So our pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.7</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.spring.boot.prometheus</groupId>
<artifactId>prometheus-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>prometheus-spring-boot</name>
<description>Project for Spring Integration and Solace</description>
<properties>
<java.version>11</java.version>
</properties>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Next, we need to set a few properties so that actuator will show endpoints appended to our application URL:
server:
port: 8081
endpoints:
health:
sensitive: false
management:
security:
enabled: false
health:
jms:
enabled: false
endpoint:
health:
show-details: always
show-components: always
endpoints:
web:
exposure:
include: health,prometheus,metrics
Now, we need to register the TimedAspect bean in our Spring context to allow Micrometer to add a timer to our custom methods.
package com.spring.boot.prometheus.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
@Configuration
public class PrometheusConfiguration {
@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
Then, find the method that you want to time, and add the @Timed annotation to it. After that add the value attribute to give the metric a name. Like below example:
package com.spring.boot.prometheus.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.micrometer.core.annotation.Timed;
@RestController
public class HomeController {
@Timed(value = "homepage.time", description = "Time taken to return homepage")
@GetMapping("/home")
public String homePage() throws InterruptedException {
Thread.sleep(1000);
return "Welcome to HomePage!!!!!";
}
}
Now let's check it out by starting our application and hitting endpoint “/home”. We will access the Prometheus endpoint in actuator like this:
http://localhost:8081/actuator/prometheus
Now will we access this endpoint and will check the entry of our method:
This is how we will check the health of our application/method etc.
Matrix types and their use case
Gauge: Measuring resource usage, capacity, etc. Values that can rise and fall, and that have fixed upper bounds. Examples like the size of a collection, number of running threads, number of messages on a queue, memory usage.
Counter: Measuring the number of events or actions - a value that only increases, and never decreases. The total number of orders processed, total tasks completed, etc.
Timer: Measuring short-duration events and their frequency. Examples like method execution time, request duration, time is taken to make a cup of tea.
If you think there is some mistake in this article feel free to comment on it.