@wingfoil/telemetry
v0.1.0
Published
Pipeline-agnostic latency-telemetry dashboard components (chart, flamegraph, breakdown, status pill) for the wingfoil web stack.
Readme
@wingfoil/telemetry
Pipeline-agnostic latency-telemetry dashboard components for the
wingfoil web stack. Each component takes a host element plus a
declarative spec and exposes a push(rt) / destroy() lifecycle —
nothing about FIX, market data, or stamp-index layout is baked in.
Designed to pair with @wingfoil/client's
LatencyTracker (which emits RoundTrip<T> events), but the components
are generic over T — pass whichever shape your server produces and
provide value-extractor functions in the spec.
Components
| Module | Class | Purpose |
|--------|-------|---------|
| @wingfoil/telemetry/chart | LatencyChart | Per-stage line chart over a log Y-axis (wraps uPlot). |
| @wingfoil/telemetry/flamegraph | FlameGraph | Nested-call-stack canvas with rolling-mean boxes and hover tooltip. |
| @wingfoil/telemetry/breakdown | BreakdownPanel | N rolling-mean tiles (e.g. total / resident / wire). |
| @wingfoil/telemetry/status | StatusPill | Connection-status pill bound to a WingfoilClient. |
| @wingfoil/telemetry/format | fmtNs, fmtAxisNs, fmtUs | Nanosecond formatters. |
All five are re-exported from the package root.
Example
import { WingfoilClient } from "@wingfoil/client";
import { LatencyTracker, RoundTrip } from "@wingfoil/client/tracing";
import {
LatencyChart,
FlameGraph,
BreakdownPanel,
StatusPill,
} from "@wingfoil/telemetry";
const client = new WingfoilClient({ url: "wss://your-host/ws", codec: "json" });
const tracker = new LatencyTracker({ client, outbound: "in", inbound: "out", echo: "echo" });
new StatusPill({ host: document.getElementById("status")!, client });
const chart = new LatencyChart<RoundTrip>({
host: document.getElementById("chart")!,
stages: [
{ name: "stage 0 → 1", color: "#58a6ff", value: (rt) => rt.stamps[1] - rt.stamps[0] },
{ name: "wire RTT", color: "#e3b341", value: (rt) => rt.wireRttNs },
],
});
const flame = new FlameGraph<RoundTrip>({
host: document.getElementById("flamegraph") as HTMLCanvasElement,
layers: [
{ name: "browser", color: "#58a6ff", detail: "full RTT", value: (rt) => rt.rttNs },
{ name: "server", color: "#3fb950", detail: "stamps[0..last]", value: (rt) => rt.serverResidentNs },
],
});
const breakdown = new BreakdownPanel<RoundTrip>({
buckets: [
{ el: document.getElementById("total")!, value: (rt) => rt.rttNs },
{ el: document.getElementById("resident")!, value: (rt) => rt.serverResidentNs },
{ el: document.getElementById("wire")!, value: (rt) => rt.wireRttNs },
],
});
tracker.onResponse((rt) => {
chart.push(rt);
flame.push(rt);
breakdown.push(rt);
});Reference deployment: the latency_e2e example in the
wingfoil repo.
Peer dependencies
uplot ^1.6— required for thechartmodule. The other modules have no peer deps.
Build
npm install
npm run build # tsc → dist/
npm test # vitest, happy-dom environment