Spring Boot Actuator and Observability

Introduction

Production services need health checks, metrics, and safe operational endpoints—not guesswork from log tailing alone. Spring Boot Actuator exposes /actuator/health, metrics via Micrometer, and optional integration with Prometheus and Grafana. This chapter enables Actuator securely and outlines logs + metrics + tracing as one observability stack.

Prerequisites

Add Actuator

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Expose endpoints:

yaml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: when_authorized

Default base path: /actuator.

Health Endpoint

bash
curl http://localhost:8080/actuator/health

Example response:

json
{
  "status": "UP"
}

With DB on classpath, db indicator appears:

json
{
  "status": "UP",
  "components": {
    "db": { "status": "UP" },
    "diskSpace": { "status": "UP" }
  }
}

Kubernetes liveness/readiness probes often hit /actuator/health/liveness and /actuator/health/readiness when configured.

Custom health indicator:

Application Info

yaml
info:
  app:
    name: demo-service
    version: 1.0.0
 
management:
  info:
    env:
      enabled: true
bash
curl http://localhost:8080/actuator/info

Metrics With Micrometer

Actuator registers JVM, HTTP, and datasource metrics automatically.

List names:

bash
curl http://localhost:8080/actuator/metrics

Single metric:

bash
curl "http://localhost:8080/actuator/metrics/http.server.requests"

Custom counter:

Prometheus Scraping

xml
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
yaml
management:
  endpoints:
    web:
      exposure:
        include: health,prometheus

Prometheus scrapes /actuator/prometheus. Grafana dashboards visualize latency, error rate, and JVM heap.

Secure Actuator in Production

Warning

Do Not Expose All Endpoints Publicly

/actuator/env and /actuator/beans leak internals—restrict by network or Spring Security.

yaml
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
  server:
    port: 9091

Separate management port on internal network only.

Integrate with Spring Security:

java
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/**").hasRole("ADMIN")

Logs + Metrics + Tracing

PillarTooling
LogsLogback JSON, centralized ELK/Loki
MetricsMicrometer → Prometheus → Grafana
TracingMicrometer Tracing + OpenTelemetry + Zipkin/Jaeger

Add tracing starter (concept):

xml
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>

Trace id in logs correlates slow HTTP span with SQL—debug production latency.

FAQ

Actuator 404?

Missing dependency or endpoints not in exposure.include.

Health DOWN but app runs?

DB/Redis unreachable—fix dependency or disable indicator in dev.

High cardinality metrics?

Avoid unbounded tags (user id on every counter)—explodes Prometheus.

Actuator vs custom /health?

Actuator standardizes probes—prefer over ad-hoc endpoint.

Cloud platform metrics?

AWS CloudWatch, Azure Monitor via Micrometer registries—same MeterRegistry API.

Sensitive env in /actuator/env?

Keep endpoint disabled in prod or sanitize properties.