@nolag/dash
Live dashboards with real-time metrics, time-series aggregation, and widgets.
Overview
@nolag/dash powers live operational dashboards with streaming metrics and interactive widgets. Agents or servers publish metric data points and widget state snapshots to panels; viewers connected to the same panel receive updates instantly and can query rolling aggregations (average, min, max, sum, count) over any time window without hitting a separate time-series database.
Key Features
- Streaming metric ingestion with per-stream data point buffering
- Client-side rolling aggregation over configurable time windows
- Widget state publishing for KPI cards, gauges, tables, and custom types
- 1-hour replay for both metrics and widgets so new viewers see recent history immediately
- Tag-based metadata on metrics for multi-dimensional filtering
- Automatic reconnection with panel restoration
How It Works
NoLagDash wraps the @nolag/js-sdk client. Calling joinPanel() creates a DashboardPanel that subscribes to two topics: metrics for time-series data points and widgets for widget state snapshots. A MetricBuffer inside the panel accumulates data points per stream ID and provides efficient rolling-window aggregation, while a WidgetStore keeps the latest state for each widget keyed by widget ID.
| Topic | Purpose | Replay |
|---|---|---|
metrics | Time-series data points: value, timestamp, unit, tags | 1 hour |
widgets | Widget state snapshots: type, data payload, last updated | 1 hour |
Installation
npm install @nolag/dash @nolag/js-sdkQuick Start
import { NoLagDash } from '@nolag/dash'
// Create and connect the client
const dash = new NoLagDash('your-access-token')
await dash.connect()
// Join a dashboard panel
const panel = await dash.joinPanel('ops-overview')
// Publish a metric (typically called from a server or agent)
await panel.publishMetric('cpu.usage', 74.2, {
unit: 'percent',
tags: { host: 'web-01', region: 'us-east-1' },
})
// Listen for incoming metrics
panel.on('metric', ({ streamId, value, timestamp, tags }) => {
console.log(`[${streamId}] ${value} @ ${new Date(timestamp).toISOString()}`)
})
// Get all buffered data points for a metric stream
const points = panel.getMetrics('cpu.usage')
console.log('Data points:', points.length)
// Get a rolling aggregation over the last 5 minutes
const agg = panel.getAggregation('cpu.usage', 5 * 60_000)
console.log('Avg CPU:', agg.avg.toFixed(1) + '%')
console.log('Max CPU:', agg.max.toFixed(1) + '%')
// Publish a widget state (e.g. a status card)
await panel.publishWidget('status-card', 'kpi', {
label: 'Active Sessions',
value: 1_248,
trend: 'up',
})
// Listen for widget updates
panel.on('widgetUpdate', ({ widgetId, type, data }) => {
console.log(`Widget ${widgetId} (${type}):`, data)
})
// Read current widget state
const widget = panel.getWidget('status-card')
await dash.leavePanel('ops-overview')
dash.disconnect()API Reference
NoLagDash
The main class. Manages the WebSocket connection and dashboard panel lifecycle.
| Method | Description |
|---|---|
connect() | Establish WebSocket connection |
disconnect() | Gracefully close the connection and leave all panels |
joinPanel(name) | Join a dashboard panel; returns a DashboardPanel instance |
leavePanel(name) | Leave a panel and unsubscribe from its topics |
Events: NoLagDash
| Event | Payload | Description |
|---|---|---|
connected | none | WebSocket connection established |
disconnected | reason: string | Connection closed |
reconnected | none | Reconnection successful; panels are restored automatically |
error | error: Error | Unrecoverable error occurred |
viewerOnline | viewer: DashViewer | A viewer joined any panel |
viewerOffline | viewer: DashViewer | A viewer left any panel |
DashboardPanel
Returned by joinPanel(). Handles metric ingestion, aggregation, widget state, and per-panel viewer presence.
| Method | Description |
|---|---|
publishMetric(streamId, value, opts) | Publish a single data point to a metric stream; opts accepts unit, tags, and timestamp |
publishWidget(widgetId, type, data) | Publish a widget state snapshot; replaces the previous state for that widget ID |
getMetrics(streamId) | Return all buffered data points for the given metric stream, ordered by timestamp |
getAggregation(streamId, windowMs) | Return { avg, min, max, sum, count } for all data points within the last windowMs milliseconds |
getWidget(widgetId) | Return the latest state snapshot for a single widget |
getWidgets() | Return the latest state snapshots for all widgets in this panel |
Events: DashboardPanel
| Event | Payload | Description |
|---|---|---|
metric | { streamId: string, value: number, timestamp: number, unit?: string, tags?: Record<string, string> } | A new data point arrived for a metric stream |
widgetUpdate | { widgetId: string, type: string, data: unknown } | A widget state snapshot was updated |
viewerJoined | viewer: DashViewer | A viewer joined this panel |
viewerLeft | viewer: DashViewer | A viewer left this panel |
replayStart | { count: number } | Historical data replay is beginning |
replayEnd | { replayed: number } | Historical data replay is complete |