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
Unlocking Micronaut: Safeguarding Your Apps with Ease

Fortify Micronaut Applications with Streamlined Security and Powerful Tools

Blog Image
Unleash Micronaut's Power: Supercharge Your Java Apps with HTTP/2 and gRPC

Micronaut's HTTP/2 and gRPC support enhances performance in real-time data processing applications. It enables efficient streaming, seamless protocol integration, and robust error handling, making it ideal for building high-performance, resilient microservices.

Blog Image
Vaadin and Kubernetes: Building Scalable UIs for Cloud-Native Applications

Vaadin and Kubernetes combine for scalable cloud UIs. Vaadin builds web apps with Java, Kubernetes manages containers. Together, they offer easy scaling, real-time updates, and robust deployment for modern web applications.

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

Orchestrating Real-Time Microservices: A Micronaut and Kafka Symphony

Blog Image
Secure Your Micronaut APIs: Implementing CORS, CSRF, and Secure Headers

Micronaut API security: Implement CORS, CSRF, secure headers. Configure CORS, enable CSRF protection, add secure headers. Enhance API resilience against web threats. Use HTTPS in production.

Blog Image
Mastering Zero-Cost State Machines in Rust: Boost Performance and Safety

Rust's zero-cost state machines leverage the type system to enforce state transitions at compile-time, eliminating runtime overhead. By using enums, generics, and associated types, developers can create self-documenting APIs that catch invalid state transitions before runtime. This technique is particularly useful for modeling complex systems, workflows, and protocols, ensuring type safety and improved performance.