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/channels.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { isMeasure } from './project.js';
|
|
2
|
+
import { clamp, contrast, defaultEncoding, emissionRate, logNorm, particleRadius, particleSpeed, rpsDomain, } from './scales.js';
|
|
3
|
+
/** Error rate below which a danger halo draws nothing: every box has some errors. */
|
|
4
|
+
export const ERROR_FLOOR = 0.004;
|
|
5
|
+
/** Error rate at which a danger halo is at full strength. */
|
|
6
|
+
export const ERROR_CEIL = 0.06;
|
|
7
|
+
export const CHANNELS = {
|
|
8
|
+
density: { name: 'density', target: 'edge', accepts: 'measure', summary: 'particles per second along the edge (log-scaled)' },
|
|
9
|
+
speed: { name: 'speed', target: 'edge', accepts: 'measure', summary: 'how fast particles travel; inverted, so high values crawl' },
|
|
10
|
+
radius: { name: 'radius', target: 'edge', accepts: 'measure', summary: 'particle size (sqrt-scaled)' },
|
|
11
|
+
hue: { name: 'hue', target: 'edge', accepts: 'dimension', maxCardinality: 12, summary: 'particle colour, one per category' },
|
|
12
|
+
glyph: { name: 'glyph', target: 'edge', accepts: 'dimension', maxCardinality: 6, summary: 'particle shape; readable in greyscale, so it pairs with hue' },
|
|
13
|
+
dash: { name: 'dash', target: 'edge', accepts: 'dimension', maxCardinality: 5, summary: 'the edge line pattern under the particles' },
|
|
14
|
+
lane: { name: 'lane', target: 'edge', accepts: 'dimension', maxCardinality: 6, summary: 'splits an edge into parallel lanes, one per category' },
|
|
15
|
+
coupling: { name: 'coupling', target: 'edge', accepts: 'dimension', maxCardinality: 3, summary: 'failure semantics: a rigid conduit that propagates death, or a breakaway link that stops it' },
|
|
16
|
+
distance: { name: 'distance', target: 'edge', accepts: 'both', maxCardinality: 24, summary: 'how close things sit: bind a measure and heavy callers pull together, bind a dimension and same-value things cluster' },
|
|
17
|
+
nodeFill: { name: 'nodeFill', target: 'node', accepts: 'dimension', maxCardinality: 10, summary: 'node fill colour, one per category' },
|
|
18
|
+
halo: { name: 'halo', target: 'node', accepts: 'measure', summary: 'a ring around the node sized by a measure - traffic through it, or any numeric fact such as instances. Bound to an error rate it becomes a red glow that scales with how bad things are: 0.5% is a hint, 5% is a siren' },
|
|
19
|
+
column: { name: 'column', target: 'node', accepts: 'dimension', maxCardinality: 12, summary: 'forces nodes into columns by category instead of inferring layers' },
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Categorical palette.
|
|
23
|
+
*
|
|
24
|
+
* Ordered so the first few stay distinguishable under the common forms of
|
|
25
|
+
* colour-vision deficiency, and legible on both a light and a dark ground.
|
|
26
|
+
*
|
|
27
|
+
* Red is absent and amber comes late on purpose: those two are *semantic* here.
|
|
28
|
+
* Red means an error and amber means degraded, and a category that borrows one
|
|
29
|
+
* of them makes a healthy region look like an incident. Two encodings cannot
|
|
30
|
+
* share a colour any more than they can share a channel.
|
|
31
|
+
*/
|
|
32
|
+
export const CATEGORICAL = [
|
|
33
|
+
'#3b82f6',
|
|
34
|
+
'#10b981',
|
|
35
|
+
'#a855f7',
|
|
36
|
+
'#06b6d4',
|
|
37
|
+
'#ec4899',
|
|
38
|
+
'#84cc16',
|
|
39
|
+
'#8b5cf6',
|
|
40
|
+
'#14b8a6',
|
|
41
|
+
'#eab308',
|
|
42
|
+
'#f97316',
|
|
43
|
+
];
|
|
44
|
+
const GLYPHS = ['dot', 'ring', 'square', 'triangle', 'bar', 'diamond'];
|
|
45
|
+
const DASHES = [null, [7, 5], [2, 4], [12, 4, 2, 4], [1, 5]];
|
|
46
|
+
const GLYPH_MARK = {
|
|
47
|
+
dot: '●',
|
|
48
|
+
ring: '◍',
|
|
49
|
+
square: '■',
|
|
50
|
+
triangle: '▲',
|
|
51
|
+
bar: '▬',
|
|
52
|
+
diamond: '◆',
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Stable value ordering, so a category keeps its colour across re-projections.
|
|
56
|
+
* An explicit `order` on the binding comes first; anything unlisted follows,
|
|
57
|
+
* sorted, so a partial order is still a complete one.
|
|
58
|
+
*/
|
|
59
|
+
function domainOf(values, order) {
|
|
60
|
+
const all = [...new Set(values)];
|
|
61
|
+
if (!order?.length)
|
|
62
|
+
return all.sort();
|
|
63
|
+
const rank = new Map(order.map((v, i) => [v, i]));
|
|
64
|
+
return all.sort((a, b) => {
|
|
65
|
+
const ra = rank.get(a);
|
|
66
|
+
const rb = rank.get(b);
|
|
67
|
+
if (ra !== undefined && rb !== undefined)
|
|
68
|
+
return ra - rb;
|
|
69
|
+
if (ra !== undefined)
|
|
70
|
+
return -1;
|
|
71
|
+
if (rb !== undefined)
|
|
72
|
+
return 1;
|
|
73
|
+
return a.localeCompare(b);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function measureOf(edge, field) {
|
|
77
|
+
const m = edge.metrics;
|
|
78
|
+
return m[field] ?? 0;
|
|
79
|
+
}
|
|
80
|
+
function dimOf(edge, field) {
|
|
81
|
+
return edge.dims[field] ?? (edge.spans[field]?.length === 1 ? edge.spans[field][0] : undefined);
|
|
82
|
+
}
|
|
83
|
+
function nodeDimOf(node, field) {
|
|
84
|
+
return node.key[field] ?? (node.spans[field]?.length === 1 ? node.spans[field][0] : undefined);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve every binding into concrete visual values.
|
|
88
|
+
*
|
|
89
|
+
* Unbound channels fall back to the v0.1 encoding, so a scene with no spec at
|
|
90
|
+
* all still draws the way it always did.
|
|
91
|
+
*/
|
|
92
|
+
export function styleScene(scene, spec, theme, enc = defaultEncoding) {
|
|
93
|
+
const bindings = (spec.channels ?? {});
|
|
94
|
+
const legend = [];
|
|
95
|
+
const issues = [];
|
|
96
|
+
const rpsDom = rpsDomain(scene.edges.map((e) => e.metrics.rps));
|
|
97
|
+
// --- helpers -------------------------------------------------------------
|
|
98
|
+
const categorical = (channel, values, binding) => {
|
|
99
|
+
const def = CHANNELS[channel];
|
|
100
|
+
const index = new Map(values.map((v, i) => [v, i]));
|
|
101
|
+
if (def.maxCardinality && values.length > def.maxCardinality) {
|
|
102
|
+
const warning = `${values.length} distinct values of "${binding.field}" is too many for ${channel} (max ${def.maxCardinality}); left at the default`;
|
|
103
|
+
issues.push(warning);
|
|
104
|
+
legend.push({ channel, field: binding.field, kind: 'dimension', summary: def.summary, swatches: [], warning });
|
|
105
|
+
return { index, ok: false };
|
|
106
|
+
}
|
|
107
|
+
return { index, ok: true };
|
|
108
|
+
};
|
|
109
|
+
const measureNorm = (value, domain, binding) => {
|
|
110
|
+
const scale = binding.scale ?? (binding.field === 'share' || binding.field === 'errorRate' ? 'linear' : 'log');
|
|
111
|
+
let t;
|
|
112
|
+
if (scale === 'linear')
|
|
113
|
+
t = domain.max > domain.min ? (value - domain.min) / (domain.max - domain.min) : 1;
|
|
114
|
+
else if (scale === 'sqrt')
|
|
115
|
+
t = domain.max > 0 ? Math.sqrt(Math.max(value, 0) / domain.max) : 0;
|
|
116
|
+
else
|
|
117
|
+
t = logNorm(value, domain.min, domain.max);
|
|
118
|
+
return binding.invert ? 1 - t : t;
|
|
119
|
+
};
|
|
120
|
+
const measureDomain = (field) => {
|
|
121
|
+
if (field === 'share' || field === 'errorRate')
|
|
122
|
+
return { min: 0, max: 1 };
|
|
123
|
+
const values = scene.edges.map((e) => measureOf(e, field)).filter((v) => v > 0);
|
|
124
|
+
if (!values.length)
|
|
125
|
+
return { min: 0, max: 1 };
|
|
126
|
+
const max = Math.max(...values);
|
|
127
|
+
return { min: Math.min(Math.min(...values), max / 1000), max };
|
|
128
|
+
};
|
|
129
|
+
// --- edge channels -------------------------------------------------------
|
|
130
|
+
const edgeStyles = new Map();
|
|
131
|
+
const hueBinding = bindings.hue;
|
|
132
|
+
const hueDomain = hueBinding && !isMeasure(hueBinding.field)
|
|
133
|
+
? domainOf(scene.edges.map((e) => dimOf(e, hueBinding.field) ?? '—'))
|
|
134
|
+
: [];
|
|
135
|
+
const hueIdx = hueBinding ? categorical('hue', hueDomain, hueBinding) : null;
|
|
136
|
+
const glyphBinding = bindings.glyph;
|
|
137
|
+
const glyphDomain = glyphBinding ? domainOf(scene.edges.map((e) => dimOf(e, glyphBinding.field) ?? '—')) : [];
|
|
138
|
+
const glyphIdx = glyphBinding ? categorical('glyph', glyphDomain, glyphBinding) : null;
|
|
139
|
+
const dashBinding = bindings.dash;
|
|
140
|
+
const dashDomain = dashBinding ? domainOf(scene.edges.map((e) => dimOf(e, dashBinding.field) ?? '—')) : [];
|
|
141
|
+
const dashIdx = dashBinding ? categorical('dash', dashDomain, dashBinding) : null;
|
|
142
|
+
const laneBinding = bindings.lane;
|
|
143
|
+
const laneDomain = laneBinding ? domainOf(scene.edges.map((e) => dimOf(e, laneBinding.field) ?? '—'), laneBinding.order) : [];
|
|
144
|
+
const laneIdx = laneBinding ? categorical('lane', laneDomain, laneBinding) : null;
|
|
145
|
+
const distanceBinding = bindings.distance;
|
|
146
|
+
const distanceIsMeasure = Boolean(distanceBinding && isMeasure(distanceBinding.field));
|
|
147
|
+
const distanceDomain = distanceBinding && distanceIsMeasure ? measureDomain(distanceBinding.field) : { min: 0, max: 1 };
|
|
148
|
+
const clusterBy = distanceBinding && !distanceIsMeasure ? distanceBinding.field : null;
|
|
149
|
+
const couplingBinding = bindings.coupling;
|
|
150
|
+
const couplingDomain = couplingBinding
|
|
151
|
+
? domainOf(scene.edges.map((e) => dimOf(e, couplingBinding.field) ?? '—'))
|
|
152
|
+
: [];
|
|
153
|
+
const densityBinding = bindings.density;
|
|
154
|
+
const densityDomain = densityBinding ? measureDomain(densityBinding.field) : rpsDom;
|
|
155
|
+
const speedBinding = bindings.speed;
|
|
156
|
+
const speedDomain = speedBinding ? measureDomain(speedBinding.field) : { min: 0, max: 1 };
|
|
157
|
+
const radiusBinding = bindings.radius;
|
|
158
|
+
const radiusDomain = radiusBinding ? measureDomain(radiusBinding.field) : { min: 0, max: 1 };
|
|
159
|
+
const palette = (binding) => binding?.palette ?? CATEGORICAL;
|
|
160
|
+
for (const edge of scene.edges) {
|
|
161
|
+
// density
|
|
162
|
+
let density;
|
|
163
|
+
if (densityBinding) {
|
|
164
|
+
const t = contrast(measureNorm(measureOf(edge, densityBinding.field), densityDomain, densityBinding), enc.densityCurve);
|
|
165
|
+
density = measureOf(edge, densityBinding.field) <= 0 ? 0 : enc.minEmitPerSecond + t * (enc.maxEmitPerSecond - enc.minEmitPerSecond);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
density = emissionRate(edge.metrics.rps, rpsDom, enc);
|
|
169
|
+
}
|
|
170
|
+
// speed
|
|
171
|
+
let speed;
|
|
172
|
+
if (speedBinding) {
|
|
173
|
+
const t = measureNorm(measureOf(edge, speedBinding.field), speedDomain, speedBinding);
|
|
174
|
+
speed = enc.maxSpeedPxPerSecond - t * (enc.maxSpeedPxPerSecond - enc.minSpeedPxPerSecond);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
speed = particleSpeed(edge.metrics.latencyMs, enc);
|
|
178
|
+
}
|
|
179
|
+
// radius
|
|
180
|
+
let radius;
|
|
181
|
+
if (radiusBinding) {
|
|
182
|
+
const t = measureNorm(measureOf(edge, radiusBinding.field), radiusDomain, { ...radiusBinding, scale: radiusBinding.scale ?? 'sqrt' });
|
|
183
|
+
radius = enc.minRadiusPx + t * (enc.maxRadiusPx - enc.minRadiusPx);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
radius = particleRadius(edge.metrics.bytes, enc);
|
|
187
|
+
}
|
|
188
|
+
// hue
|
|
189
|
+
let hue = theme.flow[edge.kind];
|
|
190
|
+
if (hueBinding && hueIdx?.ok) {
|
|
191
|
+
const v = dimOf(edge, hueBinding.field) ?? '—';
|
|
192
|
+
const p = palette(hueBinding);
|
|
193
|
+
hue = bindOverride(hueBinding, v) ?? p[(hueIdx.index.get(v) ?? 0) % p.length];
|
|
194
|
+
}
|
|
195
|
+
// glyph
|
|
196
|
+
let glyph = 'dot';
|
|
197
|
+
if (glyphBinding && glyphIdx?.ok) {
|
|
198
|
+
const v = dimOf(edge, glyphBinding.field) ?? '—';
|
|
199
|
+
glyph = bindOverride(glyphBinding, v) ?? GLYPHS[(glyphIdx.index.get(v) ?? 0) % GLYPHS.length];
|
|
200
|
+
}
|
|
201
|
+
// dash
|
|
202
|
+
let dash = edge.kind === 'retry' || edge.kind === 'challenge' ? [5, 5] : null;
|
|
203
|
+
if (dashBinding && dashIdx?.ok) {
|
|
204
|
+
const v = dimOf(edge, dashBinding.field) ?? '—';
|
|
205
|
+
dash = DASHES[(dashIdx.index.get(v) ?? 0) % DASHES.length] ?? null;
|
|
206
|
+
}
|
|
207
|
+
// lane
|
|
208
|
+
let lane = 0;
|
|
209
|
+
let laneLabel = null;
|
|
210
|
+
if (laneBinding && laneIdx?.ok) {
|
|
211
|
+
const v = dimOf(edge, laneBinding.field) ?? '—';
|
|
212
|
+
lane = laneIdx.index.get(v) ?? 0;
|
|
213
|
+
laneLabel = v;
|
|
214
|
+
}
|
|
215
|
+
// coupling
|
|
216
|
+
let coupling = 'plain';
|
|
217
|
+
if (couplingBinding) {
|
|
218
|
+
const v = dimOf(edge, couplingBinding.field) ?? '—';
|
|
219
|
+
coupling = couplingFor(v, couplingBinding);
|
|
220
|
+
}
|
|
221
|
+
// Unbound, distance pulls on share: the fraction of the caller's traffic
|
|
222
|
+
// that goes down this edge. Two services that send most of what they have
|
|
223
|
+
// to each other are coupled, whatever the absolute rps.
|
|
224
|
+
const strength = distanceBinding?.strength ?? 1;
|
|
225
|
+
const attraction = clamp((distanceBinding && distanceIsMeasure
|
|
226
|
+
? measureNorm(measureOf(edge, distanceBinding.field), distanceDomain, distanceBinding)
|
|
227
|
+
: clamp(edge.metrics.share ?? 0.3, 0, 1)) * strength, 0, 2);
|
|
228
|
+
edgeStyles.set(edge.id, { density, speed, radius, hue, glyph, dash, lane, laneLabel, coupling, attraction });
|
|
229
|
+
}
|
|
230
|
+
// --- node channels -------------------------------------------------------
|
|
231
|
+
const nodeStyles = new Map();
|
|
232
|
+
const fillBinding = bindings.nodeFill;
|
|
233
|
+
const fillDomain = fillBinding ? domainOf(scene.nodes.map((n) => nodeDimOf(n, fillBinding.field) ?? '—')) : [];
|
|
234
|
+
const fillIdx = fillBinding ? categorical('nodeFill', fillDomain, fillBinding) : null;
|
|
235
|
+
const columnBinding = bindings.column;
|
|
236
|
+
const columnDomain = columnBinding ? domainOf(scene.nodes.map((n) => nodeDimOf(n, columnBinding.field) ?? '—'), columnBinding.order) : [];
|
|
237
|
+
const columnIdx = columnBinding ? categorical('column', columnDomain, columnBinding) : null;
|
|
238
|
+
const haloBinding = bindings.halo;
|
|
239
|
+
// A halo can size by traffic through the node or by any numeric fact on it
|
|
240
|
+
// (instances, connections, ...). Node facts win when the name matches one.
|
|
241
|
+
const haloValue = (n) => {
|
|
242
|
+
const f = haloBinding?.field ?? 'inboundRps';
|
|
243
|
+
if (f === 'outboundRps')
|
|
244
|
+
return n.outboundRps;
|
|
245
|
+
if (f === 'inboundRps' || f === 'rps')
|
|
246
|
+
return n.inboundRps;
|
|
247
|
+
return n.attrs[f] ?? 0;
|
|
248
|
+
};
|
|
249
|
+
const haloValues = scene.nodes.map(haloValue);
|
|
250
|
+
const haloMax = Math.max(1, ...haloValues);
|
|
251
|
+
for (const node of scene.nodes) {
|
|
252
|
+
let fill = theme.node[node.kind];
|
|
253
|
+
if (fillBinding && fillIdx?.ok) {
|
|
254
|
+
const v = nodeDimOf(node, fillBinding.field) ?? '—';
|
|
255
|
+
const p = palette(fillBinding);
|
|
256
|
+
fill = mix(p[(fillIdx.index.get(v) ?? 0) % p.length], theme.name === 'dark' ? 0.72 : 0.84, theme);
|
|
257
|
+
}
|
|
258
|
+
let halo = 0;
|
|
259
|
+
let haloIntensity = 0;
|
|
260
|
+
const haloDanger = /error|fail|5xx/i.test(haloBinding?.field ?? '');
|
|
261
|
+
if (haloBinding) {
|
|
262
|
+
const v = haloValue(node);
|
|
263
|
+
let t;
|
|
264
|
+
if (haloDanger) {
|
|
265
|
+
// Error rates read on an absolute scale so the picture means the same
|
|
266
|
+
// thing every day: a fleet where the worst box is at 0.3% should look
|
|
267
|
+
// calm, not have one box lit up just for being the worst. Log between
|
|
268
|
+
// ERROR_FLOOR and ERROR_CEIL, so 0.5% is a hint and 5% is a siren.
|
|
269
|
+
t = v > ERROR_FLOOR ? logNorm(v, ERROR_FLOOR, ERROR_CEIL) : 0;
|
|
270
|
+
}
|
|
271
|
+
else if (haloBinding.field === 'share') {
|
|
272
|
+
t = clamp(v / Math.max(haloMax, 0.0001), 0, 1);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
// Counts span decades and read on a log.
|
|
276
|
+
t = v > 0 ? logNorm(v, Math.max(haloMax / 1000, 0.001), haloMax) : 0;
|
|
277
|
+
}
|
|
278
|
+
haloIntensity = t;
|
|
279
|
+
halo = t > 0 ? 3 + t * 13 : 0;
|
|
280
|
+
}
|
|
281
|
+
const groupValue = columnBinding ? (nodeDimOf(node, columnBinding.field) ?? null) : null;
|
|
282
|
+
const column = columnBinding && columnIdx?.ok
|
|
283
|
+
? (columnIdx.index.get(nodeDimOf(node, columnBinding.field) ?? '—') ?? null)
|
|
284
|
+
: null;
|
|
285
|
+
nodeStyles.set(node.id, { fill, halo, haloDanger, haloIntensity, column, group: groupValue });
|
|
286
|
+
}
|
|
287
|
+
// --- legend --------------------------------------------------------------
|
|
288
|
+
if (hueBinding && hueIdx?.ok) {
|
|
289
|
+
const p = palette(hueBinding);
|
|
290
|
+
legend.push({
|
|
291
|
+
channel: 'hue',
|
|
292
|
+
field: hueBinding.field,
|
|
293
|
+
kind: 'dimension',
|
|
294
|
+
summary: CHANNELS.hue.summary,
|
|
295
|
+
swatches: hueDomain.map((v, i) => ({ value: v, color: bindOverride(hueBinding, v) ?? p[i % p.length] })),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
if (glyphBinding && glyphIdx?.ok) {
|
|
299
|
+
legend.push({
|
|
300
|
+
channel: 'glyph',
|
|
301
|
+
field: glyphBinding.field,
|
|
302
|
+
kind: 'dimension',
|
|
303
|
+
summary: CHANNELS.glyph.summary,
|
|
304
|
+
swatches: glyphDomain.map((v, i) => ({ value: v, mark: GLYPH_MARK[GLYPHS[i % GLYPHS.length]] })),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (dashBinding && dashIdx?.ok) {
|
|
308
|
+
legend.push({
|
|
309
|
+
channel: 'dash',
|
|
310
|
+
field: dashBinding.field,
|
|
311
|
+
kind: 'dimension',
|
|
312
|
+
summary: CHANNELS.dash.summary,
|
|
313
|
+
swatches: dashDomain.map((v, i) => ({ value: v, mark: DASHES[i % DASHES.length] ? '– –' : '——' })),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
if (laneBinding && laneIdx?.ok) {
|
|
317
|
+
legend.push({
|
|
318
|
+
channel: 'lane',
|
|
319
|
+
field: laneBinding.field,
|
|
320
|
+
kind: 'dimension',
|
|
321
|
+
summary: CHANNELS.lane.summary,
|
|
322
|
+
swatches: laneDomain.map((v, i) => ({ value: v, mark: `lane ${i + 1}` })),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (couplingBinding) {
|
|
326
|
+
legend.push({
|
|
327
|
+
channel: 'coupling',
|
|
328
|
+
field: couplingBinding.field,
|
|
329
|
+
kind: 'dimension',
|
|
330
|
+
summary: CHANNELS.coupling.summary,
|
|
331
|
+
swatches: couplingDomain.map((v) => ({ value: v, mark: couplingFor(v, couplingBinding) })),
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
if (distanceBinding) {
|
|
335
|
+
legend.push({
|
|
336
|
+
channel: 'distance',
|
|
337
|
+
field: distanceBinding.field,
|
|
338
|
+
kind: distanceIsMeasure ? 'measure' : 'dimension',
|
|
339
|
+
summary: !distanceIsMeasure
|
|
340
|
+
? 'things sharing this value cluster together'
|
|
341
|
+
: distanceBinding.field === 'share'
|
|
342
|
+
? 'coupled services sit together: the more of its traffic a caller sends down an edge, the shorter it is'
|
|
343
|
+
: 'heavier flows pull their endpoints together',
|
|
344
|
+
swatches: [],
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
for (const [name, binding] of [
|
|
348
|
+
['density', densityBinding],
|
|
349
|
+
['speed', speedBinding],
|
|
350
|
+
['radius', radiusBinding],
|
|
351
|
+
['halo', haloBinding],
|
|
352
|
+
]) {
|
|
353
|
+
if (!binding)
|
|
354
|
+
continue;
|
|
355
|
+
legend.push({ channel: name, field: binding.field, kind: 'measure', summary: CHANNELS[name].summary, swatches: [] });
|
|
356
|
+
}
|
|
357
|
+
if (fillBinding && fillIdx?.ok) {
|
|
358
|
+
const p = palette(fillBinding);
|
|
359
|
+
legend.push({
|
|
360
|
+
channel: 'nodeFill',
|
|
361
|
+
field: fillBinding.field,
|
|
362
|
+
kind: 'dimension',
|
|
363
|
+
summary: CHANNELS.nodeFill.summary,
|
|
364
|
+
swatches: fillDomain.map((v, i) => ({ value: v, color: p[i % p.length] })),
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (columnBinding && columnIdx?.ok) {
|
|
368
|
+
legend.push({
|
|
369
|
+
channel: 'column',
|
|
370
|
+
field: columnBinding.field,
|
|
371
|
+
kind: 'dimension',
|
|
372
|
+
summary: CHANNELS.column.summary,
|
|
373
|
+
swatches: columnDomain.map((v, i) => ({ value: v, mark: `col ${i + 1}` })),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return { edges: edgeStyles, nodes: nodeStyles, clusterBy, legend, issues };
|
|
377
|
+
}
|
|
378
|
+
function bindOverride(binding, value) {
|
|
379
|
+
return binding.map?.[value];
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Failure semantics are a first-party concept, not just another category, so
|
|
383
|
+
* the mapping recognises the vocabulary people actually use.
|
|
384
|
+
*/
|
|
385
|
+
export function couplingFor(value, binding) {
|
|
386
|
+
const override = binding?.map?.[value];
|
|
387
|
+
if (override === 'rigid' || override === 'breakaway' || override === 'plain')
|
|
388
|
+
return override;
|
|
389
|
+
const v = value.toLowerCase().replace(/[\s_]/g, '-');
|
|
390
|
+
if (v.includes('fail-closed') || v === 'closed' || v === 'hard' || v === 'required' || v === 'critical')
|
|
391
|
+
return 'rigid';
|
|
392
|
+
if (v.includes('fail-open') || v === 'open' || v === 'soft' || v === 'optional' || v === 'best-effort')
|
|
393
|
+
return 'breakaway';
|
|
394
|
+
return 'plain';
|
|
395
|
+
}
|
|
396
|
+
/** Blend a palette colour toward the theme surface, so node fills stay backgrounds. */
|
|
397
|
+
function mix(hex, toward, theme) {
|
|
398
|
+
const base = hexToRgb(hex);
|
|
399
|
+
const ground = hexToRgb(theme.surface);
|
|
400
|
+
const r = Math.round(base.r + (ground.r - base.r) * toward);
|
|
401
|
+
const g = Math.round(base.g + (ground.g - base.g) * toward);
|
|
402
|
+
const b = Math.round(base.b + (ground.b - base.b) * toward);
|
|
403
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
404
|
+
}
|
|
405
|
+
function hexToRgb(hex) {
|
|
406
|
+
const h = hex.replace('#', '');
|
|
407
|
+
const n = h.length === 3 ? h.split('').map((c) => c + c).join('') : h;
|
|
408
|
+
const v = Number.parseInt(n, 16);
|
|
409
|
+
return { r: (v >> 16) & 255, g: (v >> 8) & 255, b: v & 255 };
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { NodeHealth } from './failure.js';
|
|
2
|
+
import type { SceneNode } from './scene.js';
|
|
3
|
+
import type { Theme } from './theme.js';
|
|
4
|
+
/**
|
|
5
|
+
* The component library for world mode.
|
|
6
|
+
*
|
|
7
|
+
* Flat boxes are fine for a topology, but they make you *read* every label to
|
|
8
|
+
* know what a thing is. A little world does not: a rack reads as compute, a
|
|
9
|
+
* cylinder reads as a relational store, a chip reads as a cache, and the size
|
|
10
|
+
* of the rack tells you how many instances are behind it. You can glance at it.
|
|
11
|
+
*
|
|
12
|
+
* These are direct pictures of software, not factory metaphors - no conveyor
|
|
13
|
+
* belts, no smokestacks. The only borrowed cue is mass: more instances is
|
|
14
|
+
* visibly more machine.
|
|
15
|
+
*
|
|
16
|
+
* Extending: register a component here and any spec - hand-written or composed
|
|
17
|
+
* by a model - can select it by name. The renderer never knows their internals.
|
|
18
|
+
*/
|
|
19
|
+
export interface ComponentBox {
|
|
20
|
+
/** Centre x of the footprint. */
|
|
21
|
+
cx: number;
|
|
22
|
+
/** Top y of the footprint. */
|
|
23
|
+
top: number;
|
|
24
|
+
w: number;
|
|
25
|
+
h: number;
|
|
26
|
+
}
|
|
27
|
+
export interface Gauge {
|
|
28
|
+
label: string;
|
|
29
|
+
/** 0..1 */
|
|
30
|
+
value: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ComponentProps {
|
|
33
|
+
instances: number;
|
|
34
|
+
gauges: Gauge[];
|
|
35
|
+
fill: string;
|
|
36
|
+
stroke: string;
|
|
37
|
+
accent: string;
|
|
38
|
+
muted: string;
|
|
39
|
+
ground: string;
|
|
40
|
+
danger: string;
|
|
41
|
+
health: NodeHealth;
|
|
42
|
+
/** 0..1 animation of the failure front arriving. */
|
|
43
|
+
struck: number;
|
|
44
|
+
}
|
|
45
|
+
export interface WorldComponent {
|
|
46
|
+
name: string;
|
|
47
|
+
summary: string;
|
|
48
|
+
/** Which node kinds this is a sensible default for. */
|
|
49
|
+
tierHint: number;
|
|
50
|
+
draw(ctx: CanvasRenderingContext2D, box: ComponentBox, p: ComponentProps): void;
|
|
51
|
+
}
|
|
52
|
+
/** Height reserved under the body for gauges. */
|
|
53
|
+
export declare function gaugeSpace(p: ComponentProps): number;
|
|
54
|
+
/** How many silhouettes to stack for an instance count. Log, so 200 pods stay drawable. */
|
|
55
|
+
export declare function stackCount(instances: number): number;
|
|
56
|
+
export declare const COMPONENTS: Record<string, WorldComponent>;
|
|
57
|
+
export type ComponentName = keyof typeof COMPONENTS;
|
|
58
|
+
/**
|
|
59
|
+
* Pick a silhouette for a node. An explicit hint wins; then an engine-ish
|
|
60
|
+
* dimension; then the node kind. Falling back to the kind means an unannotated
|
|
61
|
+
* table still produces a legible world.
|
|
62
|
+
*/
|
|
63
|
+
export declare function pickComponent(node: SceneNode, hint?: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Default tier for a node kind, top to bottom: what talks to you, what runs
|
|
66
|
+
* your code, what holds your state.
|
|
67
|
+
*
|
|
68
|
+
* Three planes, not seven. Each plane costs real vertical pixels - the body,
|
|
69
|
+
* its gauges, and two lines of label - and a world with more planes than the
|
|
70
|
+
* canvas can afford is a world where every plane overlaps the next. Split
|
|
71
|
+
* further with `world.tierBy` when a particular question needs it.
|
|
72
|
+
*/
|
|
73
|
+
export declare function defaultTier(node: SceneNode): number;
|
|
74
|
+
export declare const TIER_LABELS: string[];
|
|
75
|
+
export declare function componentProps(theme: Theme): Pick<ComponentProps, 'stroke' | 'muted' | 'ground' | 'danger' | 'accent'>;
|
|
76
|
+
//# sourceMappingURL=components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,YAAY;IAC3B,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,GAAG,EAAE,wBAAwB,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACjF;AAKD,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAEpD;AAyBD,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGpD;AAyCD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAgSrD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,UAAU,CAAC;AAapD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAenD;AAED,eAAO,MAAM,WAAW,UAA+B,CAAC;AAExD,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAQtH"}
|