Live Monitoring

Real-time in-memory ring buffers

Where monitoring persists metrics for history and alerting, liveMonitoring is the lightweight, zero-database counterpart: rolling in-memory ring buffers of the most recent activity, streamed to a dashboard over SSE. It's built for the live view — what is my service doing right now.

It tracks four feeds — memory, CPU, Dapr events and WebSocket activity — plus request logs, each capped at a configurable size so memory stays bounded. Because nothing touches the database, it's cheap enough to leave on in production.

Feed toggles#

Enable the subsystem and pick which feeds to capture. Each feed is independent, so you can watch just memory and CPU, or add the Dapr and WebSocket streams when debugging realtime issues.

config.nucleus.json — liveMonitoring
1{2  "liveMonitoring": {3    "enabled": true,4    "logMemory": true,5    "logCpu": true,6    "logDapr": false,7    "logWebSocket": true,8    "memoryLogInterval": 2000,9    "cpuLogInterval": 2000,10    "memoryLogLimit": 120,11    "cpuLogLimit": 120,12    "wsLogLimit": 200,13    "requestLogLimit": 200,14    "streamInterval": 1000,15    "basePath": "/live-monitoring"16  }17}
enabledbooleanOptional

Master switch for live monitoring.

Defaultfalse
logMemorybooleanOptional

Capture a rolling memory-usage feed.

logCpubooleanOptional

Capture a rolling CPU-usage feed.

logDaprbooleanOptional

Capture Dapr sidecar events (pub/sub, bindings, invocations).

logWebSocketbooleanOptional

Capture WebSocket connection and message activity.

Sampling intervals#

How often samples are taken and how often the buffers are pushed to connected clients. Values are in milliseconds.

memoryLogIntervalnumberOptional

Milliseconds between memory samples.

cpuLogIntervalnumberOptional

Milliseconds between CPU samples.

streamIntervalnumberOptional

Milliseconds between SSE pushes to connected dashboards — the cadence at which new buffer data is flushed to the client.

Buffer limits#

Each feed is a fixed-size ring buffer. Once full, the oldest entry is dropped as a new one arrives, so memory usage is bounded no matter how long the service runs.

memoryLogLimitnumberOptional

Max retained memory samples.

cpuLogLimitnumberOptional

Max retained CPU samples.

daprLogLimitnumberOptional

Max retained Dapr events.

wsLogLimitnumberOptional

Max retained WebSocket events.

requestLogLimitnumberOptional

Max retained request log entries.

Endpoint#

The live feed is served from a single base path with an SSE stream.

basePathstringOptional

Route prefix for the live-monitoring endpoints, including the SSE stream the dashboard subscribes to.

Under the hood — LiveMonitoringService#

Everything here lives in process memory — no Redis, no database. The service keeps small ring buffers and streams deltas, which is what makes it cheap enough to leave on.

ring buffersin-memory, trimmedOptional

memory, cpu, requests, dapr and ws each have their own array, trimmed back to its configured limit once it grows past 2× — so memory use is bounded and the newest samples win. Nothing survives a restart, by design.

collectorsprocess.memoryUsage / os.cpusOptional

A memory timer samples rss/heapUsed/heapTotal every memoryLogInterval; a CPU timer computes utilisation from os.cpus() deltas every cpuLogInterval. recordRequest / recordDaprEvent / recordWsEvent push the other feeds (gated by the logDapr / logWebSocket toggles).

delta streaminggetSnapshot + getUpdatesSinceOptional

The SSE endpoint sends one full getSnapshot, then on streamInterval calls getUpdatesSince(timestamps) and pushes only the new samples per feed — so the dashboard stays live without resending the whole buffer each tick.

live-tunablechangeSettingsOptional

The settings endpoint flips feeds on/off, changes intervals (restarting the affected collector) and resizes buffers at runtime — no redeploy, which is the point of a debugging feed.

Related sections