Streaming Architecture¶
Sidekick Docker uses AsyncIterable (async generators) throughout for streaming data from the Docker daemon.
Pattern¶
All streaming methods in DockerClient return AsyncIterable:
streamLogs(id: string, opts?: LogStreamOptions): AsyncIterable<LogEntry>
streamStats(id: string): AsyncIterable<ContainerStats>
streamEvents(filters?: Record<string, string[]>): AsyncIterable<DockerEvent>
Consumers iterate with for await:
Stream Managers¶
The dashboard uses manager classes to control when streaming starts and stops. Streaming is selection-driven — it only runs for the currently selected container, avoiding unnecessary resource usage.
LogStreamManager¶
- Starts streaming when a container is selected on the Logs tab
- Maintains a ring buffer of the most recent 1000 log entries
- Feeds each log entry into three analytics processors:
- LogAnalytics — running severity counts (ERROR, WARN, INFO, DEBUG, OTHER)
- LogSeverityTimeSeries — 60-bucket ring buffer tracking severity distribution over time (1-minute buckets)
- LogTemplateEngine — Drain-like pattern clustering that groups similar lines into templates with
<*>wildcards
- Stops streaming when the user navigates away
- Resets all analytics when the selected container changes
StatsStreamManager¶
- Starts streaming when a container is selected on the Stats tab
- Pushes samples to
StatsCollectorfor time-series storage - Stops streaming when the user navigates away
EventWatcher¶
- Runs continuously while the dashboard is open
- Auto-reconnects on connection loss with exponential backoff
- Fires typed callbacks:
onEvent,onError,onReconnect - Feeds events into
DockerState.processEvent()for incremental updates
StatsCollector¶
A per-container ring buffer (default 60 samples) that stores stats history:
push(id, stats)— add a new samplegetCpuSeries(id)— returns array of CPU percentages for sparkline renderinggetMemorySeries(id)— returns array of memory usage valuesgetLatest(id)— returns the most recent stats sample
The 60-sample buffer at ~1 sample/second gives roughly 1 minute of history for the sparkline charts.