trace-viz 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +21 -0
- package/README.md +385 -0
- package/dist/adapters/index.d.ts +32 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +83 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/agent.d.ts +66 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +329 -0
- package/dist/agent.js.map +1 -0
- package/dist/atlas/atlas.d.ts +203 -0
- package/dist/atlas/atlas.d.ts.map +1 -0
- package/dist/atlas/atlas.js +1466 -0
- package/dist/atlas/atlas.js.map +1 -0
- package/dist/atlas/index.d.ts +7 -0
- package/dist/atlas/index.d.ts.map +1 -0
- package/dist/atlas/index.js +4 -0
- package/dist/atlas/index.js.map +1 -0
- package/dist/atlas/layout.d.ts +44 -0
- package/dist/atlas/layout.d.ts.map +1 -0
- package/dist/atlas/layout.js +103 -0
- package/dist/atlas/layout.js.map +1 -0
- package/dist/atlas/model.d.ts +164 -0
- package/dist/atlas/model.d.ts.map +1 -0
- package/dist/atlas/model.js +489 -0
- package/dist/atlas/model.js.map +1 -0
- package/dist/channels.d.ts +105 -0
- package/dist/channels.d.ts.map +1 -0
- package/dist/channels.js +411 -0
- package/dist/channels.js.map +1 -0
- package/dist/components.d.ts +76 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +432 -0
- package/dist/components.js.map +1 -0
- package/dist/estate.d.ts +25 -0
- package/dist/estate.d.ts.map +1 -0
- package/dist/estate.js +285 -0
- package/dist/estate.js.map +1 -0
- package/dist/failure.d.ts +36 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +82 -0
- package/dist/failure.js.map +1 -0
- package/dist/geometry.d.ts +24 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +92 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +66 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +152 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout3d.d.ts +98 -0
- package/dist/layout3d.d.ts.map +1 -0
- package/dist/layout3d.js +350 -0
- package/dist/layout3d.js.map +1 -0
- package/dist/mesh.d.ts +23 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +263 -0
- package/dist/mesh.js.map +1 -0
- package/dist/model.d.ts +94 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +84 -0
- package/dist/model.js.map +1 -0
- package/dist/particles.d.ts +80 -0
- package/dist/particles.d.ts.map +1 -0
- package/dist/particles.js +118 -0
- package/dist/particles.js.map +1 -0
- package/dist/project.d.ts +113 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +288 -0
- package/dist/project.js.map +1 -0
- package/dist/react/index.d.ts +22 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +69 -0
- package/dist/react/index.js.map +1 -0
- package/dist/renderer.d.ts +252 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +1710 -0
- package/dist/renderer.js.map +1 -0
- package/dist/scales.d.ts +99 -0
- package/dist/scales.d.ts.map +1 -0
- package/dist/scales.js +126 -0
- package/dist/scales.js.map +1 -0
- package/dist/scene.d.ts +53 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +44 -0
- package/dist/scene.js.map +1 -0
- package/dist/schema.d.ts +24 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +131 -0
- package/dist/schema.js.map +1 -0
- package/dist/seed.d.ts +33 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +173 -0
- package/dist/seed.js.map +1 -0
- package/dist/theme.d.ts +35 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +83 -0
- package/dist/theme.js.map +1 -0
- package/dist/trace-viz.esm.js +15 -0
- package/dist/trace-viz.min.js +15 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +105 -0
package/dist/project.js
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { endpointDims, } from './model.js';
|
|
2
|
+
/** Channels that describe one edge, so binding a dimension to one must split edges by it. */
|
|
3
|
+
const EDGE_CHANNELS = new Set(['hue', 'glyph', 'dash', 'lane', 'coupling', 'density', 'speed', 'radius']);
|
|
4
|
+
export function nodeIdFor(dims, nodeKey) {
|
|
5
|
+
return nodeKey.map((k) => dims[k] ?? '∅').join(' / ');
|
|
6
|
+
}
|
|
7
|
+
/** Does this endpoint fall inside the focus? */
|
|
8
|
+
function inFocus(dims, focus) {
|
|
9
|
+
if (!focus)
|
|
10
|
+
return false;
|
|
11
|
+
return Object.entries(focus.match).every(([k, v]) => dims[k] === v);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Roll a flow table up into a drawable scene.
|
|
15
|
+
*
|
|
16
|
+
* Two things happen that are easy to miss and matter a lot:
|
|
17
|
+
*
|
|
18
|
+
* 1. Binding a *dimension* to any per-edge channel adds it to `splitBy`, so the
|
|
19
|
+
* edges are grouped by it rather than averaged over it. Colouring by region
|
|
20
|
+
* therefore turns one edge into two lanes, one per region - which is the
|
|
21
|
+
* honest picture. Averaging a dimension you are also encoding would draw a
|
|
22
|
+
* colour that describes nothing.
|
|
23
|
+
* 2. Measures aggregate differently by kind: throughput sums, everything else
|
|
24
|
+
* is a throughput-weighted mean. A 10k rps hop at 2ms and a 1 rps hop at 900ms
|
|
25
|
+
* do not average to 451ms.
|
|
26
|
+
*/
|
|
27
|
+
export function project(table, spec) {
|
|
28
|
+
const nodeKey = spec.nodeKey.length ? spec.nodeKey : ['service'];
|
|
29
|
+
const splitBy = new Set();
|
|
30
|
+
for (const [channel, binding] of Object.entries(spec.channels ?? {})) {
|
|
31
|
+
if (!EDGE_CHANNELS.has(channel))
|
|
32
|
+
continue;
|
|
33
|
+
// Only dimensions split; measures are aggregated numbers.
|
|
34
|
+
if (!isMeasure(binding.field))
|
|
35
|
+
splitBy.add(binding.field);
|
|
36
|
+
}
|
|
37
|
+
for (const k of nodeKey)
|
|
38
|
+
splitBy.delete(k);
|
|
39
|
+
const split = [...splitBy];
|
|
40
|
+
let matched = 0;
|
|
41
|
+
let filtered = 0;
|
|
42
|
+
const nodes = new Map();
|
|
43
|
+
const edges = new Map();
|
|
44
|
+
for (const record of table.records) {
|
|
45
|
+
if (!passes(record, spec.where)) {
|
|
46
|
+
filtered++;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
matched++;
|
|
50
|
+
const fromDims = endpointDims(record, 'from');
|
|
51
|
+
const toDims = endpointDims(record, 'to');
|
|
52
|
+
// Focus expands the key locally, so one service can show its APIs while
|
|
53
|
+
// every other service stays a single box.
|
|
54
|
+
const fromKey = inFocus(fromDims, spec.focus) ? [...nodeKey, ...spec.focus.expandBy] : nodeKey;
|
|
55
|
+
const toKey = inFocus(toDims, spec.focus) ? [...nodeKey, ...spec.focus.expandBy] : nodeKey;
|
|
56
|
+
const fromId = nodeIdFor(fromDims, fromKey);
|
|
57
|
+
const toId = nodeIdFor(toDims, toKey);
|
|
58
|
+
const rps = Math.max(record.metrics.rps, 0);
|
|
59
|
+
touchNode(nodes, fromId, fromDims, fromKey, record, { outbound: rps });
|
|
60
|
+
touchNode(nodes, toId, toDims, toKey, record, { inbound: rps });
|
|
61
|
+
if (spec.dropSelfEdges && fromId === toId)
|
|
62
|
+
continue;
|
|
63
|
+
const laneDims = {};
|
|
64
|
+
for (const d of split) {
|
|
65
|
+
const v = record.dims?.[d] ?? record.from[d] ?? record.to[d];
|
|
66
|
+
if (v !== undefined)
|
|
67
|
+
laneDims[d] = v;
|
|
68
|
+
}
|
|
69
|
+
const edgeId = [fromId, '→', toId, ...split.map((d) => laneDims[d] ?? '∅')].join('|');
|
|
70
|
+
let edge = edges.get(edgeId);
|
|
71
|
+
if (!edge) {
|
|
72
|
+
edges.set(edgeId, (edge = {
|
|
73
|
+
id: edgeId,
|
|
74
|
+
from: fromId,
|
|
75
|
+
to: toId,
|
|
76
|
+
dims: laneDims,
|
|
77
|
+
spans: {},
|
|
78
|
+
rps: 0,
|
|
79
|
+
latencyWeighted: 0,
|
|
80
|
+
errorWeighted: 0,
|
|
81
|
+
bytesWeighted: 0,
|
|
82
|
+
records: 0,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
edge.rps += rps;
|
|
86
|
+
edge.latencyWeighted += (record.metrics.latencyMs ?? 25) * rps;
|
|
87
|
+
edge.errorWeighted += (record.metrics.errorRate ?? 0) * rps;
|
|
88
|
+
edge.bytesWeighted += (record.metrics.bytes ?? 1024) * rps;
|
|
89
|
+
edge.records++;
|
|
90
|
+
collectSpans(edge.spans, { ...record.dims, ...record.from }, split, nodeKey);
|
|
91
|
+
collectSpans(edge.spans, { ...record.dims, ...record.to }, split, nodeKey);
|
|
92
|
+
}
|
|
93
|
+
const sceneNodes = [...nodes.values()].map((n) => ({
|
|
94
|
+
id: n.id,
|
|
95
|
+
label: n.label,
|
|
96
|
+
...(n.sublabel ? { sublabel: n.sublabel } : {}),
|
|
97
|
+
kind: n.kind,
|
|
98
|
+
key: n.key,
|
|
99
|
+
spans: sortSpans(n.spans),
|
|
100
|
+
inboundRps: n.inbound,
|
|
101
|
+
outboundRps: n.outbound,
|
|
102
|
+
attrs: {},
|
|
103
|
+
records: n.records,
|
|
104
|
+
}));
|
|
105
|
+
attachFacts(sceneNodes, table.nodes ?? []);
|
|
106
|
+
// Error rate is measured on flows, but "how badly is this thing failing" is
|
|
107
|
+
// a question about a node: the rps-weighted error rate of what it serves.
|
|
108
|
+
// Exposed as a node attribute so halo (or anything else) can bind to it.
|
|
109
|
+
const errWeighted = new Map();
|
|
110
|
+
for (const e of edges.values()) {
|
|
111
|
+
const acc = errWeighted.get(e.to) ?? { err: 0, rps: 0 };
|
|
112
|
+
acc.err += e.errorWeighted;
|
|
113
|
+
acc.rps += e.rps;
|
|
114
|
+
errWeighted.set(e.to, acc);
|
|
115
|
+
}
|
|
116
|
+
for (const n of sceneNodes) {
|
|
117
|
+
const acc = errWeighted.get(n.id);
|
|
118
|
+
n.attrs.errorRate = acc && acc.rps > 0 ? round(acc.err / acc.rps, 5) : 0;
|
|
119
|
+
}
|
|
120
|
+
// Infer a role for anything the data did not label, so the palette still
|
|
121
|
+
// distinguishes a client from a datastore after an arbitrary projection.
|
|
122
|
+
for (const n of sceneNodes) {
|
|
123
|
+
if (n.kind !== 'service')
|
|
124
|
+
continue;
|
|
125
|
+
if (n.inboundRps === 0 && n.outboundRps > 0)
|
|
126
|
+
n.kind = 'client';
|
|
127
|
+
else if (n.outboundRps === 0 && n.inboundRps > 0)
|
|
128
|
+
n.kind = 'datastore';
|
|
129
|
+
}
|
|
130
|
+
const outboundOf = new Map();
|
|
131
|
+
for (const e of edges.values())
|
|
132
|
+
outboundOf.set(e.from, (outboundOf.get(e.from) ?? 0) + e.rps);
|
|
133
|
+
const sceneEdges = [...edges.values()].map((e) => ({
|
|
134
|
+
id: e.id,
|
|
135
|
+
from: e.from,
|
|
136
|
+
to: e.to,
|
|
137
|
+
kind: edgeKindOf(e.dims),
|
|
138
|
+
dims: e.dims,
|
|
139
|
+
spans: sortSpans(e.spans),
|
|
140
|
+
metrics: {
|
|
141
|
+
rps: round(e.rps, 2),
|
|
142
|
+
latencyMs: e.rps > 0 ? round(e.latencyWeighted / e.rps, 2) : 0,
|
|
143
|
+
errorRate: e.rps > 0 ? round(e.errorWeighted / e.rps, 5) : 0,
|
|
144
|
+
bytes: e.rps > 0 ? Math.round(e.bytesWeighted / e.rps) : 0,
|
|
145
|
+
share: (outboundOf.get(e.from) ?? 0) > 0 ? round(e.rps / outboundOf.get(e.from), 4) : 0,
|
|
146
|
+
},
|
|
147
|
+
records: e.records,
|
|
148
|
+
...(labelFor(e.dims, split) ? { label: labelFor(e.dims, split) } : {}),
|
|
149
|
+
}));
|
|
150
|
+
return {
|
|
151
|
+
scene: {
|
|
152
|
+
nodes: sceneNodes,
|
|
153
|
+
edges: sceneEdges,
|
|
154
|
+
meta: { ...table.meta, ...(spec.title ? { title: spec.title } : {}) },
|
|
155
|
+
nodeKey,
|
|
156
|
+
},
|
|
157
|
+
splitBy: split,
|
|
158
|
+
matched,
|
|
159
|
+
filtered,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Attach per-thing facts to whichever nodes they belong to.
|
|
164
|
+
*
|
|
165
|
+
* A fact keyed `{ service: 'orders' }` attaches to the single `orders` node at
|
|
166
|
+
* service resolution, and to every `orders / <api>` node when the projection is
|
|
167
|
+
* finer. Counts sum, everything else is an instance-weighted mean - averaging
|
|
168
|
+
* CPU across twelve pods and one pod without weighting is how dashboards lie.
|
|
169
|
+
*/
|
|
170
|
+
function attachFacts(nodes, facts) {
|
|
171
|
+
var _a;
|
|
172
|
+
if (!facts.length)
|
|
173
|
+
return;
|
|
174
|
+
const weights = new Map();
|
|
175
|
+
const valueOf = (node, k) => node.key[k] ?? (node.spans[k]?.length === 1 ? node.spans[k][0] : undefined);
|
|
176
|
+
for (const fact of facts) {
|
|
177
|
+
const identity = Object.entries(fact.key);
|
|
178
|
+
if (!identity.length)
|
|
179
|
+
continue;
|
|
180
|
+
for (const node of nodes) {
|
|
181
|
+
// The key must match exactly - that is what makes this fact about this
|
|
182
|
+
// thing. The fact's own dimensions only *narrow*: if the node knows a
|
|
183
|
+
// conflicting value, the fact belongs to a different deployment; if the
|
|
184
|
+
// node has never heard of the dimension, the fact is new information.
|
|
185
|
+
if (!identity.every(([k, v]) => valueOf(node, k) === v))
|
|
186
|
+
continue;
|
|
187
|
+
const conflicts = Object.entries(fact.dims ?? {}).some(([k, v]) => {
|
|
188
|
+
const own = valueOf(node, k);
|
|
189
|
+
return own !== undefined && own !== v;
|
|
190
|
+
});
|
|
191
|
+
if (conflicts)
|
|
192
|
+
continue;
|
|
193
|
+
const w = fact.attrs?.instances ?? 1;
|
|
194
|
+
for (const [k, v] of Object.entries(fact.attrs ?? {})) {
|
|
195
|
+
if (COUNT_ATTRS.has(k))
|
|
196
|
+
node.attrs[k] = (node.attrs[k] ?? 0) + v;
|
|
197
|
+
else
|
|
198
|
+
node.attrs[k] = (node.attrs[k] ?? 0) + v * w;
|
|
199
|
+
}
|
|
200
|
+
weights.set(node.id, (weights.get(node.id) ?? 0) + w);
|
|
201
|
+
if (fact.component)
|
|
202
|
+
node.component = fact.component;
|
|
203
|
+
for (const [k, v] of Object.entries(fact.dims ?? {})) {
|
|
204
|
+
((_a = node.spans)[k] ?? (_a[k] = [])).includes(v) || node.spans[k].push(v);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const node of nodes) {
|
|
209
|
+
const w = weights.get(node.id);
|
|
210
|
+
if (!w)
|
|
211
|
+
continue;
|
|
212
|
+
for (const k of Object.keys(node.attrs)) {
|
|
213
|
+
if (!COUNT_ATTRS.has(k))
|
|
214
|
+
node.attrs[k] = round(node.attrs[k] / w, 3);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Attributes that sum rather than average when several things roll into one node. */
|
|
219
|
+
const COUNT_ATTRS = new Set(['instances', 'replicas', 'pods', 'shards', 'connections']);
|
|
220
|
+
const MEASURES = new Set(['rps', 'latencyMs', 'errorRate', 'bytes', 'share']);
|
|
221
|
+
export function isMeasure(field) {
|
|
222
|
+
return MEASURES.has(field);
|
|
223
|
+
}
|
|
224
|
+
function passes(record, where) {
|
|
225
|
+
if (!where)
|
|
226
|
+
return true;
|
|
227
|
+
for (const [field, allowed] of Object.entries(where)) {
|
|
228
|
+
if (!allowed.length)
|
|
229
|
+
continue;
|
|
230
|
+
const value = record.dims?.[field] ?? record.from[field] ?? record.to[field];
|
|
231
|
+
if (value === undefined || !allowed.includes(value))
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
function touchNode(nodes, id, dims, nodeKey, record, delta) {
|
|
237
|
+
let n = nodes.get(id);
|
|
238
|
+
if (!n) {
|
|
239
|
+
const parts = nodeKey.map((k) => dims[k] ?? '∅');
|
|
240
|
+
nodes.set(id, (n = {
|
|
241
|
+
id,
|
|
242
|
+
// Label with the most specific part of the key; the coarser parts go on
|
|
243
|
+
// the second line, where they read as context rather than noise.
|
|
244
|
+
label: parts[parts.length - 1] ?? id,
|
|
245
|
+
...(parts.length > 1 ? { sublabel: parts.slice(0, -1).join(' · ') } : {}),
|
|
246
|
+
kind: dims.kind ?? 'service',
|
|
247
|
+
key: Object.fromEntries(nodeKey.map((k, i) => [k, parts[i]])),
|
|
248
|
+
spans: {},
|
|
249
|
+
inbound: 0,
|
|
250
|
+
outbound: 0,
|
|
251
|
+
records: 0,
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
n.inbound += delta.inbound ?? 0;
|
|
255
|
+
n.outbound += delta.outbound ?? 0;
|
|
256
|
+
n.records++;
|
|
257
|
+
collectSpans(n.spans, dims, [], nodeKey);
|
|
258
|
+
void record;
|
|
259
|
+
}
|
|
260
|
+
function collectSpans(into, dims, exclude, nodeKey) {
|
|
261
|
+
for (const [k, v] of Object.entries(dims)) {
|
|
262
|
+
if (exclude.includes(k) || nodeKey.includes(k))
|
|
263
|
+
continue;
|
|
264
|
+
(into[k] ?? (into[k] = new Set())).add(v);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function sortSpans(spans) {
|
|
268
|
+
const out = {};
|
|
269
|
+
for (const [k, v] of Object.entries(spans))
|
|
270
|
+
out[k] = [...v].sort();
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
function labelFor(dims, split) {
|
|
274
|
+
const parts = split.map((d) => dims[d]).filter(Boolean);
|
|
275
|
+
return parts.length ? parts.join(' · ') : undefined;
|
|
276
|
+
}
|
|
277
|
+
/** Map known failure/traffic dimensions onto the renderer's edge kinds. */
|
|
278
|
+
function edgeKindOf(dims) {
|
|
279
|
+
const k = dims.kind ?? dims.edgeKind;
|
|
280
|
+
if (k === 'retry' || k === 'challenge' || k === 'response' || k === 'async' || k === 'request')
|
|
281
|
+
return k;
|
|
282
|
+
return 'request';
|
|
283
|
+
}
|
|
284
|
+
function round(v, digits) {
|
|
285
|
+
const f = 10 ** digits;
|
|
286
|
+
return Math.round(v * f) / f;
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CSSProperties, ReactElement } from 'react';
|
|
2
|
+
import { TraceLight, type HoverTarget, type TraceLightOptions } from '../renderer.js';
|
|
3
|
+
import type { GraphSource } from '../adapters/index.js';
|
|
4
|
+
import type { Graph } from '../types.js';
|
|
5
|
+
export interface TraceLightViewProps extends TraceLightOptions {
|
|
6
|
+
/** A graph you already have. Ignored when `source` is given. */
|
|
7
|
+
graph?: Graph;
|
|
8
|
+
/** A source to load from, and subscribe to if it supports pushing. */
|
|
9
|
+
source?: GraphSource;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
onError?: (err: Error) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thin React wrapper over {@link TraceLight}. The renderer owns the canvas and
|
|
16
|
+
* the animation loop; React only owns the container, so re-renders never
|
|
17
|
+
* restart the particle streams.
|
|
18
|
+
*/
|
|
19
|
+
export declare function TraceLightView({ graph, source, className, style, onError, ...options }: TraceLightViewProps): ReactElement;
|
|
20
|
+
export type { HoverTarget, TraceLightOptions };
|
|
21
|
+
export { TraceLight };
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,gEAAgE;IAChE,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,sEAAsE;IACtE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,OAAO,EACX,EAAE,mBAAmB,GAAG,YAAY,CAoEpC;AAED,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { TraceLight } from '../renderer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Thin React wrapper over {@link TraceLight}. The renderer owns the canvas and
|
|
6
|
+
* the animation loop; React only owns the container, so re-renders never
|
|
7
|
+
* restart the particle streams.
|
|
8
|
+
*/
|
|
9
|
+
export function TraceLightView({ graph, source, className, style, onError, ...options }) {
|
|
10
|
+
const ref = useRef(null);
|
|
11
|
+
const instance = useRef(null);
|
|
12
|
+
const [current, setCurrent] = useState(graph);
|
|
13
|
+
// Create once.
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!ref.current)
|
|
16
|
+
return;
|
|
17
|
+
const tl = new TraceLight(ref.current, options);
|
|
18
|
+
instance.current = tl;
|
|
19
|
+
return () => {
|
|
20
|
+
tl.destroy();
|
|
21
|
+
instance.current = null;
|
|
22
|
+
};
|
|
23
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
|
+
}, []);
|
|
25
|
+
// Push option changes through without recreating.
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
instance.current?.setOptions(options);
|
|
28
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
+
}, [
|
|
30
|
+
options.theme,
|
|
31
|
+
options.speed,
|
|
32
|
+
options.animate,
|
|
33
|
+
options.showEdgeLabels,
|
|
34
|
+
options.showLegend,
|
|
35
|
+
]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (graph)
|
|
38
|
+
setCurrent(graph);
|
|
39
|
+
}, [graph]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!source)
|
|
42
|
+
return;
|
|
43
|
+
let cancelled = false;
|
|
44
|
+
source
|
|
45
|
+
.load()
|
|
46
|
+
.then((g) => !cancelled && setCurrent(g))
|
|
47
|
+
.catch((err) => onError?.(err));
|
|
48
|
+
const unsubscribe = source.subscribe?.((g) => !cancelled && setCurrent(g), (err) => onError?.(err));
|
|
49
|
+
return () => {
|
|
50
|
+
cancelled = true;
|
|
51
|
+
unsubscribe?.();
|
|
52
|
+
};
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
+
}, [source]);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!current || !instance.current)
|
|
57
|
+
return;
|
|
58
|
+
try {
|
|
59
|
+
instance.current.setGraph(current);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
onError?.(err);
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
|
+
}, [current]);
|
|
66
|
+
return (_jsx("div", { ref: ref, className: className, style: { width: '100%', height: '100%', minHeight: 320, ...style } }));
|
|
67
|
+
}
|
|
68
|
+
export { TraceLight };
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { couplingFor, type LegendGroup } from './channels.js';
|
|
2
|
+
import { type NodeHealth } from './failure.js';
|
|
3
|
+
import { type LayoutOptions } from './layout.js';
|
|
4
|
+
import { type FlowTable, type TableSchema } from './model.js';
|
|
5
|
+
import { type ViewSpec } from './project.js';
|
|
6
|
+
import { type Scene, type SceneEdge, type SceneNode } from './scene.js';
|
|
7
|
+
import { type EncodingOptions } from './scales.js';
|
|
8
|
+
import { type Theme } from './theme.js';
|
|
9
|
+
import type { Graph } from './types.js';
|
|
10
|
+
export interface HoverTarget {
|
|
11
|
+
kind: 'node' | 'edge';
|
|
12
|
+
node?: SceneNode;
|
|
13
|
+
edge?: SceneEdge;
|
|
14
|
+
}
|
|
15
|
+
export interface TraceLightOptions {
|
|
16
|
+
theme?: 'auto' | 'light' | 'dark' | Theme;
|
|
17
|
+
encoding?: Partial<EncodingOptions>;
|
|
18
|
+
layout?: Partial<LayoutOptions>;
|
|
19
|
+
showEdgeLabels?: boolean;
|
|
20
|
+
showLegend?: boolean;
|
|
21
|
+
speed?: number;
|
|
22
|
+
animate?: boolean;
|
|
23
|
+
seed?: number;
|
|
24
|
+
/** In world mode, let the camera drift slowly round the mesh when nobody is touching it. */
|
|
25
|
+
orbit?: boolean;
|
|
26
|
+
/** Milliseconds for a re-projection morph. 0 snaps. */
|
|
27
|
+
morphMs?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Space to keep clear at each edge, in pixels - for a page that floats its
|
|
30
|
+
* own legend, readout or inspector over the canvas. The layout fits inside
|
|
31
|
+
* the remaining box, so nothing lands under a panel.
|
|
32
|
+
*/
|
|
33
|
+
insets?: {
|
|
34
|
+
top?: number;
|
|
35
|
+
right?: number;
|
|
36
|
+
bottom?: number;
|
|
37
|
+
left?: number;
|
|
38
|
+
};
|
|
39
|
+
onHover?: (target: HoverTarget | null) => void;
|
|
40
|
+
onSelect?: (target: HoverTarget | null) => void;
|
|
41
|
+
/** Fires after every re-projection, with what the picture now encodes. */
|
|
42
|
+
onView?: (info: ViewInfo) => void;
|
|
43
|
+
}
|
|
44
|
+
export interface ViewInfo {
|
|
45
|
+
scene: Scene;
|
|
46
|
+
spec: ViewSpec;
|
|
47
|
+
legend: LegendGroup[];
|
|
48
|
+
splitBy: string[];
|
|
49
|
+
issues: string[];
|
|
50
|
+
stats: Stats;
|
|
51
|
+
}
|
|
52
|
+
export interface Stats {
|
|
53
|
+
totalRps: number;
|
|
54
|
+
wastedRps: number;
|
|
55
|
+
wastedFraction: number;
|
|
56
|
+
nodes: number;
|
|
57
|
+
edges: number;
|
|
58
|
+
records: number;
|
|
59
|
+
filtered: number;
|
|
60
|
+
deadRps: number;
|
|
61
|
+
degradedRps: number;
|
|
62
|
+
deadNodes: number;
|
|
63
|
+
degradedNodes: number;
|
|
64
|
+
}
|
|
65
|
+
export declare class TraceLight {
|
|
66
|
+
private container;
|
|
67
|
+
private canvas;
|
|
68
|
+
private ctx;
|
|
69
|
+
private tooltip;
|
|
70
|
+
private opts;
|
|
71
|
+
private insets;
|
|
72
|
+
private theme;
|
|
73
|
+
private themeSetting;
|
|
74
|
+
private encoding;
|
|
75
|
+
private layoutOpts;
|
|
76
|
+
private table;
|
|
77
|
+
private spec;
|
|
78
|
+
private scene;
|
|
79
|
+
private styles;
|
|
80
|
+
private failure;
|
|
81
|
+
private splitBy;
|
|
82
|
+
private matched;
|
|
83
|
+
private filtered;
|
|
84
|
+
private targets;
|
|
85
|
+
private origins;
|
|
86
|
+
private positions;
|
|
87
|
+
private morphFrom;
|
|
88
|
+
private morphing;
|
|
89
|
+
private views;
|
|
90
|
+
private rand;
|
|
91
|
+
private killedAt;
|
|
92
|
+
private world;
|
|
93
|
+
private camera;
|
|
94
|
+
private yaw;
|
|
95
|
+
private yawVelocity;
|
|
96
|
+
private dragging;
|
|
97
|
+
/** A persistent selection, distinct from the transient hover. */
|
|
98
|
+
private selected;
|
|
99
|
+
/** Isolate one value of one dimension: everything else dims. */
|
|
100
|
+
private highlight;
|
|
101
|
+
/** Shockwaves from recent kills, drawn as expanding rings. */
|
|
102
|
+
private shocks;
|
|
103
|
+
private sprites;
|
|
104
|
+
private width;
|
|
105
|
+
private height;
|
|
106
|
+
private dpr;
|
|
107
|
+
private raf;
|
|
108
|
+
private lastFrame;
|
|
109
|
+
private running;
|
|
110
|
+
private hovered;
|
|
111
|
+
private pointer;
|
|
112
|
+
private resizeObserver?;
|
|
113
|
+
private motionQuery?;
|
|
114
|
+
private themeQuery?;
|
|
115
|
+
constructor(container: HTMLElement, options?: TraceLightOptions);
|
|
116
|
+
/** Draw a hand-written flat graph. The v0.1 path; still supported unchanged. */
|
|
117
|
+
setGraph(graph: Graph): void;
|
|
118
|
+
/** Draw a dimensional flow table under a view spec. */
|
|
119
|
+
setTable(table: FlowTable, spec?: ViewSpec): void;
|
|
120
|
+
/**
|
|
121
|
+
* Change the knobs. With a table loaded this re-projects (and morphs); with a
|
|
122
|
+
* flat graph it just restyles. Safe to call every frame.
|
|
123
|
+
*/
|
|
124
|
+
setSpec(spec: ViewSpec): void;
|
|
125
|
+
getSpec(): ViewSpec;
|
|
126
|
+
getScene(): Scene;
|
|
127
|
+
getLegend(): LegendGroup[];
|
|
128
|
+
/** What dimensions and measures the loaded table offers. */
|
|
129
|
+
schema(): TableSchema | null;
|
|
130
|
+
/** Kill nodes and watch the front travel. Pass [] to bring everything back. */
|
|
131
|
+
kill(ids: string[]): void;
|
|
132
|
+
/** Current health of a node under the active kills: ok, degraded or dead. */
|
|
133
|
+
health(id: string): NodeHealth;
|
|
134
|
+
/** Mark one node as selected. It keeps its ring until you pass null. */
|
|
135
|
+
select(id: string | null): void;
|
|
136
|
+
getSelected(): string | null;
|
|
137
|
+
/**
|
|
138
|
+
* Isolate one value of a dimension - "show me only eu-west" - by dimming
|
|
139
|
+
* every edge that does not carry it. Pass null to clear. Unlike a filter,
|
|
140
|
+
* nothing is re-projected: the rest of the picture stays where it is, faded,
|
|
141
|
+
* so you can see the isolated traffic *in context*.
|
|
142
|
+
*/
|
|
143
|
+
setHighlight(highlight: {
|
|
144
|
+
field: string;
|
|
145
|
+
value: string;
|
|
146
|
+
} | null): void;
|
|
147
|
+
/** Nudge the world camera. Yaw is in radians; the renderer eases toward it. */
|
|
148
|
+
setYaw(yaw: number): void;
|
|
149
|
+
getYaw(): number;
|
|
150
|
+
setOptions(options: Partial<TraceLightOptions>): void;
|
|
151
|
+
stats(): Stats;
|
|
152
|
+
start(): void;
|
|
153
|
+
stop(): void;
|
|
154
|
+
toDataURL(type?: string): string;
|
|
155
|
+
destroy(): void;
|
|
156
|
+
private reproject;
|
|
157
|
+
private applyScene;
|
|
158
|
+
private layout;
|
|
159
|
+
private buildViews;
|
|
160
|
+
private isWorld;
|
|
161
|
+
/** Which plane a node sits on: an explicit binding, else its kind. */
|
|
162
|
+
private tierOf;
|
|
163
|
+
/**
|
|
164
|
+
* How big a body is drawn. Mass, not area: a fleet of 64 should read as
|
|
165
|
+
* bigger than a single box without swallowing the plane, so it grows with the
|
|
166
|
+
* logarithm of the instance count.
|
|
167
|
+
*/
|
|
168
|
+
private bodySize;
|
|
169
|
+
/**
|
|
170
|
+
* Shrink every body when the projection puts more things on screen than the
|
|
171
|
+
* canvas can hold at full size. Expanding a service into forty APIs should
|
|
172
|
+
* give you smaller machines, not a pile of overlapping ones.
|
|
173
|
+
*/
|
|
174
|
+
private crowdScale;
|
|
175
|
+
/** How rows are ordered inside a flat column, from the spec. */
|
|
176
|
+
private rowKey;
|
|
177
|
+
/** The drawable box once insets and the legend strip are taken out. */
|
|
178
|
+
private box;
|
|
179
|
+
/** Re-project after a camera change, keeping everything else in place. */
|
|
180
|
+
private recamera;
|
|
181
|
+
/** Flatten the world onto the screen for this frame's camera. */
|
|
182
|
+
private projectWorld;
|
|
183
|
+
private pathFor;
|
|
184
|
+
private onMotionChange;
|
|
185
|
+
private onThemeChange;
|
|
186
|
+
private resize;
|
|
187
|
+
private frame;
|
|
188
|
+
/** Seconds after the kill at which the front reaches this edge. */
|
|
189
|
+
private frontArrival;
|
|
190
|
+
private draw;
|
|
191
|
+
/** Is this edge pushed into the background by the current hover, selection or isolation? */
|
|
192
|
+
private isDimmed;
|
|
193
|
+
private drawEdge;
|
|
194
|
+
/**
|
|
195
|
+
* A rigid (fail-closed) coupling is drawn as a mechanical conduit: two
|
|
196
|
+
* parallel rails with cross-ties. It looks like something that transmits
|
|
197
|
+
* force, because that is exactly what it does - death travels along it.
|
|
198
|
+
*/
|
|
199
|
+
private strokeRigid;
|
|
200
|
+
/**
|
|
201
|
+
* A breakaway (fail-open) coupling has a deliberate parting line: a gap with
|
|
202
|
+
* two facing chevrons. When the far side dies it opens, and an amber shield
|
|
203
|
+
* arc marks where the front stopped. A fail-open dependency is a firebreak
|
|
204
|
+
* and the picture should say so.
|
|
205
|
+
*/
|
|
206
|
+
private drawBreakaway;
|
|
207
|
+
/** Where a rigid coupling gives way, it fractures rather than fading. */
|
|
208
|
+
private drawFracture;
|
|
209
|
+
private drawParticles;
|
|
210
|
+
/** A cached radial sprite per colour: bright core, soft halo. */
|
|
211
|
+
private sprite;
|
|
212
|
+
private drawEdgeLabel;
|
|
213
|
+
private drawNode;
|
|
214
|
+
/**
|
|
215
|
+
* A neighbourhood per group. When boxes are arranged by a dimension (a team,
|
|
216
|
+
* a tier), the boxes sharing a value get a soft region behind them with the
|
|
217
|
+
* value written at the top, so "these live together" is drawn, not inferred
|
|
218
|
+
* from alignment.
|
|
219
|
+
*/
|
|
220
|
+
private drawGroups;
|
|
221
|
+
/**
|
|
222
|
+
* The planes themselves. Drawing the ground a tier sits on is what turns a
|
|
223
|
+
* scatter of boxes into somewhere - and it makes "the data tier" a place you
|
|
224
|
+
* can point at rather than a convention you have to remember.
|
|
225
|
+
*/
|
|
226
|
+
private drawTiers;
|
|
227
|
+
private tierLabel;
|
|
228
|
+
private drawWorldNode;
|
|
229
|
+
private componentHint;
|
|
230
|
+
/**
|
|
231
|
+
* The error halo: a red glow that scales with how bad things are. Low
|
|
232
|
+
* intensity is a thin warm rim you notice on a second look; high intensity
|
|
233
|
+
* is a wide bloom that breathes slowly, so a burning box is the thing you
|
|
234
|
+
* see from across the room without anything flashing at you.
|
|
235
|
+
*/
|
|
236
|
+
private drawDangerGlow;
|
|
237
|
+
/** A steady ring around the selected thing, with a slow breathing halo. */
|
|
238
|
+
private drawSelectionRing;
|
|
239
|
+
/** The moment of a kill: one expanding ring, gone in a second and a half. */
|
|
240
|
+
private drawShock;
|
|
241
|
+
private drawLegend;
|
|
242
|
+
private placeLabels;
|
|
243
|
+
private hitTest;
|
|
244
|
+
private onPointerDown;
|
|
245
|
+
private onPointerUp;
|
|
246
|
+
private onPointerMove;
|
|
247
|
+
private onPointerLeave;
|
|
248
|
+
private onClick;
|
|
249
|
+
private updateTooltip;
|
|
250
|
+
}
|
|
251
|
+
export { couplingFor };
|
|
252
|
+
//# sourceMappingURL=renderer.d.ts.map
|