Skip to content

Improve logging: structured app-wide logging + optional external log shipping #104

@rado0x54

Description

@rado0x54

Background

Current logs are dominated by health-check 200 request lines, while important subsystems (push notifications, WebAuthn signing flow, WebSocket lifecycle, MCP) produce little to no useful output. Debugging issues like the recurring iOS PWA push-notification disablement is hard because we can't see whether pushes were sent, accepted, or rejected (e.g. 410 Gone from APNs/FCM bridge).

Concrete recent example: notifications silently disable on the installed iPhone PWA. Logs show /api/push/subscribe being called on every app open (suggesting subscription eviction) and [WebAuthn Agent] Sign rejected … Signing request expired warnings, but nothing about whether web-push.sendNotification succeeded or what the push provider returned.

a) Structured app-wide logging

  • Audit log call sites and add structured logs (with reqId correlation where applicable) for:
    • Push: subscribe / unsubscribe / send result (status, endpoint host, ttl) / dead-subscription cleanup on 404/410
    • WebAuthn signing flow: request created, delivered to client, resolved/expired/rejected (with timing)
    • WebSocket: connect / auth / disconnect / reconnect with reason
    • MCP: tool invocations and errors
    • Auth: login success/failure, session creation
  • Demote noisy health-check / polling request logs (separate logger or level: debug, or filter from access log).
  • Standardize on a single logger config (pino) with consistent fields (module, event, userId where safe).

b) Optional external log shipping

Make log destination configurable via env so a self-hosted aggregator can be plugged in. Candidates worth evaluating:

  • Loki + Grafana (Grafana Labs) — lightweight, label-based, pairs naturally with the existing Grafana ecosystem. Probably the best fit.
  • SigNoz — full observability (logs + traces + metrics), ClickHouse-backed.
  • OpenObserve — single-binary, S3-backed, low resource use.
  • Graylog — heavier but mature.

Likely approach: ship pino JSON logs to stdout (already the case) and let the operator wire up Promtail/Vector/Fluent Bit to forward to the chosen backend. Document the recommended setup in docs/.

Acceptance

  • Triggering a push notification produces a clear log line including the provider response.
  • Failed/expired subscriptions are logged and cleaned up from the DB.
  • Health-check spam is no longer the dominant log output.
  • README/docs describe how to forward logs to an external aggregator.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions