Files
werkator/docs/prs/2026-09-15-PR#69-what-waited-for-the-disk.md
5e4209553a
werkator build succeeded after 01:49
werkator/deploy build succeeded after 00:07
feat(metrics): collect the time spent waiting for storage (#69) (#69)
The third of the kernel's pressure-stall figures, /proc/pressure/io,
beside the two already sampled. It is the one resource a build spends
its time on that neither the processor nor the memory figure explains.

Collected, kept in the history, shown on the System page and the home
rail -- and read by nothing: no health verdict, no sizing advice, no new
threshold. That is RFC 0004's order, the one oomKills was added under:
the series has to exist before anyone can say what a number means. On a
shared hive the disks are what is shared hardest, so the figure will say
as much about the neighbours as about this instance until it has been
watched for a while.

Also fills the placeholder in PR#65's doc with the production run it
promised: the journal of the first deployment in which the instance
ended itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #69
2026-09-15 13:55:36 +02:00

4.8 KiB

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

  • RFC 0004 — a resource is sized by whether something waited; collect first, judge later
  • PR#67 — the other half of "what did this cost"

The Problem

Werkator collects two of the kernel's three pressure-stall figures: /proc/pressure/cpu and /proc/pressure/memory. The third, /proc/pressure/io, says how much of the last minute something waited for storage, and it is the one resource a build spends its time on that neither of the other two can explain.

RFC 0004 settled how a resource is judged — by whether anything waited for it, never by how full it is — and it settled the order in which a new figure is introduced: collect it first, so that the data exists by the time anybody wants to read it. oomKills was added that way, and this is the same move for storage.

Non-Goals

  • No health verdict and no sizing advice reads the figure. That is the point of the order, not an omission.
  • No new threshold, no new constant. There is nothing yet to set one from.
  • Nothing about per-build IO. This is a machine measurement, like the other two; what a build cost is PR#67's question.

The Scenarios

Feature: storage pressure

Background

  • PSI reports some and full per resource; some means at least one task stalled, full means every runnable task did.
  • some avg60 is what the other two figures use: the earlier signal, and the one comparable across the three.

Scenario#69.01: The figure is sampled beside the other two

So that waiting for storage is visible at all.

  • Given a host whose /proc/pressure/io reports some avg60=3.40
  • When the collector samples
  • Then the snapshot's storage pressure is 3.40
  • And given a host without the file
  • Then it is null, and no other metric is affected
Verified by

Scenario#69.02: It is kept, not just shown

So that the history exists by the time somebody asks what the number means.

  • Given the same host
  • When the collector samples
  • Then the figure is recorded in the sample history under its own key
Verified by

Scenario#69.03: It appears where the other two do

So that it is read in the same breath as them.

  • Given a snapshot carrying all three figures
  • When the System view is built
  • Then it carries a Disk pressure tile between RAM pressure and Swap
Verified by

The Solution

One more readPressure call, one more field on the snapshot, one more key in MetricsHistory.BASE_KEYS, and a tile beside the other two on the System page and the home rail. The history tiers carry the union of what was sampled, so a state file written before this simply has no such column and the series starts where the sampling did — the same property oomKills relies on.

Nothing reads the figure. SystemHealth.assess and CapacitySizing.of are untouched.

Open Questions

  • On a shared host PSI measures the whole machine, and the disks are what is shared hardest. The figure therefore says "something on this machine waited for storage", not "Werkator waited" — more so than for the processor and memory figures, which already carry that caveat. Whether it can be made to say anything about this instance alone is the question the collected history is meant to answer.

Additional Changes

  • The PR-doc of PR#65 gets the production run it was left a placeholder for: the journal of the first deployment in which the instance ended itself (762afb5, v1.16.1).

Prerequisite PRs

  • None beyond what is on main.

Follow-up PRs

  • Whether any of the three pressure figures should reach the health verdict or the sizing, once there is a month of history to look at.