package com.example.demo.service;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;
@Service
public class MetricsService {
private final Counter userCreationCounter;
private final Timer userProcessingTimer;
private final MeterRegistry registry;
public MetricsService(Counter userCreationCounter,
Timer userProcessingTimer,
MeterRegistry registry) {
this.userCreationCounter = userCreationCounter;
this.userProcessingTimer = userProcessingTimer;
this.registry = registry;
}
public void recordUserCreation() {
userCreationCounter.increment();
}
public void recordProcessingTime(Runnable task) {
userProcessingTimer.record(task);
}
public void recordActiveUsers(int count) {
registry.gauge("users.active", count);
}
}
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus,env,loggers
base-path: /actuator
endpoint:
health:
show-details: when-authorized
probes:
enabled: true
shutdown:
enabled: true
server:
port: 9090
metrics:
export:
prometheus:
enabled: true
tags:
application: user-service
environment: production
info:
app:
name: '@project.name@'
version: '@project.version@'
description: User Management Service
encoding: '@project.build.sourceEncoding@'
java:
version: '@java.version@'
package com.example.demo.actuator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
try {
// Check external service availability
boolean externalServiceUp = checkExternalService();
if (externalServiceUp) {
return Health.up()
.withDetail("externalService", "Available")
.withDetail("responseTime", "45ms")
.build();
} else {
return Health.down()
.withDetail("externalService", "Unavailable")
.build();
}
} catch (Exception e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
private boolean checkExternalService() {
// Implementation to check external service
return true;
}
}
package com.example.demo.config;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MetricsConfig {
@Bean
public Counter userCreationCounter(MeterRegistry registry) {
return Counter.builder("users.created")
.description("Number of users created")
.tag("type", "registration")
.register(registry);
}
@Bean
public Timer userProcessingTimer(MeterRegistry registry) {
return Timer.builder("users.processing.time")
.description("Time taken to process user requests")
.register(registry);
}
}
Spring Boot Actuator provides production-ready features—health checks, metrics, info endpoints. /actuator/health shows application status for load balancers. /actuator/metrics exposes JVM metrics, HTTP stats, custom metrics. /actuator/info displays application metadata. Custom health indicators check dependencies—database, Redis, external APIs. Micrometer integrates with monitoring systems like Prometheus, Grafana, Datadog. Endpoint security restricts sensitive data. Management port separates actuator from application traffic. Graceful shutdown enables zero-downtime deployments. Custom endpoints extend functionality. Actuator enables observability—essential for debugging production issues, capacity planning, and SLA monitoring. I expose relevant endpoints based on environment and secure them appropriately.