ServerlessIRCd Docs

Docs home

Observability

The server ships a structured-logger port that every adapter uses to emit JSON log lines carrying a per-request traceId and per-connection connectionId. The canonical event names are the contract dashboards and log queries are built against.

Log contract

Every record is one physical line of JSON with at least:

Field Source
ts ISO-8601 timestamp from the injected Clock.
level debug / info / warn / error.
msg Event name (see below).
traceId Per-request id; fresh per inbound frame.
connectionId The bound connection's id (ConnId).

Additional structured fields appear per event. The msg catalogue:

msg Level Emitted by Notes
frame.receive debug ConnectionActor One per parsed IRC line. Fields: command, lines.
frame.parse-error warn ConnectionActor A line failed to parse. Fields: line, token.
dispatch debug dispatch() Before interpreting an effect list. Fields: effects (array of tags), histogram.
dispatch.error warn dispatch() A runtime method rejected. Fields: effect, err.

Adapters may emit their own events (e.g. local-cli listening, shutdown) following the same shape.

Cloudflare Workers

The apps/cf-worker/wrangler.toml enables [observability] so every console.* line emitted by the ConsoleLogger inside ConnectionDO is captured by Workers Analytics.

Workers Analytics dashboards can be built on the Cloudflare dashboard under Workers & Pages → → Observability.

AWS (Lambda + API Gateway WebSocket)

The Lambda handler writes to CloudWatch Logs via the global console. Each invocation emits one JSON line per log record; the log group name follows the standard /aws/lambda/<function-name> convention.

A starter CloudWatch dashboard is checked in at dashboards/cloudwatch-irc.json. Provision it via:

aws cloudwatch put-dashboard \
  --dashboard-name ServerlessIRCd-staging \
  --dashboard-body file://dashboards/cloudwatch-irc.json

The dashboard variables (API_ID, LAMBDA_NAME, LOG_GROUP_ARN, AWS_REGION) are templated by CloudWatch's dashboard variables feature — set them once in the dashboard UI after import.

Sample CloudWatch Logs Insights query — count dispatched effects by tag over the last hour:

fields @timestamp, msg, fields.histogram
| filter msg = "dispatch"
| sort @timestamp desc

Local CLI

The local-cli server uses the same ConsoleLogger so the structured stream is visible while developing:

{"ts":"2026-07-22T12:34:56.789Z","level":"debug","msg":"frame.receive","traceId":"…","connectionId":"…","command":"PRIVMSG","lines":1}

Filter with jq:

pnpm --filter local-cli start | jq 'select(.msg=="dispatch.error")'