Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Observe a running server

This page covers the four ways to watch a running boatramp server: the JSON access log, the health endpoints, the Prometheus metrics endpoint, and the per-site CLI (logs and stats). Each is one command or one endpoint away.

For the full metric list and the full set of access-log fields, see the metrics reference. This page covers only how to reach them.

Read the access log

Every request is logged on the boatramp::access tracing target. Set BOATRAMP_LOG_FORMAT=json for a machine-readable sink, and start the server:

BOATRAMP_LOG_FORMAT=json boatramp serve

Each request writes one JSON object to stdout:

{"target":"boatramp::access","request_id":"1a2b3c-4","method":"GET","path":"/index.html","host":"my-site.example","client_ip":"203.0.113.7","status":200,"bytes":1841,"encoding":"br","cache_result":"full","duration_ms":3}

The request_id is assigned per request (an inbound X-Request-Id is honored, else generated), and the same id tags the request’s captured guest log lines — so you can correlate a handler’s output with its access line. The cache_result field is one of full, partial, not-modified, redirect, or error. Verbosity follows RUST_LOG (default boatramp=info). Pipe the sink to your log shipper, or to jq to read one field:

BOATRAMP_LOG_FORMAT=json boatramp serve | jq -r 'select(.target=="boatramp::access") | .status'
200
304
200

Check health

Two endpoints report health. Point a load balancer or orchestrator probe at them:

EndpointMeaning
/healthzLiveness — the process is up.
/readyzReadiness — a cheap KV probe; returns 503 when the metadata backend is unreachable.

Probe readiness — a 503 means the process is up but the metadata backend is unreachable, so route no traffic to this node yet:

curl -i http://localhost:8080/readyz
HTTP/1.1 200 OK

ready

Scrape metrics

An admin-scoped Prometheus exporter is always served at /api/metrics, carrying the process-wide serving and lifecycle counters. With the handlers feature it also renders per-handler invocation counters and per-consumer queue-depth and dead-letter gauges. Scrape it:

curl http://localhost:8080/api/metrics
# HELP boatramp_http_requests_total requests by status class and cache result
# TYPE boatramp_http_requests_total counter
boatramp_http_requests_total{status_class="2xx",cache_result="full"} 1420
boatramp_http_requests_total{status_class="3xx",cache_result="not-modified"} 87
boatramp_deployments_total 12
boatramp_activations_total 9

For every metric, its labels, and their meaning, see the metrics reference.

Tail guest logs and read handler stats

For sites running handlers, two commands report per-site activity. Tail the captured guest stdout, stderr, and wasi:logging messages, with --follow to stream new lines:

boatramp logs my-site --follow
2026-07-09T12:04:11Z my-site http/GET/api/hello  stdout  handling request id=7f3a
2026-07-09T12:04:19Z my-site queue/emails        stderr  retry 1: upstream timeout

Tail a function’s logs

A standalone function — a GraphQL subgraph, an auth function, or a worker invoked through emit::invoke rather than served under a site — captures its guest output the same way, but under its own scope. Tail it with --function (since 0.3.17); the flag takes precedence over --site / BOATRAMP_SITE, and --project scopes it to a non-default project:

boatramp logs --function my-worker --follow

The logs read from GET /api/functions/<name>/_boatramp/logs (and /stream when --follow is set) — the same captured-log store as the per-site endpoint, under the function’s project-qualified scope, so a project-scoped token reaches only its own functions’ logs.

Read invocation counts, consumer lag, and dead-letter totals:

boatramp stats my-site
site my-site
  http/GET/api/hello   invocations 1420   errors 3
  queue/emails         invocations  512   errors 1   lag 0   dead-letters 2

Messages that exhaust their retry budget are dead-lettered — kept with their payload and counted here. Inspect the cause in logs, then redrive or purge them; see Run consumers, crons, and streams.

On a cluster, the stats JSON also carries an async_shards block: for each function this node drains, its owning_node and queued depth, plus a safetynet_only_drains counter. Use it to answer “which node drains this function?” and to tell a shard gap (a function briefly owned by no node) from a slow drain: a rising safetynet_only_drains means the unsharded backstop is covering work the owner isn’t picking up (work is still draining), whereas a climbing queued with a flat counter is a genuinely stalled drain. The messaging_safetynet_interval_ms knob (which paces the delivery backstop) also bounds how quickly that async no-owner gap is recovered.

Captured guest lines are also mirrored to the server log under the boatramp::guest target (at debug), so RUST_LOG=boatramp=debug surfaces guest output in serve.log too — handy in development. Each captured line carries the request’s request_id (above). A site that opts out with disable_log_capture captures nothing — its guest stdio is discarded, useful when output may carry secrets.

Reference