Skip to content

Monitor Your Application with the Winter Boot Actuator

The Actuator exposes operational information about your running application over HTTP, with no controller code: registered beans, configuration properties, environment variables, scheduled tasks, request mappings, Prometheus metrics, and the health of your dependencies. Load balancers, orchestrators, and monitoring agents can use these JSON endpoints to check on the service.

All Actuator endpoints are disabled by default. Turn on the global switch, then enable each endpoint you want in application.yml. Each endpoint can also be mounted at a custom path.

application.yml
management:
endpoints:
enabled: true # global switch — must be true for any endpoint to work
endpoint:
beans:
enabled: true
path: "manage/beans"
configprops:
enabled: true
path: "manage/configprops"
env:
enabled: true
path: "manage/env"
health:
enabled: true
path: "manage/health"
info:
enabled: true
path: "manage/info"
mappings:
enabled: true
path: "manage/mappings"
scheduledtasks:
enabled: true
path: "manage/scheduledtasks"
prometheus:
enabled: true
path: "manage/prometheus"
heapdump:
enabled: true
path: "manage/heapdump"
Endpoint Default path Description
beans /beans Lists all beans registered in the application context.
configprops /configprops Displays all application.yml properties (secret-looking values masked).
env /env Exposes environment variables (secret-looking values masked).
health /health Aggregated health status from all #[HealthInformer] beans. Answers HTTP 503 when the status is DOWN or OUT_OF_SERVICE, otherwise 200.
info /info Application information contributed by #[InfoInformer] beans.
mappings /mappings Lists all registered HTTP route mappings.
scheduledtasks /scheduledtasks Shows all tasks registered with the #[Scheduled] attribute.
prometheus /prometheus Prometheus metrics, including http_request_duration labeled by route template (e.g. /users/{id}) and method, recorded from each worker’s first request.
heapdump /heapdump Lists the server’s processes (master, workers, task processes) with PID and memory details.

Each endpoint is served at its default path unless you set path. The example above moves them all under manage/.

Once an endpoint is enabled and the application is running, query it with a standard HTTP request:

Terminal window
curl http://localhost:8080/manage/health
curl http://localhost:8080/manage/info

The health endpoint combines the status reported by every class that implements HealthIndicator and is annotated with #[HealthInformer]. Add one for each dependency you care about: databases, message brokers, external APIs, and so on.

Implement the health(): Health method and return one of the Health factory methods for the appropriate state:

Method Description
Health::up() Service is healthy and available.
Health::down(?Throwable $ex = null) Service is unavailable. Pass a Throwable to have the exception class and message added as the error detail.
Health::outOfService() Service is intentionally taken out of service (e.g. maintenance).
Health::unknown() Health state cannot be determined.
Health::status(string $statusCode) Custom status code for non-standard states.
DatabaseHealthIndicator.php
use dev\winterframework\actuator\HealthIndicator;
use dev\winterframework\actuator\Health;
use dev\winterframework\actuator\stereotype\HealthInformer;
use dev\winterframework\stereotype\Autowired;
use dev\winterframework\pdbc\PdbcTemplate;
#[HealthInformer]
class DatabaseHealthIndicator implements HealthIndicator
{
#[Autowired]
private PdbcTemplate $pdbc;
public function health(): Health
{
try {
$this->pdbc->queryForScalar('SELECT 1');
return Health::up();
} catch (\Throwable $ex) {
return Health::down($ex)->withDetail('database', 'connection check failed');
}
}
}

The response status follows the aggregated health, so load balancers, Kubernetes probes and Docker HEALTHCHECKs that read only the status code see an unhealthy instance: DOWN and OUT_OF_SERVICE answer 503 Service Unavailable, UP and UNKNOWN answer 200 OK. The JSON body is the same in both cases.

Custom Application Info with InfoContributor

Section titled “Custom Application Info with InfoContributor”

The info endpoint is populated by beans that implement InfoContributor and are annotated with #[InfoInformer]. Use it to surface metadata such as the application name, version, build timestamp, or Git revision.

Implement the contribute(InfoBuilder $info): void method and call $info->withDetail(key, value) for each piece of information you want to expose. The method is chainable.

ApplicationInfoContributor.php
use dev\winterframework\actuator\InfoContributor;
use dev\winterframework\actuator\InfoBuilder;
use dev\winterframework\actuator\stereotype\InfoInformer;
#[InfoInformer]
class ApplicationInfoContributor implements InfoContributor
{
public function contribute(InfoBuilder $info): void
{
$info->withDetail('appName', 'ExampleMicroService')
->withDetail('appVersion', '1.0.0-1')
->withDetail('buildTimestamp', '2024-01-15T10:30:00Z');
}
}

Querying the info endpoint returns a JSON object that merges all contributors:

Terminal window
curl http://localhost:8080/manage/info
# {"appName":"ExampleMicroService","appVersion":"1.0.0-1","buildTimestamp":"2024-01-15T10:30:00Z"}