You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(diagnostics): Diagnostic Sessions — containers and VMs on one time axis
Implements the retrospective slice of plans/deep-spec-unified-live-diagnostics.md
(I1, I3, I4, I7), which is what that spec recommended shipping first: it is the
cheap half, and it produces the evidence live capture should be gated on —
whether operators create cross-provider sessions at all, and whether real clock
skew is small enough for correlation to mean anything.
A session answers "what was happening across my estate at 14:32?" and changes
nothing.
Design
- Stores only its DEFINITION: which subjects, over which window. Every series is
re-read from container_stats*, vm_metric_samples, docker_events, health_events
and audit_log, all of which already exist. No sample table, deliberately: that
is what live capture needs, and adding it now would be storage for a feature
that has not earned it.
- One shared axis — bucket N is the same instant for every subject, which is what
makes a container and a VM comparable. Nothing is interpolated to align them.
The gate the deep-spec imposed, discharged before the schema settled
- 25 series x 900 samples reduce to 15 000 points in ~20 ms server-side.
- The page draws SVG polylines with no charting library.
Three failure modes, each a real monitoring-UI bug, encoded and tested
- A gap is a gap: empty buckets yield null, never 0. The implementation itself
fell into this — `Number(null)` is 0, so an early version turned missing
readings into measured zeros. The tests caught it before it shipped.
- Cumulative counters reset: a container restart returns net_rx to zero, so the
delta breaks the line instead of drawing a cliff.
- Clock skew is reported, never corrected. Correcting would hide the thing most
likely to make two series incomparable.
Two further bugs found by driving a real browser, which the unit tests could not
see
- The i18n block was registered at the top level while the page reads
`pages.diagnostics.*`, so every label rendered as its raw key.
- Sparse data rendered as an empty chart: at 600 buckets each reading lands in
its own bucket, and dropping single-point runs made real data invisible — the
same "missing looks like nothing happened" failure, one layer up. Isolated
readings now render as dots.
Also: annotations carry usernames but never client IPs; create, delete and export
are audited; the page is registered with a help entry and EN/RO labels.
38 new tests across 2 suites. Full suite: 336 suites, 4170 passing.
Browser-verified 7/7 against seeded history with a deliberate gap and a counter reset.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
intro: 'Answers "what was happening across my estate at 14:32?" by putting containers and VMs on one time axis.',
29
+
sections: [
30
+
{icon: 'fa-clock-rotate-left',title: 'Retrospective, not a collector',body: 'A session stores only which subjects over which window. Every series is re-read from metrics already collected, so creating one changes nothing and costs no extra sampling.'},
31
+
{icon: 'fa-chart-line',title: 'One shared axis',body: 'Bucket N means the same instant for every subject, which is what makes a container and a VM comparable at a glance. Nothing is interpolated to line them up.'},
32
+
{icon: 'fa-square-minus',title: 'A gap is a gap',body: 'Missing data renders as a break in the line, never as zero. A cumulative counter that resets when a container restarts breaks the line too, rather than drawing a cliff.'},
33
+
{icon: 'fa-triangle-exclamation',title: 'Clock skew is reported',body: 'If the sources disagree by more than two seconds you are told, and by how much. The offset is never silently corrected, because that would turn a coincidence into an apparent cause.'},
34
+
],
35
+
tip: 'Correlation is not causation. A session shows you what happened together; it does not claim one caused the other.',
36
+
},
37
+
ro: {
38
+
title: 'Sesiuni de diagnostic',icon: 'fa-wave-square',
39
+
intro: 'Raspunde la "ce se intampla in parcul meu la 14:32?" punand containere si VM-uri pe aceeasi axa de timp.',
40
+
sections: [
41
+
{icon: 'fa-clock-rotate-left',title: 'Retrospectiv, nu colector',body: 'O sesiune retine doar ce subiecte si ce fereastra. Fiecare serie e recitita din metricile deja colectate, deci crearea ei nu schimba nimic si nu costa esantionare in plus.'},
42
+
{icon: 'fa-chart-line',title: 'O singura axa comuna',body: 'Bucket-ul N inseamna acelasi moment pentru fiecare subiect, ceea ce face comparabile un container si un VM dintr-o privire. Nimic nu e interpolat ca sa se alinieze.'},
43
+
{icon: 'fa-square-minus',title: 'Un gol ramane gol',body: 'Datele lipsa apar ca intrerupere a liniei, niciodata ca zero. Un contor cumulativ care se reseteaza la restartul containerului rupe la fel linia, in loc sa deseneze o prapastie.'},
44
+
{icon: 'fa-triangle-exclamation',title: 'Derapajul de ceas e raportat',body: 'Daca sursele difera cu peste doua secunde esti anuntat, si cu cat. Decalajul nu e corectat tacit, fiindca asta ar transforma o coincidenta intr-o cauza aparenta.'},
45
+
],
46
+
tip: 'Corelatia nu e cauzalitate. O sesiune arata ce s-a intamplat impreuna; nu pretinde ca una a cauzat-o pe cealalta.',
0 commit comments