java

Boost Your Micronaut Apps: Mastering Monitoring with Prometheus and Grafana

Micronaut, Prometheus, and Grafana form a powerful monitoring solution for cloud applications. Custom metrics, visualizations, and alerting provide valuable insights into application performance and user behavior.

Boost Your Micronaut Apps: Mastering Monitoring with Prometheus and Grafana

Micronaut has become a go-to framework for building microservices and serverless applications. It’s lightning-fast startup time and low memory footprint make it perfect for cloud environments. But how do we monitor these applications effectively? Enter Prometheus and Grafana - the dynamic duo of observability.

Let’s dive into how we can leverage these tools with Micronaut to create a robust monitoring solution. First things first, we need to add the necessary dependencies to our Micronaut project. In your build.gradle file, include these lines:

implementation("io.micronaut.micrometer:micronaut-micrometer-core")
implementation("io.micronaut.micrometer:micronaut-micrometer-registry-prometheus")

Now, we need to configure Micronaut to expose a Prometheus endpoint. In your application.yml file, add:

micronaut:
  metrics:
    enabled: true
    export:
      prometheus:
        enabled: true
        step: PT1M
        descriptions: true

This tells Micronaut to enable metrics and expose them in Prometheus format. The ‘step’ property sets how often metrics are collected, and ‘descriptions’ adds human-readable descriptions to the metrics.

With these configurations in place, Micronaut will automatically expose a /prometheus endpoint that Prometheus can scrape. But we’re not done yet! Let’s create some custom metrics to really showcase the power of this setup.

Imagine we’re building a simple online bookstore. We might want to track how many times each book is viewed. Here’s how we could implement that:

import io.micrometer.core.instrument.MeterRegistry;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/books")
public class BookController {

    private final MeterRegistry meterRegistry;

    public BookController(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Get("/{id}")
    public Book getBook(Long id) {
        // Increment the view count for this book
        meterRegistry.counter("book.views", "id", id.toString()).increment();
        
        // Fetch and return the book (implementation omitted)
        return fetchBook(id);
    }
}

In this example, we’re using Micrometer (which Micronaut integrates with) to create a counter. Every time a book is viewed, we increment the counter for that specific book ID.

Now that we have our application emitting metrics, let’s set up Prometheus to collect them. We’ll use Docker to keep things simple. Create a file named prometheus.yml:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'micronaut'
    metrics_path: '/prometheus'
    static_configs:
      - targets: ['host.docker.internal:8080']

This configuration tells Prometheus to scrape our Micronaut application every 15 seconds. The ‘host.docker.internal’ is a special DNS name in Docker that resolves to the host machine’s IP.

Now, let’s fire up Prometheus with Docker:

docker run -p 9090:9090 -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

Great! Prometheus is now collecting metrics from our Micronaut application. But raw numbers aren’t very exciting, are they? This is where Grafana comes in to make our metrics visually appealing and easier to understand.

Let’s set up Grafana:

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

Once Grafana is running, we can access it at http://localhost:3000. The default login is admin/admin. The first thing we need to do is add Prometheus as a data source. Go to Configuration > Data Sources > Add data source > Prometheus. Set the URL to http://host.docker.internal:9090 and save.

Now comes the fun part - creating dashboards! Let’s create a simple dashboard to visualize our book views. Create a new dashboard and add a graph panel. In the panel settings, use this PromQL query:

sum(increase(book_views_total[1h])) by (id)

This query shows the increase in views for each book over the last hour. Play around with different visualizations and time ranges to find what works best for your needs.

But wait, there’s more! Micronaut provides a wealth of built-in metrics that we can visualize. For example, we can track HTTP request durations with this query:

histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le))

This shows the 95th percentile of HTTP request durations over the last 5 minutes. It’s a great way to keep an eye on your application’s performance.

Now, you might be thinking, “This is cool and all, but what about when I deploy to the cloud?” Great question! Most cloud providers have their own managed Prometheus and Grafana services that you can use. For example, on AWS you could use Amazon Managed Service for Prometheus and Amazon Managed Grafana.

The beauty of this setup is that it’s cloud-agnostic. Whether you’re running on AWS, Google Cloud, or your own bare metal servers, the principles remain the same. You just need to ensure that your Prometheus instance can reach your Micronaut applications, and that Grafana can reach Prometheus.

One thing to keep in mind when running in the cloud is that you’ll want to secure your /prometheus endpoint. You don’t want just anyone to be able to scrape your metrics! Micronaut makes this easy with its security features. Here’s a quick example of how you could secure the endpoint with basic auth:

@Requires(property = "micronaut.security.enabled", value = "true")
@Controller("/prometheus")
public class SecurePrometheusController {

    @Secured("ADMIN")
    @Get(produces = MediaType.TEXT_PLAIN)
    public String getMetrics() {
        // Return Prometheus metrics
    }
}

This ensures that only users with the ADMIN role can access the Prometheus metrics.

As your application grows, you’ll find more and more uses for metrics. Maybe you want to track how many users are logged in at any given time, or how many items are in users’ shopping carts. With Micronaut, Prometheus, and Grafana, the sky’s the limit!

One of my favorite things about this setup is how it encourages a data-driven approach to development. Instead of guessing about how your application is performing or how users are interacting with it, you have cold, hard data at your fingertips.

I remember one project where we used this exact stack to diagnose a mysterious performance issue. We were seeing sporadic slowdowns, but couldn’t reproduce them consistently. By setting up detailed metrics and visualizing them in Grafana, we were able to correlate the slowdowns with specific database queries. It turned out that a particular query was causing table scans under certain conditions. Without our metrics, we might have been hunting for that bug for weeks!

As you get more comfortable with this setup, you’ll find yourself adding metrics to everything. CPU usage, memory usage, cache hit rates, database connection pool stats - all of these can provide valuable insights into your application’s behavior.

And don’t forget about alerting! Grafana has powerful alerting capabilities that can notify you when things go wrong. Set up alerts for things like high error rates, slow response times, or low disk space, and you’ll be the first to know when your application needs attention.

In conclusion, the combination of Micronaut, Prometheus, and Grafana provides a powerful toolset for monitoring your applications in the cloud. It gives you visibility into your application’s behavior, helps you diagnose issues quickly, and allows you to make data-driven decisions about performance optimizations and feature development. So go forth and instrument your code - your future self will thank you!

Keywords: Micronaut, Prometheus, Grafana, microservices, observability, metrics, monitoring, cloud-native, performance, scalability



Similar Posts
Blog Image
Java Records: 7 Optimization Techniques for Better Performance and Code Clarity

Discover 6 expert optimization techniques for Java Records that boost application performance. Learn how to enhance your data-centric code with immutability handling, custom accessors, and more proven patterns from production environments. Code examples included.

Blog Image
You’re Probably Using Java the Wrong Way—Here’s How to Fix It

Java evolves with features like Optional, lambdas, streams, and records. Embrace modern practices for cleaner, more efficient code. Stay updated to write concise, expressive, and maintainable Java programs.

Blog Image
What Every Java Developer Needs to Know About Concurrency!

Java concurrency: multiple threads, improved performance. Challenges: race conditions, deadlocks. Tools: synchronized keyword, ExecutorService, CountDownLatch. Java Memory Model crucial. Real-world applications: web servers, data processing. Practice and design for concurrency.

Blog Image
Java or Python? The Real Truth That No One Talks About!

Python and Java are versatile languages with unique strengths. Python excels in simplicity and data science, while Java shines in enterprise and Android development. Both offer excellent job prospects and vibrant communities. Choose based on project needs and personal preferences.

Blog Image
Mastering Java File I/O: Baking the Perfect Code Cake with JUnit Magic

Exploring Java's File I/O Testing: Temp Directories, Mocking Magic, and JUnit's No-Fuss, Organized Culinary Experience

Blog Image
Crafting Advanced Microservices with Kafka and Micronaut: Your Ultimate Guide

Orchestrating Real-Time Microservices: A Micronaut and Kafka Symphony