Skip to main content

Health checks

/healthz and /readyz are also reachable through the UI on port 8080. The worker writes a heartbeat every 10 seconds and removes it when it stops cleanly, so a heartbeat age of null or above 30 seconds means the worker is not running. The UI shows a banner when storage is unavailable.

Logs

Every log line is one JSON object with ts, level, logger, and msg, plus fields for the event and exc for a traceback. Tokens, secrets, message content, and full attribute maps are never logged. Set the level with APGAR_LOG_LEVEL.

Prometheus metrics

The API serves GET /metrics on port 8000. The worker serves GET /metrics on port 8001. When APGAR_WORKER_METRICS_URL is set, as in the compose file, the API also includes the worker’s turn, assembly, and rollup metrics. Scrape both processes to get everything. The Compose file publishes neither port. Run Prometheus on the Compose network, or publish the ports in docker-compose.override.yml, bound to an address that only Prometheus reaches:
docker-compose.override.yml
On Kubernetes with the Prometheus Operator, enable the chart’s ServiceMonitor. It scrapes the API and the worker directly, and the chart leaves APGAR_WORKER_METRICS_URL unset. Add the labels your Prometheus selects ServiceMonitors by, for example:
values.yaml
metrics.prometheusRule adds alerts for a process that stops answering on /metrics, assembly lag above 30 minutes, and ingest requests that fail to write to ClickHouse. With networkPolicy.enabled, allow Prometheus to reach the worker, or the worker is not scraped:
values.yaml
Labels are low cardinality. Counter names end in _total.

Ingest

Assembly

Verdicts and jobs

Langfuse

Notifications and telemetry

What to alert on

  • /readyz not 200.
  • Worker heartbeat age null or above 60 seconds.
  • apgar_assembly_lag_seconds well above APGAR_ASSEMBLY_MAX_AGE_SECONDS.
  • apgar_job_last_success_timestamp_seconds for verdict or notifications older than a few intervals.
  • apgar_notifications_failed_rows above 0.