A real-time service-telemetry dashboard: a .NET 10 backend streams simulated live-ops metrics over SignalR (WebSockets) to a React 19 + TypeScript front end that renders filtered, aggregated time-series charts.
Built to demonstrate an end-to-end .NET + SignalR + React + charts stack.
- Live streaming — SignalR pushes a batch of metrics every second; the chart and KPI tiles update in place with no polling.
- History backfill — new clients receive a rolling snapshot on connect, so charts are populated immediately.
- Filtering — slice by service (
checkout,search,payments,inventory) and region (us-east,eu-west,ap-south); metrics re-roll up on the fly (throughput sums, error rate is request-weighted, p95 takes the worst series, CPU averages). - Persisted views — name and save a filter+metric combination to
localStorageand reapply it later. - Connection state — visible live / reconnecting / offline badge with automatic reconnection.
backend/ .NET 10 minimal API
MetricsEngine random-walk simulation + per-series history buffer
MetricsBroadcastService PeriodicTimer -> IHubContext, 1 Hz fan-out
MetricsHub server-push hub (snapshot on connect, metrics/tick)
Program.cs DI, CORS, REST endpoints, hub mapping
frontend/ Vite + React 19 + TypeScript
hooks/useMetricsStream SignalR connection + rolling sample buffer
hooks/useSavedViews localStorage-backed presets
lib/aggregate filter + timeline roll-up
components/ KpiRow, MetricChart (Recharts), FilterBar, SavedViews
REST:
GET /api/healthGET /api/metrics/meta→{ services, regions }GET /api/metrics/history→MetricSample[]
SignalR hub /hubs/metrics:
snapshot→MetricSample[](sent once on connect)metrics→MetricSample[](one batch per second)
MetricSample = {
timestamp: string; service: string; region: string;
requestsPerSec: number; errorRate: number; // 0..1
p95LatencyMs: number; cpuPercent: number; // 0..100
}Backend (listens on http://localhost:5099):
cd backend
dotnet runFront end (Vite dev server on http://localhost:5173):
cd frontend
npm install
npm run devThen open http://localhost:5173. Override the backend URL with
VITE_API_BASE if needed.