Files
werkator/docs/prs/2026-10-10-PR#146-swap-out-card.md
claude-code 41da4413b5
werkator build succeeded after 02:09
werkator/deploy build succeeded after 00:08
Swap-out card with history on the System page, cards and tiles in one row (v1.39.0) (#146)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-10 16:07:40 +02:00

7.6 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.

The Problem

The System page showed swap as a small tile: the swap in use, and the swap traffic over five minutes. The tile had no history, so a night of swapping was invisible the next morning. The traffic counted pages swapped in and out. On Hostsharing only swap-out costs: a page written to the swap changes a block that DRBD sends to the mirror and the backup stores. A page read back changes nothing. The swap in use matters less than both: pages that stay in the swap cost nothing.

A fifth card did not fit the row of four, and the eight tiles already broke into a second row at 1180 px.

Non-Goals

  • No RAM sizing rule on swap-out yet; the series is recorded first, as RFC 0004 asks.
  • The health verdict is unchanged; it still names half the swap in use as pressure.
  • The page stays 1180 px wide; the cards and tiles get narrower instead.
  • The swapTraffic series of PR#102 is not migrated into swapOut: it counted the reads as well, so its numbers mean something else.

The Scenarios

Feature: Swap-out as a card with history

Scenario#146.01: Swap-out counts only the pages written to the swap

So that the card shows what costs the mirror and the backup, not what is read back.

  • Given the pswpin and pswpout counters of /proc/vmstat
  • When samples are taken a minute apart, ten minutes apart, and after the counter went backwards
  • Then the swap-out is null for a single sample, the pages written per second in MiB/s, zero once the burst left the window, and null again after a reboot
  • And pswpin changes none of these numbers
Verified by

Scenario#146.02: Swap-out turns the swap readings amber and red, the occupancy only amber

So that only what costs the mirror can raise the alarm.

  • Given snapshots with swap-out below, at the warning, and at the critical threshold, and with a lot of swap in use but no swap-out
  • When the swap level is judged
  • Then it is calm, amber, and red, and amber for the occupancy alone
  • And a threshold set to null never fires
  • And the home rail's tile reads Swap-out 1.25 MiB/s, with the swap in use as its tooltip
Verified by

Scenario#146.03: The swap-out card stands between RAM and the disks, scaled against the critical threshold

So that swap-out has a history and a peak like CPU, RAM and the disks, and its bar says how close it is to red.

  • Given a host with swap and one monitored disk
  • When the System page is rendered
  • Then the cards are CPU, RAM, Swap-out and the disk, in this order
  • And the swap-out card reads 0.25 MiB/s, its detail line 0.10 of 4.00 GiB in use, and its bar stands at 25 % of the critical 1.0 MiB/s
  • And without a critical threshold the warning scales the bar, and a swap-out above it fills the bar, no more
  • And before two samples the card reads n/a without a unit
  • And the swap tile is gone, and a host without swap has no swap-out card
Verified by
  • UiViewsUnitTest — Scenario#146.03, and the updated Scenario#27.05 and Scenario#101.01

Scenario#146.04: The card says why the swap in use makes it amber

So that an amber card with 0.00 MiB/s on it does not look like a mistake.

  • Given more swap in use than metrics.swapWarningGib, or half the swap in use
  • When the System page is rendered
  • Then the swap-out card is amber with the note more than 0.50 GiB in use or half the swap or more in use
  • And the tiles and the health verdict stay calm, as before
Verified by

Scenario#146.05: The thresholds are renamed, the old names still read

So that the key says what it judges, and a host file written for PR#102 keeps working.

  • Given an instance file without the keys, with swapOutWarningMibPerSecond and swapOutCriticalMibPerSecond, and with the old swapTraffic… names
  • When the configuration is loaded
  • Then the thresholds are 0.1 and 1.0, or what the file says under either name, and null turns one off
  • And where a file has both names, the new one wins
  • And the old names log a warning once per file
Verified by

Scenario#146.06: The swap-out's peak is judged against the thresholds

So that the peak line under the card says watch or critical like the card itself.

  • Given a history tier with swap-out averages and maxima
  • When the peaks are computed
  • Then the swap-out's peak is the highest maximum with its time, has no total, and its level follows today's thresholds
  • And a tier without swap-out values has no swap-out peak
Verified by

Scenario#146.07: The cards and the tiles each stand in one row on a desktop screen

So that the whole machine is visible at a glance, however many disks a host shows.

  • Given a window at least 1100 px wide
  • When the System page shows five cards and seven tiles
  • Then the cards stand in one row and the tiles in another
  • And below 1100 px they wrap as before
Verified by
  • checked by hand in the browser at 1280, 1100 and 900 px against a demo instance with two disks

The Solution

  • SystemMetricsCollector reads only pswpout now; the swap-out goes into the snapshot as swapOutMibPerSecond and into the history as the series swapOut.
  • metrics.swapOutWarningMibPerSecond (0.1) and …CriticalMibPerSecond (1.0) replace the swapTraffic… keys. ConfigLoader reads the old names under the new ones on the raw map of every layer, like the bwrap section, with a warning.
  • GaugeView.swapOut builds the card: the value in MiB/s with the unit in small type (valueUnit), the bar against the critical threshold, the swap in use as detail line, and the occupancy as note. It stands between RAM and the disks, so the memory cards stand together.
  • HistoryPeaks adds the swap-out's peak, judged by SystemHealth.swapOutLevel.
  • werkator.js mirrors it: renderSwapOutCard, and drawSpark takes limits for a rate — the dashed lines at the two thresholds, the colours by them, and the critical line at 90 % of the height as for a total. The average beside the value is the bare number, since the value already carries the unit.
  • The home rail keeps swap-out as a tile, not a row: Swap-out and 0.02 MiB/s fit neither the label nor the value column of a row.
  • From 1100 px window width the cards and the tiles each flow into one row (grid-auto-flow: column); the tile values are 16 px there, since 0 of 1 running breaks at 18 px. At 1100 px five cards are 196 px wide and seven tiles 139 px.

Additional Changes

  • docs/configuration.md, the init template and the architecture skill describe the new keys and the card.
  • Version 1.39.0 with its release note.

Follow-up PRs

  • A RAM sizing rule on swap-out, once a few weeks of the swapOut series show what its numbers mean.