Files
werkator/docs/prs/2026-10-10-PR#147-oom-kills-tile.md
claude-code ace602454b
werkator build succeeded after 02:42
werkator/deploy build succeeded after 00:08
OOM kills tile, System page tiles in two rows of four (v1.40.0) (#147)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-10 22:56:24 +02:00

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

Problem

PR#146 put the seven tiles of the System page into one row. They are narrow there, so their values had to shrink to 16 px. Two rows would give them room, but seven tiles cannot fill two rows evenly.

The OOM kills are sampled since RFC 0004, but no page shows them. Their aggregated buckets also held the average per sample, not the count, so no range could be added up.

Non-Goals

  • The OOM kills are shown, not judged: the counter is machine-wide, so on a shared hive it counts the neighbours' kills too.
  • The cards keep their one row from PR#146.
  • The home rail keeps its five tiles.

Specification

Feature: OOM kills tile, tiles in full rows

Scenario#147.01: The OOM kills are summed per bucket

So that a minute and a quarter hour hold the kills that happened in them, not the kills per sample.

  • Given one OOM kill per minute for an hour
  • When the history aggregates the samples into minutes and quarter hours
  • Then every minute holds 1 and every quarter hour 15
  • And a level such as cpuUsed is still averaged
Verified by

Scenario#147.02: A range adds up its OOM kills

So that the tile can say how many kills the selected range holds, and n/a where the series was not yet sampled.

  • Given one OOM kill per minute for an hour, a range without the series, and a quiet range
  • When the total of each range is computed
  • Then it is 60, no total, and 0
Verified by

Scenario#147.03: The history endpoint serves the OOM kills as a total, not as an average

So that the page reads the count of the range, and no mean of bucket sums whose unit changes with the range.

  • Given samples with 0, 2 and 1 OOM kills
  • When GET /api/system/history is asked for 1h and for 24h
  • Then totals.oomKills is 3 in both, and averages has no oomKills
  • And for a range without the series totals.oomKills is null
Verified by

Scenario#147.04: The server renders the OOM kills tile without a count

So that the tile never shows the count of a range other than the selected one; werkator.js fills in the count of the selected range.

  • Given a snapshot of the machine
  • When the server renders the System page
  • Then the OOM kills tile reads n/a and in the last 1 h
  • And the tile has no colour
Verified by
  • UiViewsUnitTest — Scenario#147.04
  • the count filled in by werkator.js for the 1 h and 24 h ranges, checked by hand in the browser

Scenario#147.05: The tiles stand in two full rows of four

So that the tiles look tidy and have room for their values.

  • Given the System page with its eight tiles
  • When it is shown on a screen wider than 680 px
  • Then Load, CPU pressure, RAM pressure and OOM kills form the first row, Disk pressure, Repositories, Builds and PR targets the second
  • And on a phone they stand in four rows of two
Verified by
  • UiViewsUnitTest — Scenario#147.05, and the updated Scenario#27.05, Scenario#101.01 and Scenario#146.03
  • the layout checked by hand in the browser at 1280 and 390 px

Solution

  • MetricsHistory.COUNTED_KEYS names the series that count events, so far oomKills; HistoryTier.aggregate sums them instead of averaging. The bucket's field is points now, not averages, since it holds either. Every OOM kills point recorded on mih09 until now is 0, so no stored bucket changes its meaning.
  • HistoryTotals.of adds up a counted series over a range; GET /api/system/history serves it as totals. HistoryAverages leaves the counted series out: a mean of bucket sums would be kills per minute in one range and per quarter hour in the next.
  • The tile row is now processor and memory — Load, CPU pressure, RAM pressure, OOM kills — and the second row the disk and the builds.
  • The server renders the OOM kills tile as n/a, since it knows no range; werkator.js fills in the count and the range label with every history fetch, like the peak line under a card.
  • .tiles is a grid of four columns, two up to 680 px; the 16 px tile values of PR#146 are 18 px again.

Additional Changes

  • The architecture skill describes the counted series and the tile rows; its system-metrics paragraph has one sentence per line now.
  • Version 1.40.0 with its release note.

Prerequisite PRs

  • PR#146: the swap-out card and the one-row layout this PR changes.