Skip to main content

Logging: platform log page

Nexus aggregates logs from every componentnexus-core, nexus-worker, nexus-telegram, and the per-run nexus-agent-runner pods — into one queryable place: the Admin UI Logs page. Use it to confirm agents connect, NATS and MongoDB are reachable, and LLM calls aren't erroring.

Why this design (NATS and MongoDB)

The two systems play different roles:

ConcernChoiceWhy
TransportNATS (plain pub/sub)Every component already has (or can get) a NATS connection — including the confined, ephemeral agent pods, which have no MongoDB credentials and shouldn't. Decouples emitters from storage.
Storage / queryMongoDB capped collectionA capped collection is fixed-size, insertion-ordered, and self-trimming — ideal for logs. It's queryable (component / level / text / time) to back the UI page.
Node-level baselinestdout (JSON)kubectl logs and any cluster log stack keep working unchanged.

Logs are published on the plain (core) NATS subject logs.<component>, deliberately outside the nexus.> JetStream stream, so high-volume log traffic never bloats the durable event log.

Pipeline

tracing::info!/warn!/error! (any component)
│ CaptureLayer (nexus-observability)

in-process channel ──pump──▶ NATS logs.<component> (also → stdout JSON)

log sink (nexus-worker) subscribes logs.>

MongoDB capped collection `logs`

GET /v1/logs (nexus-core) ◀── Admin UI “Logs” page (polls)
  • Capturenexus_observability::init("<component>") installs a tracing subscriber with a JSON stdout layer plus a capture layer that turns each event (severity ≥ INFO by default) into a LogRecord on an in-process channel.
  • Ship — long-lived services spawn pump_logs(...) to publish records to logs.<component>. The short-lived agent runner instead drains its buffer to NATS right before exit, so agent connectivity / LLM-call logs aren't lost.
  • Sink — the worker runs the single logs.> subscriber and inserts each record into the capped logs collection.
  • ReadGET /v1/logs?component=&level=&search=&since= returns newest-first (capped $natural order). The UI polls every few seconds while Live is on.

Configuration

Env varDefaultPurpose
NEXUS_LOGinfostdout EnvFilter (e.g. nexus_worker=debug,info).
NEXUS_LOG_CAPTUREinfoMinimum severity captured for the page (debug/info/warn/error).
NEXUS_LOGS_CAP_BYTES268435456 (256 MiB)Capped collection size.
NEXUS_LOGS_CAP_DOCS1000000Capped collection max documents.

All components need NEXUS_NATS_URL set to ship logs; the worker additionally writes to MongoDB. If NATS is unreachable a component still logs to stdout — it just won't appear on the page.

Troubleshooting

  • Page is empty — check the worker's log sink subscribed (log sink: subscribe failed on stderr means NATS is down) and that the capped logs collection exists.
  • An agent's logs are missing — agent pods must have NEXUS_NATS_URL and egress to NATS (allowed by the agent NetworkPolicy). Run-level outcomes also appear on the Runs page regardless.
  • No logs anywherenexus_observability::init(...) must run at startup; it installs the only subscriber.