You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packages/utils/src/logger.ts (createLogger) is env-driven and picks one implicit sink: if AGENT_RELAY_LOG_FILE is set it writes to the file and returns, otherwise it writes to the console. Fleet-node structured logging (#1237 — capabilities registered, actions invoked/completed/failed) now flows through it, which surfaces the limitations:
No simultaneous sinks. You cannot tee to both a file and stdout — the file path short-circuits console output entirely (logger.ts ~L90-102).
No pluggable adapters. Format (text vs JSON) and destination are hardcoded and chosen by env vars; there's no way to register a custom sink (ship to relaycast, PostHog, syslog, an in-memory ring buffer for tests).
Process-global config. Level/file/format are read from process.env per call, so every component (broker, router, connection, fleet) shares one destination — you can't route fleet to its own file while leaving broker logs on the console.
Blocking writes.appendFileSync per line; no buffering/rotation.
Proposal
Introduce an adapter interface and let a logger fan out to N adapters:
interfaceLogAdapter{write(entry: LogEntry): void;// or Promise<void> for async sinksminLevel?: LogLevel;// per-adapter filtering}createLogger('fleet',{adapters: [stdoutAdapter(),fileAdapter('./node.log',{json: true})]})
Per-component adapter overrides so fleet logs can go somewhere distinct from broker/router logs.
Context
Surfaced while adding fleet-node structured logging (#1237). That change deliberately reused createLogger and injects it into serveNode via a FleetLogger seam, so once adapters land, fleet gains multi-sink/custom-sink output with no changes on the fleet side.
Activity