Monitoring Spring Boot Application With Micrometer, Prometheus and Grafana Using Custom Metrics

Image for post
Image for post

It is important to monitor an application’s metrics and health which helps us to improve performance, manage the app in a better way, and notice unoptimized behavior. Monitoring each service is important to be able to maintain a system that consists of many microservices.

In this blog post, I will demonstrate how a Spring Boot web application can be monitored using Micrometer which exposes metrics from our application, Prometheus which stores the metric data, and Grafana to visualize the data in graphs.

Implementing these tools can be done quite easily by adding just a few configurations. Additional to the default JVM metrics I will show how you can expose custom metrics like a user counter.

As always, the code for the demo used in this article can be found on GitHub.

Spring Boot

The base for our demo is a Spring Boot application which we initialize using Spring Initializr:

Image for post
Image for post

We initialized the project using spring-boot-starter-actuator which already exposes production-ready endpoints.

If we start our application we can see that some endpoints like health and info are already exposed to the /actuator endpoint per default

Triggering the /actuator/health endpoint gives us a metric if the service is up and running:

▶ http GET "http://localhost:8080/actuator/health"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/vnd.spring-boot.actuator.v3+json
Date: Wed, 21 Oct 2020 18:11:35 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked

{
"status": "UP"
}

Spring Boot Actuator can be integrated into Spring Boot Admin which provides a visual admin interface for your application. But this approach is not very popular and has some limitations. Therefore, we use Prometheus instead of Spring Boot Actuator and Grafana instead of Spring Boot Admin to have a more popular and framework/language-independent solution.

This solution approach needs vendor-neutral metrics and Micrometer is a popular tool for this use case.

Micrometer

Micrometer provides a simple facade over the instrumentation clients for the most popular monitoring systems, allowing you to instrument your JVM-based application code without vendor lock-in. Think SLF4J, but for metrics.

Micrometer is an open-source project and provides a metric facade that exposes metric data in a vendor-neutral format that a monitoring system can understand. These monitoring systems are supported:

Micrometer is not part of the Spring ecosystem and needs to be added as a dependency. In our demo application, this was already done in the Spring Initializr configuration.

Next step is to expose the Prometheus metrics in application.properties:

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

Now we can trigger this endpoint and see the Prometheus metrics:

Custom Metrics

We can also define some custom metrics, which I will demonstrate in this section. The demo contains a Scheduler class which periodically runs the included schedulingTask method.

To be able to send custom metrics we need to import MeterRegistry from the Micrometer library and inject it into our class. For more detail please check the official documentation.

It is possible to instantiate these types of meters from MeterRegistry:

  • Counter: reports merely a count over a specified property of an application
  • Gauge: shows the current value of a meter
  • Timers: measures latencies or frequency of events
  • DistributionSummary: provides distribution of events and a simple summary

I implemented a counter and a gauge for demonstration purposes:

@Component
public class Scheduler {

private final AtomicInteger testGauge;
private final Counter testCounter;

public Scheduler(MeterRegistry meterRegistry) {
// Counter vs. gauge, summary vs. histogram
// https://prometheus.io/docs/practices/instrumentation/#counter-vs-gauge-summary-vs-histogram
testGauge = meterRegistry.gauge("custom_gauge", new AtomicInteger(0));
testCounter = meterRegistry.counter("custom_counter");
}

@Scheduled(fixedRateString = "1000", initialDelayString = "0")
public void schedulingTask() {
testGauge.set(Scheduler.getRandomNumberInRange(0, 100));

testCounter.increment();
}

private static int getRandomNumberInRange(int min, int max) {
if (min >= max) {
throw new IllegalArgumentException("max must be greater than min");
}

Random r = new Random();
return r.nextInt((max - min) + 1) + min;
}
}

If we run the application we can see that our custom metrics are exposed via the actuatuor/prometheus endpoint:

▶ http GET "http://localhost:8080/actuator/prometheus" | grep custom
# HELP custom_gauge
# TYPE custom_gauge gauge
custom_gauge 29.0
# HELP custom_counter_total
# TYPE custom_counter_total counter
custom_counter_total 722.0

As we now have the metrics available in a format that Prometheus can understand, we will look at how to set up Prometheus.

Prometheus

Prometheus stores our metric data in time series in memory by periodically pulling it via HTTP. The data can be visualized by a console template language, a built-in expression browser, or by integrating Grafana (which we will do after setting up Prometheus).

In this demo, we will run Prometheus locally in a Docker container and we, therefore, need some configurations in a prometheus.yml file that you can place anywhere on your hard drive:

global:
scrape_interval: 10s # How frequently to scrape targets by default

scrape_configs:
- job_name: 'spring_micrometer' # The job name is assigned to scraped metrics by default.
metrics_path: '/actuator/prometheus' # The HTTP resource path on which to fetch metrics from targets.
scrape_interval: 5s # How frequently to scrape targets from this job.
static_configs: # A static_config allows specifying a list of targets and a common label set for them
- targets: ['192.168.178.22:8080']

All available configuration options can be seen in the official documentation.

As we want to run Prometheus in a Docker container we need to tell Prometheus our IP address instead of localhost in static_configs -> targets. Instead of localhost:8080 we are using 192.168.178.22:8080 where 192.168.178.22 is my IP address at the moment. To get your system IP you can use ifconfig or ipconfig in your terminal depending on your operating system.

Now we are ready to run Prometheus:

docker run -d -p 9090:9090 -v <path-to-your-prometheus.yml>:/etc/prometheus/prometheus.yml prom/prometheus

<path-to-your-prometheus.yml> should be the path where you placed the prometheus.yml configuration file described above.

Finally, we can open the Prometheus on http://localhost:9090 in the web browser and search for our custom metric named custom_gauge:

Image for post
Image for post

To check that Prometheus is correctly listening to our locally running Spring Boot application we can navigate to Status -> Targets in the top main navigation bar:

Image for post
Image for post

Prometheus provides a query language PromQL, check the official documentation for more details.

Grafana

The included Prometheus browser graph is nice for basic visualization of our metrics but we will use Grafana instead. Grafana provides a rich UI where you create, explore and share dashboards that contain multiple graphs.

Grafana can pull data from various data sources like Prometheus, Elasticsearch, InfluxDB, etc. It also allows you to set rule-based alerts, which then can notify you over Slack, Email, Hipchat, and similar.

We start Grafana also locally in a Docker container:

docker run -d -p 3000:3000 grafana/grafana

Opening http://localhost:3000 in a browser should now show the following login page:

Image for post
Image for post

You can log in using the default username admin and the default password admin. After login, you should change these default passwords by visiting http://localhost:3000/profile/password.

The first step is to add our local Prometheus as our data source:

Image for post
Image for post
Image for post
Image for post
Image for post
Image for post

Community Dashboard

The first dashboard we want to add is a community dashboard. As we are using a Spring Boot application we choose the popular JVM dashboard:

Image for post
Image for post

After loading the URL we can see the imported dashboard:

Image for post
Image for post

Custom Metric Dashboard

Finally, we want to create a new dashboard where we show our custom metrics. The first step is to create a new dashboard:

Image for post
Image for post

Now we see a new dashboard where we can create a new panel:

Image for post
Image for post

In the first panel we add a visualization for our custom_gauge metric. I use the Stat visualization as it shows the current value and a simple graph:

Image for post
Image for post

Additionally, a new panel for the custom_counter metric is added to our dashboard:

Image for post
Image for post

In the end, the dashboard looks like this:

Image for post
Image for post

Conclusion

It is important to monitor an application’s metrics and health which helps us to improve performance, manage the app in a better way and notice unoptimized behavior. Monitoring each service is important to be able to maintain a system that consists of many microservices.

In this article, I showed how a Spring Boot web application can be monitored using Micrometer which exposes metrics from our application, Prometheus which stores the metric data and Grafana to visualize the data in graphs.

This popular monitoring approach should help you to maintain your applications and make your customers happy.

As always, the code for the demo used in this article can be found on GitHub.

Image for post
Image for post

Originally published at https://www.mokkapps.de.

The Startup

Medium's largest active publication, followed by +730K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store