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

Boards, step 5a: readMachine(root) turns cgroup and /proc files into one CPU and memory point #2370

Merged opened this

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

Merged

`readMachine(root)` is added in `src/boards/machine.ts`. It turns cgroup and `/proc` files into one point, or a reason when nothing is readable. The new tests pass and `tsc` is clean. I did not run the full check; the forge runs that on this push.

shipped merged

opened this

readMachine(root) is added in src/boards/machine.ts. It turns cgroup and /proc files into one point, or a reason when nothing is readable. The new tests pass and tsc is clean. I did not run the full check; the forge runs that on this push.

  • Layout: root is a filesystem root, / in production. The function reads <root>/sys/fs/cgroup/{cpu.stat,memory.current} and <root>/proc/{meminfo,loadavg}.
  • Point: it returns { ok: true, point: { cpuUsec, memoryBytes, nodeMemoryBytes, load } }. Each field is null when its file is missing or unparseable. cpuUsec is the cumulative usage_usec, so a CPU rate needs two points.
  • Reason: if every field is null it returns { ok: false, reason }. A thrown error is caught and returned as a reason too, so it never throws.
  • Parsers: it reuses the parsers already in src/boards/sampler.ts (parseCpuStat, parseMeminfo, parseLoadavg), so there are no new dependencies. There is no timer and no storage.
  • Tests: test/boards-machine.test.ts builds fake files under a temp dir. It covers a full point, a cgroup-only point, a garbled memory.current, a missing directory, and an empty root. It joins the gate automatically because the gate is derived from the test files.

I left out turning two points into a rate and wiring this into the sampler. The sampler keeps its own readCounters, which also reads /proc/stat per CPU and the temperatures, and I did not touch it.

🤖 Generated with Claude Code

Closes #2343

commented

readMachine(root) is added in src/boards/machine.ts. It turns cgroup and /proc files into one point, or a reason when nothing is readable. The new tests pass and tsc is clean. I did not run the full check; the forge runs that on this push.

  • Layout: root is a filesystem root, / in production. The function reads <root>/sys/fs/cgroup/{cpu.stat,memory.current} and <root>/proc/{meminfo,loadavg}.
  • Point: it returns { ok: true, point: { cpuUsec, memoryBytes, nodeMemoryBytes, load } }. Each field is null when its file is missing or unparseable. cpuUsec is the cumulative usage_usec, so a CPU rate needs two points.
  • Reason: if every field is null it returns { ok: false, reason }. A thrown error is caught and returned as a reason too, so it never throws.
  • Parsers: it reuses the parsers already in src/boards/sampler.ts (parseCpuStat, parseMeminfo, parseLoadavg), so there are no new dependencies. There is no timer and no storage.
  • Tests: test/boards-machine.test.ts builds fake files under a temp dir. It covers a full point, a cgroup-only point, a garbled memory.current, a missing directory, and an empty root. It joins the gate automatically because the gate is derived from the test files.

I left out turning two points into a rate and wiring this into the sampler. The sampler keeps its own readCounters, which also reads /proc/stat per CPU and the temperatures, and I did not touch it.

🤖 Generated with Claude Code

Approved

Approved. readMachine(root) is a pure, never-throwing reader that reuses the sampler parsers (checked: parseCpuStat, parseMeminfo and parseLoadavg return null on bad input). The five tests cover a full point, a cgroup-only point, a garbled file, a missing dir and an empty root, and they would fail without the module. No new dependency, no input from users, nothing to escape. It adds no page, so the preview shows no change; that is fine for a step-5a building block.

Two things I would do next:

  1. Wire it in (5b) or delete it. Nothing calls it yet, and sampler.ts readCounters already has its own read() and a memory.current parse, so you now have two readers of the same files. Have one call the other.
  2. Put the memory.current check (digits only, else null) into sampler.ts as a parseMemoryCurrent next to the other parsers, so both readers share it and it gets its own test.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs