Actuator & Observability
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
<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:
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.0The startup log confirms it:
INFO 20800 --- [academy] [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 3 endpoints beneath base path '/actuator'
Health
curl http://localhost:8080/actuator/health{"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
curl http://localhost:8080/actuator/info{"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:
{"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:
curl http://localhost:8080/actuator/metrics/jvm.memory.used{"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:
@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,heapdumpandloggersare powerful; if you expose them, protect them with Spring Security (for example, require anADMINrole for/actuator/**excepthealth). - Endpoints you did not expose return 404, as
/actuator/envdid in the academy app. - You can run Actuator on a separate port (
management.server.port=9090) that is reachable only inside your network. shutdownis 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=alwaysin production. Usewhen-authorized.- Watching only "UP". An API can be up and still slow or failing half its requests; alert on
http.server.requestslatency 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-actuatoradds endpoints under/actuator; onlyhealthis exposed over HTTP by default.management.endpoints.web.exposure.includechooses the exposed endpoints; keep the list short and secure sensitive ones.- Health aggregates checks such as
dbanddiskSpaceand provides liveness and readiness groups. - Micrometer records metrics such as
http.server.requestsandjvm.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
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<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?
Only health is exposed by default; others must be included explicitly.
2. What does the health endpoint return when the database check fails?
A load balancer or Kubernetes can then stop routing traffic to that instance.
3. What is Micrometer?
It lets you record metrics once and send them to Prometheus, cloud systems and more.
4. Why should you not tag a metric with each user's phone number?
Tags must have a small, bounded set of values.
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
