DocsPlatformReal-time Logs

Real-time Logs

The Core captures output from backend processes and broadcasts it via Server-Sent Events (SSE). Logs are ephemeral (in-memory broadcast channel, not persisted to disk).


How it works

Each worker process gets a broadcast channel (capacity: 256 entries). Log entries are pushed to the channel from three sources:

  1. Worker IPC messages: console.log(), console.warn(), console.error() in your backend code are intercepted by the prelude and sent as structured IPC messages with a level.
  2. Raw stderr: anything written directly to stderr is captured line-by-line with level "stderr".
  3. Core lifecycle events: worker start, stop, crash, and backoff events with level "system".

Subscribers receive entries via SSE as they are produced.


Log levels

Level Source
info console.log() or log.info() in your backend
warn console.warn() or log.warn() in your backend
error console.error() or log.error() in your backend
stderr Raw stderr output from the process (not via IPC)
system Core lifecycle events (worker started, stopped, crashed, backoff)
event Custom events emitted via emit(name, data)

Logging from your backend

The prelude intercepts standard console methods and routes them through IPC:

// These all go through IPC as structured log messages:
console.log("Processing:", method);     // level: "info"
console.warn("Rate limit approaching"); // level: "warn"
console.error("Connection failed");     // level: "error"

// Or use the explicit log object:
log.info("Processing started");
log.warn("Approaching limit");
log.error("Connection failed");

console.debug is aliased to console.log (level: "info").

Log messages are truncated at 8192 characters.


SSE endpoint

GET /api/v1/apps/{appId}/logs
Authorization: Bearer <token>

Requires authentication. Returns text/event-stream.

Each event contains a JSON payload:

data: {"level":"info","message":"Processing order #123"}

data: {"level":"stderr","message":"Warning: deprecated API usage"}

data: {"level":"system","message":"worker started"}

Keep-alive

The SSE stream sends a keep-alive comment every 15 seconds to prevent client timeout.

Lagged subscribers

If a subscriber falls behind (more than 256 entries in the buffer), it receives a system message indicating how many entries were dropped:

data: {"level":"system","message":"... 42 messages dropped ..."}

The stream continues from the current position after the lag notification.

Stream termination

The stream ends when:

  • The worker is stopped or uninstalled (channel closed).
  • The client disconnects.

Custom events

Your backend can emit named events:

emit("order_processed", { orderId: "abc123", total: 4999 });

These appear in the log stream with level "event" and the format "{name}: {data}".


Technical details

Property Value
Transport Server-Sent Events (SSE)
Persistence None (in-memory broadcast only)
Channel capacity 256 entries per worker
Keep-alive interval 15 seconds
Message truncation 8192 characters (IPC log messages)
Lag handling Notifies subscriber of dropped count, continues streaming
Entry format {"level": "...", "message": "..."}

API endpoints summary

Method Path Auth Description
GET /api/v1/apps/{appId}/logs Yes Subscribe to live log stream (SSE)