@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.

TopicPurposeReplay
metricsTime-series data points: value, timestamp, unit, tags1 hour
widgetsWidget state snapshots: type, data payload, last updated1 hour

Installation

npm install @nolag/dash @nolag/js-sdk

Quick 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.

MethodDescription
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

EventPayloadDescription
connectednoneWebSocket connection established
disconnectedreason: stringConnection closed
reconnectednoneReconnection successful; panels are restored automatically
errorerror: ErrorUnrecoverable error occurred
viewerOnlineviewer: DashViewerA viewer joined any panel
viewerOfflineviewer: DashViewerA viewer left any panel

DashboardPanel

Returned by joinPanel(). Handles metric ingestion, aggregation, widget state, and per-panel viewer presence.

MethodDescription
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

EventPayloadDescription
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
viewerJoinedviewer: DashViewerA viewer joined this panel
viewerLeftviewer: DashViewerA viewer left this panel
replayStart{ count: number }Historical data replay is beginning
replayEnd{ replayed: number }Historical data replay is complete