Logs, health and metrics
The server logs JSON lines to standard error, one object per line with the time, the level, the message and the fields of the event. Requests carry a request id. The logs never contain a token, a password, an email address or the body of a record.
docker compose logs -f pdsLOG_LEVEL sets the filter: info by default, debug for everything,
or a filter by crate such as info,pds_oauth=debug. It takes effect at
the next start.
Health
Section titled “Health”curl -s https://pds.example.com/xrpc/_healthStatus 200 when the account database answers; 503 with
"error":"Service Unavailable" when it does not. The container’s health
check runs linkjar-pds health every ten seconds against the same route,
and Caddy waits for the first pass before it starts.
docker compose psThe pds service shows (healthy).
Metrics
Section titled “Metrics”PDS_METRICS_ADDRESS starts a private listener in Prometheus text
format. It must not be reachable from the public name, so bind it to the
container’s address and publish it on the host’s loopback only.
In pds.env:
PDS_METRICS_ADDRESS=0.0.0.0:9464In compose.yml, under the pds service:
ports: - "127.0.0.1:9464:9464"Then:
curl -s http://127.0.0.1:9464/metrics| Metric | What it is |
|---|---|
pds_build_info |
the version, as a label |
pds_http_requests_total{route,status} |
requests by method and status |
pds_http_request_duration_seconds{route} |
a histogram of latency by method |
pds_firehose_subscribers |
open firehose connections |
pds_audit_entries |
entries in the audit log |
pds_audit_unsigned_entries |
entries not yet under a signed checkpoint |
pds_audit_checkpoint_age_seconds |
time since the last checkpoint |
pds_notice_outbox_depth |
mail waiting to go out, in the linkjar profile |
A route label is a method the server handles, a path it knows,
proxied or other, so a client cannot make up a label.
What to alert on
Section titled “What to alert on”| Signal | Means |
|---|---|
pds_http_requests_total{status=~"5.."} rising |
the server fails requests; read the logs |
the 99th percentile of pds_http_request_duration_seconds |
the host is short of CPU or disk, or a client is heavy |
pds_audit_unsigned_entries above 0 for more than ten minutes |
checkpoints stopped; the key is missing or the clock is off |
pds_notice_outbox_depth growing |
SMTP fails |
pds_firehose_subscribers at 0 for long |
the relay is not connected; see the first account |
Rate limits
Section titled “Rate limits”The reference server’s limits run by default: by client address for
requests overall and for sign-ups and sign-ins, and by account for writes.
Every answer carries RateLimit-Limit, RateLimit-Remaining and
RateLimit-Reset; a refused request is a 429 with Retry-After. The
client’s address comes from the connection, so the server sees Caddy’s
forwarding correctly inside the Compose network.
