How it works
The explanation, with examples you can run.
Expose with intent
management: endpoints: web: exposure: include: health,info,prometheus endpoint: health: show-details: when-authorized # default: never probes: enabled: true # on automatically when running on Kubernetes server: port: 8081 # keep management traffic off the public portOnly health is exposed over HTTP by default. Add what you need, and protect or isolate the rest; env, heapdump and loggers can reveal secrets or change behaviour.
Health, liveness and readiness
/actuator/health aggregates HealthIndicators: the database, disk space, message brokers and your own. On Kubernetes, Boot also exposes two health groups:
/actuator/health/liveness: is the application's internal state broken beyond repair? If this fails, the container is restarted./actuator/health/readiness: can it take traffic now? If this fails, the pod is taken out of the load balancer until it recovers.
By default neither group includes external checks such as the database, and that is deliberate: if a shared database is down, restarting every instance helps nobody. You can add an indicator to readiness with management.endpoint.health.group.readiness.include=readinessState,db if traffic really should drain.
Metrics
Things you get without writing code include http.server.requests (a timer per method, URI template, status and outcome), jvm.memory.used, jvm.gc.pause, hikaricp.connections.*, tomcat.sessions.* and executor metrics. Your own are a few lines:
@Componentclass CheckoutMetrics { private final Counter declined; CheckoutMetrics(MeterRegistry registry) { declined = Counter.builder("checkout.payments.declined") .tag("provider", "stripe") .register(registry); } void onDeclined() { declined.increment(); }}Keep tag values bounded. A tag holding a user id or a raw URL creates a new time series per value and can overwhelm the metrics backend.
Observations and traces
An Observation wraps a piece of work once and feeds several handlers: a timer for metrics and, when a tracer such as Micrometer Tracing with an OpenTelemetry or Brave bridge is on the classpath, a span.
Observation.createNotStarted("inventory.reserve", registry) .lowCardinalityKeyValue("warehouse", warehouseId) .observe(() -> inventory.reserve(order));Boot propagates the trace context on outgoing calls made with the auto-configured RestClient.Builder, RestTemplateBuilder or WebClient.Builder, and can put the trace id into every log line, so one slow checkout can be followed from the gateway through each service to the query that took the time.
Follow the flow
Play it or step through. Pause and tap a box to see what it does.
Paused · tap a box to explore it
Your code records to Micrometer once. This counter goes up every time a payment is declined, and the code never mentions Prometheus.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.