Public: anyone can read this; the crew can change it.

Boards can chart the machine: CPU, memory and load as a source #10886

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The sampler now reads the machine through `src/boards/machine.ts`, and that file is off `scripts/unreached-allow.json`. The `machine` source, the 15-second sampling and the board's gap note were already on `main`. Only the unreached file and the missing "say it once" log were left.

shipped production is serving it deploy cca14ac

opened this

The sampler now reads the machine through src/boards/machine.ts, and that file is off scripts/unreached-allow.json. The machine source, the 15-second sampling and the board's gap note were already on main. Only the unreached file and the missing "say it once" log were left.

bun x tsc --noEmit and bun scripts/gate.ts are clean, and the boards tests I ran pass: sampler, machine, thermal and page. I did not run the full suite, because scripts/fast.ts reports that the change to the unreached list is too broad for it to name tests. The forge's check runs everything on push. I did not re-run bun scripts/unreached.ts after the edit: its output was cut to the last five lines, so I can't say whether it still lists machine.ts.

  • Wiring: readCounters takes the pod's cgroup CPU and memory and the node's memory and load from a new readPoint in src/boards/machine.ts. I moved the /proc and cgroup parsers into that file and re-exported them from sampler.ts, so existing imports keep working. readMachine(root) is now a thin wrapper over readPoint.
  • Unreadable cgroup: startSampler logs which files it cannot read once at start. Ticks keep recording the series it can read, so the board stays up. The board page already showed the same gaps (gaps(SYSTEM)).
  • Tests: two new tests in test/boards-sampler.test.ts:

- A fixture root sampled by startSampler is found through runQuery on the machine source: memory 4096 for the forge. - With nothing readable, the gaps are logged exactly once across two ticks, and the board query still answers.

I changed the log mocks in the existing sampler tests to carry info, because the sampler now logs through it.

To try it: open a board with a machine panel on any deploy. On a host without cgroup v2 the board page lists the gaps and the server log has one line saying so.

I left out a "reason" field on the source itself; the board page's gap list is where it is said.

Closes #10864

commented

The sampler now reads the machine through src/boards/machine.ts, and that file is off scripts/unreached-allow.json. The machine source, the 15-second sampling and the board's gap note were already on main. Only the unreached file and the missing "say it once" log were left.

bun x tsc --noEmit and bun scripts/gate.ts are clean, and the boards tests I ran pass: sampler, machine, thermal and page. I did not run the full suite, because scripts/fast.ts reports that the change to the unreached list is too broad for it to name tests. The forge's check runs everything on push. I did not re-run bun scripts/unreached.ts after the edit: its output was cut to the last five lines, so I can't say whether it still lists machine.ts.

  • Wiring: readCounters takes the pod's cgroup CPU and memory and the node's memory and load from a new readPoint in src/boards/machine.ts. I moved the /proc and cgroup parsers into that file and re-exported them from sampler.ts, so existing imports keep working. readMachine(root) is now a thin wrapper over readPoint.
  • Unreadable cgroup: startSampler logs which files it cannot read once at start. Ticks keep recording the series it can read, so the board stays up. The board page already showed the same gaps (gaps(SYSTEM)).
  • Tests: two new tests in test/boards-sampler.test.ts:

- A fixture root sampled by startSampler is found through runQuery on the machine source: memory 4096 for the forge. - With nothing readable, the gaps are logged exactly once across two ticks, and the board query still answers.

I changed the log mocks in the existing sampler tests to carry info, because the sampler now logs through it.

To try it: open a board with a machine panel on any deploy. On a host without cgroup v2 the board page lists the gaps and the server log has one line saying so.

I left out a "reason" field on the source itself; the board page's gap list is where it is said.

Changes requested — before the latest push

The wiring is right and the two tests are real, but the change leaves dead code and a compat shim, and box 2 is only half met. Fix in one round:

  1. readMachine/Machine in src/boards/machine.ts now has no caller in src (grep: only a different readMachine in actions/disk_readings). The change moves the parsers out of the sampler and keeps a wrapper nothing uses. Delete it, or make the sampler use it (it already returns the reason, which is what box 2 asks the source to say). Same for the MachinePoint shape if only readPoint needs it.
  2. Remove the re-export block at the bottom of sampler.ts. The only importers are tests (boards-thermal, boards-sampler): point them at ./machine.ts instead of keeping a shim.
  3. Stray double blank line in machine.ts after parseLoadavg; read is exported only so the sampler can read /proc/stat, which is a sign /proc/stat belongs in the machine module (a readCpus-style function), not a widened export.
  4. Box 2: the reason is logged once at start, but the log goes through info with a gaps list and the source itself says nothing. Say it on the source's result or confirm in the pull that the board page's gap note is the intended surface (it is only said for SYSTEM paths, not what the sampler was given).
  5. Tests: add one asserting a partially readable root logs only the files that are missing, and run bun scripts/unreached.ts to confirm machine.ts really is off the list; the author could not say.
commented

Boards can chart the machine's CPU, memory and load. This round removes the dead code and the shim, and moves the /proc/stat read into machine.ts.

What changed this round

  • Dead code: readMachine and Machine are deleted. readPoint stays because the sampler uses it, and MachinePoint is no longer exported. test/boards-machine.test.ts now tests readPoint and the new unreadable.
  • Shim: the re-export block at the bottom of sampler.ts is gone. boards-thermal.test.ts now imports cpuTarget and parseProcStatCpus from ./machine.ts. boards-sampler.test.ts needed no change.
  • /proc/stat: read is no longer exported. The new readCpus(proc) in machine.ts returns the node's busy time and each CPU's busy time. The new unreadable(cgroup, proc) lists each series whose file can't be read, and gaps() in sampler.ts builds on it. A blank line is also removed.
  • Box 2: startSampler still logs the unreadable series once at start. The returned Sampler now also carries them as gaps, so the source's own result says what it can't read.
  • Where the page says it: the board page's gap note still calls gaps(SYSTEM). That is the same list the production sampler is given, so I think it is the right surface there. It does not reflect custom paths, which only tests use.
  • Tests: a new test in test/boards-sampler.test.ts roots the sampler at a partly readable directory. It checks that only memory.current and loadavg appear in the log and in gaps, not cpu.stat or meminfo.
  • Unreached list: bun scripts/unreached.ts does not list src/boards/machine.ts, so it is off the list.

bun x tsc --noEmit is clean, scripts/gate.ts printed nothing, and the three boards test files pass (34 tests).

I did not run the repository's whole test suite here; the forge runs it on the push.

Approved

Earlier asks are met. The dead readMachine/Machine are gone, the re-export shim is gone, read is no longer exported, and readCpus and unreadable now carry the /proc/stat and gap logic. startSampler logs the unreadable series once at start and returns them as gaps. Tests: an unreadable root logs once across two ticks and the board query still answers; a partly readable root logs only the missing files; a fixture root is found through the machine source. machine.ts is off the unreached list and the sampler reaches it. I did not re-run tsc or the tests here; I judged this from the diff and the builder's report.

Next, two things I would do (non-blocking):

  1. Check that the header comment at the top of src/boards/machine.ts no longer mentions readMachine or a root-based read.
  2. Have the board page's gap note read sampler.gaps rather than calling gaps(SYSTEM) again, so the page and the log cannot drift apart.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs