Okay, the user wants me to write a technical article about Spring Boot observability with Micrometer and Grafana. Let me start by understanding the structure they provided. The title needs to be specific, including the main names. The example given uses Spring Boot 3 and Micrometer, so I'll follow that format.
The opening should address a real problem developers face in production. Instead of generic statements, I need to mention specific issues like metrics not being exposed or dashboards not updating. That makes it more relatable.
Prerequisites: I need to list specific versions and tools. Java 17, Spring Boot 3.2, Micrometer, Grafana, and maybe Docker. Let me check the latest versions to ensure accuracy.
Section 1 is about core concepts and dependencies. I'll explain Micrometer's role and then provide the pom.xml with Micrometer and Actuator dependencies. Then the application.properties entries to expose metrics and enable Prometheus. Each property needs a brief explanation.
Section 2 is the implementation. I need a Java class that demonstrates custom metrics. A service with a counter and timer makes sense. The code must be complete with package, imports, annotations, and methods. After the code, mention how to test it via the Actuator endpoint.
Section 3 is infrastructure. Since Grafana and Prometheus are involved, I should include a docker-compose.yml to set them up. Also, a Prometheus config file. Then explain how to import the dashboard.
Common Mistakes: Three specific errors. Maybe missing the Prometheus dependency, incorrect meter names, and not starting the registry. Show wrong code, the fix, and explain why it's wrong.
Summary: Three actionable points, like adding dependencies, using custom metrics, and using Docker for Grafana.
I need to ensure all code blocks have the correct language tags. No placeholders, everything compilable. Use Spring Boot 3.x only. Avoid any marketing language, keep it developer-focused.
Let me start drafting each section, making sure to follow the structure exactly. Check that the Java class includes all necessary parts. Verify the dependencies are up-to-date. For the docker-compose, use the latest images. In common mistakes, pick issues that are easy to overlook but critical for functionality.
Finally, the footer with the author's link. Make sure the article is within the word count. Avoid any markdown beyond what's specified. Double-check for any typos or incorrect versions.
Spring Boot 3 + Micrometer + Grafana: Metrics That Survive Midnight Deployments
Production Spring Boot apps fail silently when JVM memory spikes go undetected, custom business metrics aren’t tracked, and Grafana dashboards show stale data from misconfigured Prometheus scrapers. These gaps turn simple outages into all-night debugging sessions.
Prerequisites
- Java 17+ SDK
- Spring Boot 3.2.x
- Micrometer 1.12+ (included via Spring Boot)
- Grafana 10.1+ (via Docker)
- Prometheus 2.47+ (via Docker)
Section 1 — core concept and dependency setup
Micrometer acts as a metrics facade, exposing Spring Boot's internal metrics while enabling custom instrumentation. Add these dependencies:
<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>
</dependencies>
# application.properties
management.endpoints.web.exposure.include=health,metrics,prometheus
management.metrics.export.prometheus.enabled=true
management.server.port=8081
-
exposure.include: Enables Prometheus scraping endpoint -
metrics.export.prometheus: Activates registry -
server.port: Separates metrics from main app port
Section 2 — the implementation
Create a service tracking order processing metrics with custom counter and timer. The @MeterBinder annotation registers metrics at startup:
package com.example.orderservice;
import io.micrometer.core.instrument.*;
import org.springframework.stereotype.Service;
import org.springframework.context.annotation.Bean;
@Service
public class OrderMetrics {
private final Counter ordersCreated;
private final Timer orderProcessingTime;
public OrderMetrics(MeterRegistry registry) {
ordersCreated = Counter.builder("orders.created")
.description("Total completed orders")
.register(registry);
orderProcessingTime = Timer.builder("orders.processing.time")
.description("Order fulfillment latency")
.publishPercentiles(0.95)
.register(registry);
}
@Bean
public MeterBinder cacheMetrics() {
return registry -> Gauge.builder("orders.queue.size", this::simulateQueue)
.register(registry);
}
private Double simulateQueue() {
return Math.random() * 100;
}
public void recordOrder() {
ordersCreated.increment();
orderProcessingTime.record(() -> {
try { Thread.sleep((long)(Math.random() * 200)); }
catch (InterruptedException ignored) {}
});
}
}
Test by hitting /actuator/prometheus and searching for orders_created_total. Call recordOrder() from a controller to generate metrics.
Section 3 — infrastructure or integration
Create docker-compose.yml for observability stack:
version: '3'
services:
prometheus:
image: prom/prometheus:v2.47.0
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:10.1.5
ports:
- "3000:3000"
# prometheus.yml
global:
scrape_interval: 5s
scrape_configs:
- job_name: 'spring'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['host.docker.internal:8081']
Run docker compose up, then import dashboard ID 4701 in Grafana for Spring Boot metrics.
Common Mistakes
Mistake 1: Missing Prometheus registry dependency
Wrong:
<!-- Only actuator present -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Fix:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Prometheus metrics won't appear without the registry implementation.
Mistake 2: Incorrect meter name casing
Wrong:
Counter.builder("Orders_Created") // Upper case
Fix:
Counter.builder("orders.created") // Lowercase with dots
Prometheus requires snake_case metrics - Micrometer auto-converts dots to underscores.
Mistake 3: Not starting meter registry
Wrong:
public OrderMetrics() {
// No MeterRegistry injection
}
Fix:
public OrderMetrics(MeterRegistry registry) {
// Use injected registry
}
Metrics won't be registered without binding to the active MeterRegistry.
Summary
- Expose Prometheus endpoint with actuator and registry dependency
- Instrument custom business logic with @MeterBinder and Timer/Counter builders
- Configure Docker-based Grafana with host.docker.internal for local dev scraping
The author publishes Spring Boot starter templates at https://gumroad.com
Top comments (0)