Repository navigation
feat(history): record load, memory, disk and usage history and chart it - #1236
Open
karlitschek wants to merge 4 commits into
Open
karlitschek wants to merge 4 commits into
karlitschek wants to merge 4 commits into
Conversation
karlitschek
force-pushed
the
feat/os-status-collector
branch
from
October 25, 2026 19:19
6d327c2 to
34014ec
Compare
karlitschek
force-pushed
the
feat/history
branch
from
October 25, 2026 19:28
ffc0000 to
e4b3315
Compare
karlitschek
force-pushed
the
feat/history
branch
2 times, most recently
from
October 25, 2026 19:45
bcff3dc to
cbaeb33
Compare
karlitschek
marked this pull request as ready for review
October 25, 2026 20:25
karlitschek
force-pushed
the
feat/history
branch
from
October 25, 2026 20:40
cbaeb33 to
228ec4d
Compare
Everything on the Status page is a snapshot: the load and memory charts keep two minutes, and only in the browser. Whether the server was slow at ten o'clock or how fast the disk fills cannot be answered. A background job now samples every five minutes what a cron process sees the same way the web server does: load average, memory and swap, free and total space of the data directory's file system, active users (5 min, 24 h), the file count the storage job already caches and the database size, measured at most once an hour. PHP-FPM and OPcache are left out: the CLI process has its own OPcache and is no FPM worker. The same job turns the samples into hourly and daily rows (averages, plus peaks for load, memory and active users) and expires rows after 48 hours, 30 days and a year, all configurable. Both are computed from the five-minute samples, recomputing a bucket only while all of its samples still exist, so reruns change nothing and a paused cron cannot shrink a finished bucket. The job is due every four minutes and keeps one sample per five-minute slot, as TimedJob runs only once strictly more than the interval has passed and a five-minute interval would skip every other cron run. The table is wide, one column per metric: a chart reads at most a few hundred rows of one resolution with a single index range scan, and a rollup is one pass over the rows. A narrow (metric, value) table would need about 15 times the rows and index entries and a pivot for every chart; its only gain, adding a metric without a migration, is rare. The unique index on resolution, bucket start and node serves chart reads, expiry and duplicate protection. The bucket start is stored because rollup rows are written long after their bucket; the node name keeps several web servers' samples apart. An admin-only endpoint returns one range (24 h, 7 d, 30 d, 1 y) at the finest resolution kept for all of it, at most 1000 points. The table is the app's first migration, so the version goes to 8.0.0-dev.2. Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Frank Karlitschek <karlitschek@users.noreply.github.com>
The load and memory charts get a range switch: Live keeps today's two-minute chart and its polling untouched, while 24 h, 7 days, 30 days and 1 year load the stored history. A new "Disk usage over time" chart shows the data directory's file system, used against its size. Points sit on a regular time axis, so time without samples (a paused cron) shows as a gap rather than a line drawn across it, and a lone sample between two gaps is drawn as a dot. The average line uses the five-minute load average, which covers a whole sample; hourly and daily points add the peak as a dashed line. Daily points are UTC days and are labelled in UTC. Each chart has an accessible name and a sentence below it with the average and peak (or, for disk, the change over the range), which also serves as its text alternative. Colours come from the theme, so the charts follow dark mode. Before the first sample the chart says that history collection has started. Charts showing the same range share one request, reused for a minute. Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Frank Karlitschek <karlitschek@users.noreply.github.com>
The Load and Memory boxes use the shared infobox, which lays out its children in a row, so the range switch sat beside the chart and squeezed it. A modifier stacks the switch above the chart, and the switch keeps its own width instead of stretching. Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Frank Karlitschek <karlitschek@users.noreply.github.com>
Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Frank Karlitschek <karlitschek@users.noreply.github.com>
karlitschek
force-pushed
the
feat/history
branch
from
October 26, 2026 10:59
228ec4d to
f9c8130
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Based on
feat/os-status-collector(#1214).AI disclosure: this change was written with Claude Code (claude-opus-5-5) and is to be reviewed by the author before it leaves draft; every commit carries an
Assisted-bytrailer.🤖 Generated with Claude Code