Health
Metrics
GET /metrics on the server, in Prometheus text format. It needs an auditor credential (a bearer token in your scrape
config), unless REVERSI_METRICS_PUBLIC=1 (only on a private network).
Useful alerts:
reversi_halted == 1, a rising rate of reversi_ledger_events_total{event="compensation_failed"},
reversi_approvals{status="pending"} above zero for longer than your approval SLA, and readyz failing. Most of these are
also available as built-in alerts below, delivered to the places you already watch.
Logs
REVERSI_LOG=json makes the server write one line per request:
createLogger from @multimindlab/reversi writes one JSON object per line
({"level","time","msg",…fields}) at debug, info, warn or error, with child loggers for fixed fields. It redacts
before writing: credential patterns inside any string, and the whole value of any field whose name looks like a secret
(password, secret, token, authorization, api_key, cookie, credential, private_key, signature). The log:
section of reversi.config.yaml configures the engine’s own logger, which writes reloads, failed notifications, anchors and
trace export errors to stderr:
reversi.config.yaml
json writes redacted JSON lines ({"level":"warn","time":"…","msg":"…"}); pretty writes reversi [warn] message.
REVERSI_LOG=json is separate: it only controls the per-request line of the server.
Alerts
Alerts are conditions worth a human, computed from the ledger, run state, approvals and (on the gateway) upstream health. They are always visible: the console Alerts page andGET /v1/alerts (auditor and up) evaluate them live. When
notification channels are configured, an alert manager also sends them.
Event-based kinds look at the last 15 minutes of the ledger, so they clear on their own.
compensation_failed,
unresolved_outcome and halted are state-based and stay until fixed or lifted.
reversi.config.yaml
remind while it persists, and a Resolved: message
(which closes the PagerDuty or Opsgenie incident) when the condition clears. State is kept in the data store, so several
processes sharing it do not repeat each other. denial_spike is honoured by the manager, GET /v1/alerts and the console Alerts page alike. The window and the one-hour unresolved limit are not configurable in the
project file. The manager only runs when at least one channel is configured; with none, use the console or GET /v1/alerts.
Tracing
Reversi exports OpenTelemetry traces over OTLP/HTTP with JSON. There is no SDK to install.reversi.config.yaml
REVERSI_OTLP_ENDPOINT sets the endpoint without a file. The server and gateway export while running.
All spans of a run share one trace id (derived from the run id), so a run is one trace. Attributes:
reversi.run_id, reversi.step, reversi.tool, reversi.actor, reversi.effect (from the manifest),
reversi.event, reversi.reason, reversi.detail, reversi.seq.start and reversi.seq.end (the ledger positions, so a
span links back to the evidence). The resource carries service.name (default reversi) and deployment.environment
(from environment:). Spans carry names and ids, never arguments or results.
Spans are sent in batches of 50 or every five seconds, with a 10 s timeout, through the
egress guard. A failing collector is logged to stderr and never affects calls.
