EthicsComputerCourses
Join training +91 90532 10052

Actuator & Observability

Spring Boot · Lesson 23 of 29 Advanced 7 min read Updated

Once the academy API runs on a server, new questions appear. Is it up? Is the database reachable? How many requests per minute does /api/players get, and how slow are they? Which version is deployed? Spring Boot Actuator answers these through ready-made HTTP endpoints, and its metrics feed monitoring systems used in production.

In this lesson you will add Actuator, read the health, info and metrics endpoints, choose what to expose, and see how the three pillars of observability (metrics, logs and traces) map onto Spring Boot.

Adding Actuator

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

By default only the health endpoint is available over HTTP, under the base path /actuator. That is a safe default: other endpoints can reveal configuration and internals. The academy exposes two more and turns on some details:

Properties
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always
management.info.env.enabled=true
info.app.name=Pune Cricket Academy API
info.app.version=1.0.0

The startup log confirms it:

Output
INFO 20800 --- [academy] [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 3 endpoints beneath base path '/actuator'

Health

Terminal
curl http://localhost:8080/actuator/health
Output
{"components":{"db":{"details":{"database":"H2","validationQuery":"isValid()"},"status":"UP"},"diskSpace":{"details":{"total":254611025920,"free":59414204416,"threshold":10485760,"path":"...","exists":true},"status":"UP"},"livenessState":{"status":"UP"},"ping":{"status":"UP"},"readinessState":{"status":"UP"},"ssl":{"details":{"expiringChains":[],"invalidChains":[],"validChains":[]},"status":"UP"}},"groups":["liveness","readiness"],"status":"UP"}

(The disk path is shortened.) Actuator found the data source and checks it (db), checks free disk space, and reports liveness and readiness. The overall status is UP only when every component is up; if the database is down it becomes DOWN and the endpoint answers 503, so a load balancer can stop sending traffic. Kubernetes uses /actuator/health/liveness ("restart me if this fails") and /actuator/health/readiness ("do not send me requests yet").

show-details=always is handy while learning. In production use never (the default) or when-authorized, because details reveal your database type and disk layout.

You can add your own check by writing a bean that implements HealthIndicator, for example to report whether the SMS gateway is reachable.

Info

Terminal
curl http://localhost:8080/actuator/info
Output
{"app":{"name":"Pune Cricket Academy API","version":"1.0.0"}}

The info.* properties appear here because management.info.env.enabled=true. The Spring Boot Maven plugin's build-info goal and the git-commit-id plugin can add the exact build time and Git commit, which is invaluable when someone asks "which version is running?".

Metrics with Micrometer

Actuator records metrics through Micrometer, a library that works like a logging facade for numbers: your code and Spring record measurements once, and Micrometer exports them to whichever monitoring system you use. /actuator/metrics lists the names:

Output
{"names":["application.ready.time","application.started.time","disk.free","disk.total",...,"hikaricp.connections.active",...,"http.server.requests","http.server.requests.active","jdbc.connections.active",...,"jvm.memory.used",...,"process.cpu.usage","process.uptime","spring.data.repository.invocations",...,"tomcat.sessions.active.current"]}

(The list has more than 60 names; some are left out here.) Ask for one metric by name:

Terminal
curl http://localhost:8080/actuator/metrics/jvm.memory.used
Output
{"availableTags":[{"tag":"area","values":["heap","nonheap"]},{"tag":"id","values":["CodeHeap 'profiled nmethods'","G1 Old Gen","CodeHeap 'non-profiled nmethods'","G1 Survivor Space","Compressed Class Space","Metaspace","G1 Eden Space","CodeHeap 'non-nmethods'"]}],"baseUnit":"bytes","description":"The amount of used memory","measurements":[{"statistic":"VALUE","value":2.14043968E8}],"name":"jvm.memory.used"}

About 214 MB of memory in use. Tags let you narrow a metric, for example ?tag=area:heap. The most useful metric for an API is http.server.requests: count, total time and maximum time per URI pattern, method and status, recorded automatically for every controller. Spring Data also times every repository call (spring.data.repository.invocations), and HikariCP reports how busy the connection pool is.

Your own business metrics are a few lines:

Java
@Service
public class AdmissionMetrics {

    private final Counter admissions;

    public AdmissionMetrics(MeterRegistry registry) {
        this.admissions = Counter.builder("academy.admissions")
                .description("Players admitted")
                .register(registry);
    }

    public void recordAdmission() {
        admissions.increment();
    }
}

Exporting metrics: Prometheus and Grafana

Reading JSON by hand is for debugging. In production a monitoring system collects metrics every few seconds and draws dashboards and alerts. A common open-source setup is Prometheus with Grafana: add io.micrometer:micrometer-registry-prometheus, include prometheus in the exposure list, and Prometheus scrapes /actuator/prometheus. Cloud platforms have their own Micrometer registries.

Logs and traces

Observability has three pillars:

  • Metrics: numbers over time (requests per second, error rate, memory). Micrometer.
  • Logs: what happened, line by line. Covered in the next lesson, Logging.
  • Traces: the path of one request through several services, with timings for each step. Micrometer Tracing records them; Spring Boot 4 offers an OpenTelemetry starter (the "OpenTelemetry" dependency on Initializr) to export metrics and traces in the vendor-neutral OpenTelemetry format.

When tracing is on, each log line carries the trace and span IDs, so you can jump from a slow trace to its log lines.

Securing Actuator

  • Expose only what you need. env, beans, configprops, heapdump and loggers are powerful; if you expose them, protect them with Spring Security (for example, require an ADMIN role for /actuator/** except health).
  • Endpoints you did not expose return 404, as /actuator/env did in the academy app.
  • You can run Actuator on a separate port (management.server.port=9090) that is reachable only inside your network.
  • shutdown is off by default; leave it off unless you have a good reason.

Common mistakes

  • management.endpoints.web.exposure.include=* on a public server. It exposes environment variables, configuration and heap dumps.
  • show-details=always in production. Use when-authorized.
  • Watching only "UP". An API can be up and still slow or failing half its requests; alert on http.server.requests latency and error rates too.
  • High-cardinality tags. Never tag metrics with user IDs or phone numbers: every unique value creates a new time series.

Key points

  • spring-boot-starter-actuator adds endpoints under /actuator; only health is exposed over HTTP by default.
  • management.endpoints.web.exposure.include chooses the exposed endpoints; keep the list short and secure sensitive ones.
  • Health aggregates checks such as db and diskSpace and provides liveness and readiness groups.
  • Micrometer records metrics such as http.server.requests and jvm.memory.used; export them to Prometheus or a cloud system.
  • Observability combines metrics, logs and traces; Spring Boot 4 supports OpenTelemetry export.

Exercise

Configure the academy for production monitoring: expose health, info and prometheus only, show health details only to users with the ADMIN role, move Actuator to port 9090, and add an info.app.owner value of "Academy IT". Write the properties and the dependency needed for Prometheus.

Show solution
Properties
management.server.port=9090
management.endpoints.web.exposure.include=health,info,prometheus
management.endpoint.health.show-details=when-authorized
management.endpoint.health.roles=ADMIN
management.info.env.enabled=true
info.app.owner=Academy IT
XML
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

The Micrometer version is managed by Spring Boot, so no <version> is needed. With a separate management port, the firewall can allow 8080 from the internet and 9090 only from the monitoring server. Details appear only for authenticated users holding the ADMIN role.

Quick Quiz

1. Which Actuator endpoint is exposed over HTTP by default?

2. What does the health endpoint return when the database check fails?

3. What is Micrometer?

4. Why should you not tag a metric with each user's phone number?

Learn Spring Boot with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call