java

Master Spring Boot Actuator Custom Metrics and Health Indicators with Micrometer Integration Guide

Learn to implement custom metrics and health indicators using Spring Boot Actuator and Micrometer for production-grade monitoring and observability.

Master Spring Boot Actuator Custom Metrics and Health Indicators with Micrometer Integration Guide

Recently, while troubleshooting a production incident where delayed order processing impacted customers, I realized our monitoring had critical gaps. We lacked visibility into business-specific metrics and dependency health beyond basic system checks. This experience drove me to explore Spring Boot Actuator and Micrometer more deeply, leading to powerful monitoring improvements I’ll share with you.

First, let’s configure our project. Add Actuator and Micrometer dependencies in your pom.xml. For monitoring systems like Prometheus, include its registry specifically:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

In application.yml, expose endpoints and configure metrics:

management:
  endpoints:
    web:
      exposure:
        include: "*"
  metrics:
    export:
      prometheus:
        enabled: true
    tags:
      application: ${spring.application.name}

Custom metrics transform how we understand application behavior. Consider tracking order processing times:

@RestController
public class OrderController {
    private final MeterRegistry meterRegistry;
    private final Timer processingTimer;

    public OrderController(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.processingTimer = Timer.builder("business.order.processing.time")
            .description("Order processing duration")
            .register(meterRegistry);
    }

    @PostMapping("/orders")
    public Order createOrder(@RequestBody Order order) {
        return processingTimer.record(() -> {
            // Business logic here
            return orderService.process(order);
        });
    }
}

Why settle for knowing if a service is up when you can understand how well it performs? Health indicators provide this insight. Here’s how to monitor Redis connectivity:

@Component
public class RedisHealthIndicator implements HealthIndicator {
    private final RedisTemplate<String, String> redisTemplate;

    public RedisHealthIndicator(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Health health() {
        try {
            String result = redisTemplate.execute((RedisCallback<String>) connection -> 
                connection.ping()
            );
            return "PONG".equals(result) 
                ? Health.up().build() 
                : Health.down().build();
        } catch (Exception ex) {
            return Health.down(ex).build();
        }
    }
}

When exporting metrics to systems like CloudWatch, consider this configuration:

management:
  metrics:
    export:
      cloudwatch:
        namespace: OrderProcessing
        step: 1m

For custom actuator endpoints exposing business KPIs:

@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
    private final OrderRepository orderRepository;

    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @ReadOperation
    public OrderStats orderMetrics() {
        long pending = orderRepository.countByStatus(OrderStatus.PENDING);
        long completed = orderRepository.countByStatus(OrderStatus.COMPLETED);
        return new OrderStats(pending, completed);
    }

    public record OrderStats(long pending, long completed) {}
}

Security is non-negotiable. Protect endpoints with Spring Security:

@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeRequests(requests -> 
                requests.anyRequest().hasRole("ACTUATOR_ADMIN"))
            .httpBasic();
    }
}

Performance matters. Use meter filtering to control metric volume:

@Bean
public MeterFilter meterFilter() {
    return MeterFilter.deny(id -> {
        String uri = id.getTag("uri");
        return uri != null && uri.startsWith("/actuator");
    });
}

Notice how metrics collection adds minimal overhead? The timer pattern we implemented earlier samples rather than recording every event. What other techniques could optimize monitoring in high-throughput systems?

When metrics show anomalies, structured logging complements investigation. Use MDC for correlation:

@PostMapping("/orders")
public Order createOrder(@RequestBody Order order) {
    MDC.put("orderId", order.getId());
    logger.info("Processing order");
    // Processing logic
    MDC.clear();
}

Effective monitoring requires balancing detail and overhead. Focus on metrics impacting user experience and business outcomes. For our order service, tracking payment processing failures proved more valuable than system CPU metrics during peak sales.

These techniques transformed how we operate services. We detect issues before customers notice and resolve them faster. Have you considered which business metrics would provide maximum insight in your systems? Share your monitoring challenges in the comments. If this helped you, please like and share to help others improve their observability practices.

Keywords: Spring Boot Actuator, Micrometer metrics, custom health indicators, Spring Boot monitoring, actuator endpoints, Prometheus integration, InfluxDB metrics, CloudWatch monitoring, Spring Boot observability, production monitoring



Similar Posts
Blog Image
Building High-Performance Event Streaming Applications with Apache Kafka and Spring Boot: Complete Producer-Consumer Guide

Learn to build scalable event streaming apps with Apache Kafka and Spring Boot. Master producer-consumer patterns, stream processing, and performance optimization.

Blog Image
Master Apache Kafka and Spring Boot Integration: Build Scalable Event-Driven Microservices in 2024

Learn to integrate Apache Kafka with Spring Boot for scalable event-driven microservices. Build robust distributed systems with simplified configuration and messaging.

Blog Image
Apache Kafka Spring Cloud Stream Integration: Build Scalable Event-Driven Microservices Architecture Guide

Learn how to integrate Apache Kafka with Spring Cloud Stream for scalable event-driven microservices. Simplify messaging patterns and boost system resilience.

Blog Image
Event-Driven Microservices with Spring Cloud Stream, Kafka, and Reactive Streams: Complete Guide

Learn to build scalable event-driven microservices using Spring Cloud Stream, Apache Kafka, and Reactive Streams. Complete guide with code examples and best practices.

Blog Image
Java 21 Virtual Threads and Structured Concurrency: Complete Guide with Spring Boot Integration

Master virtual threads and structured concurrency in Java 21+ with practical examples. Learn Spring Boot integration, performance optimization, and migration strategies for scalable applications.

Blog Image
Apache Kafka Spring Cloud Stream Integration: Build Scalable Event-Driven Microservices Architecture Guide

Learn to integrate Apache Kafka with Spring Cloud Stream for scalable event-driven microservices. Master message streaming, error handling & real-world implementation patterns.