Observability
The status endpoint, Prometheus metrics, and per-request decision fields in access logs.
The status endpoint and metric set are the same across every adapter; each front-end only chooses how to expose them.
Status endpoint All adapters
Service.Status() returns the full engine state as JSON:
- Active and last-good bundle IDs: what’s serving now and what the fallback is.
- Reconciler state: desired vs. active bundle, quarantine status, current backoff, the last activation test report, and activation counters.
- Pool stats: target size, live instances, in-flight invocations, exhaustion count.
How to reach it per adapter:
switchboard serve:GET /switchboard/status; use--status-listen :9090to keep status and metrics off the public listener.- Caddy: set the
status_pathdirective (e.g.status_path /switchboard/status). - Embedded: mount
httpadapter.StatusHandler(service), or callService.Status()directly. See embedding.
Prometheus metrics All adapters
The same switchboard_* collectors are recorded by every adapter:
| Metric | Type | Labels | Meaning |
|---|---|---|---|
switchboard_invocations_total |
counter | decision, result |
Rule invocations, by decision and outcome. |
switchboard_invocation_duration_seconds |
histogram | — | Guest execution latency. |
switchboard_pool_instances |
gauge | — | Warm Wasm instances in the active pool. |
switchboard_pool_inflight |
gauge | — | Invocations currently executing. |
switchboard_pool_exhaustions_total |
counter | — | Requests that found no free instance. |
switchboard_activation_total |
counter | result |
Bundle activation attempts, by outcome. |
Where they are served:
switchboard serve:GET /metrics(its own registry).- Caddy: registered on Caddy’s default registry, so they appear on Caddy’s admin
/metricsendpoint next to Caddy’s own metrics. - Embedded: call
httpadapter.NewMetrics(registerer, service)and expose your registry however you like.
Labels are deliberately low-cardinality; keep tenant IDs, paths, and user IDs in logs, not metrics. Alerts worth having: switchboard_activation_total{result="failure"} increasing (deploys failing their gates) and any switchboard_pool_exhaustions_total growth (undersized pool).
Access log fields Caddy only
Under Caddy, every request’s access log entry carries:
| Field | Value |
|---|---|
switchboard_decision |
next, deny, redirect, rewrite, or respond. |
switchboard_reason |
The rule’s WithReason label, when set. |
switchboard_bundle_id |
The exact bundle that made the decision. |
switchboard_bundle_id is the piece that makes incidents tractable: any logged decision points at the precise, immutable artifact responsible, which switchboard history maps back to a generation, deployer, and commit.
Request variables Caddy only
The Caddy adapter also sets switchboard.decision and switchboard.reason as request variables, plus one variable per SetMetadata key, usable in matchers and placeholders anywhere downstream in the route. See routing on rule metadata.
Proxy-level telemetry Caddy only
Switchboard deliberately doesn’t duplicate transport metrics. Caddy’s own Prometheus/OTLP middleware covers request latency, sizes, and status codes; Switchboard’s metrics cover only what the rules add.