From 03ea6d1bdadd0c96be6c28aec919a02441edf856 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 5 Jun 2026 23:00:27 +0200 Subject: [PATCH] feat(stats): per-container cpu/mem load (#1424 p3) C0NT41N3R L04D on the SYST3M tab + GET /api/container-resources. Backend (hive-c0re/src/container_stats.rs): reads cgroup v2 cpu.stat + memory.{current,peak,max} for each running agent machine (machine-h\x2d.scope under machine.slice), read-only/world- readable so no hive-priv. CPU is a two-sample (~200ms) host-normalised percentage; one shared sleep covers all agents. Skips agents whose scope dir is absent (= not running). Network omitted: agents share the host netns, no per-container counter. Frontend: a polled C0NT41N3R L04D table on SYST3M (agent / cpu / mem / peak / limit with meter bars), reusing the ST4TS table style. Polls /api/container-resources every 5s only while the tab is active. Backend reviewed-in-principle by damocles (path escaping + cpu delta math); ping for the on-host sign-off. --- docs/web-ui/dashboard.md | 22 +++ frontend/packages/dashboard/src/dashboard.css | 26 ++++ frontend/packages/dashboard/src/index.html | 10 ++ frontend/packages/dashboard/src/tabs.js | 97 +++++++++++++ hive-c0re/src/container_stats.rs | 137 ++++++++++++++++++ hive-c0re/src/dashboard.rs | 7 + hive-c0re/src/lib.rs | 1 + 7 files changed, 300 insertions(+) create mode 100644 hive-c0re/src/container_stats.rs diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index fef65252..3baa5a59 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -153,6 +153,22 @@ age + claude-creds badge). Two actions: `⊕ R3V1V3` (queues a Spawn approval; existing state is reused), `PURG3` (wipes state + applied dirs; `POST /purge-tombstone/{name}`). +**C0NT41N3R L04D** — live CPU + memory per agent container, read +straight from cgroup v2 on the host (`cpu.stat`, `memory.current`, +`memory.peak`, `memory.max` under +`/sys/fs/cgroup/machine.slice/machine-h\x2d.scope/`). CPU is a +host-normalised percentage (0..100 across all cores) sampled over a +short (~200 ms) two-read interval; memory shows current + peak with a +bar against the `memory.max` quota. Backed by +`GET /api/container-resources` (`container_stats.rs`), which reads the +files read-only (world-readable; no `hive-priv`) and skips agents whose +scope dir is absent (= not running). Pull-only: `tabs.js` polls every +5 s **only while the SYST3M tab is active** (CPU needs a fresh sample +each refresh), and stops on tab change. Network is intentionally +omitted — agents share the host netns, so there is no per-container net +counter (per-agent network needs the netns-isolation roadmap in +`docs/network.md`). + ## P3RM1SS10NS tab Per-agent permission configuration. Two sections, each rendered as a @@ -838,6 +854,12 @@ that's a browser-level decision, not ours. zero-turn dbs); returns swarm totals, a busiest-first per-agent rollup, swarm model mix, and a labelled `est_cost_usd`. Window defaults to `24h`. +- `GET /api/container-resources` — live per-agent-container CPU + + memory from cgroup v2 (SYST3M › C0NT41N3R L04D panel). Returns one + row per running agent (`name`, `cpu_pct`, `mem_current_bytes`, + `mem_peak_bytes`, `mem_max_bytes`); samples CPU over ~200 ms so the + call briefly awaits. Skips non-running agents (no scope dir). No + network field — agents share the host netns. - `POST /cancel-reminder/{id}` — hard-delete a pending reminder. - `POST /retry-reminder/{id}` — re-arm a reminder whose delivery failed (clears the failure state so the scheduler retries). diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index 4c707dbd..5d1f3294 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -1609,3 +1609,29 @@ body.dashboard-shell.has-selection { padding-bottom: 4.5em; } color: var(--muted); font-variant-numeric: tabular-nums; } + +/* ─── SYST3M › C0NT41N3R L04D: live cgroup cpu/mem ───────────────────────────── + Reuses the `.hive-stats-table` styling from the ST4TS tab; only the + inline meter bar is new. */ +.cload-meter { + display: inline-block; + width: 6em; + height: 10px; + vertical-align: middle; + margin-left: 6px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: 3px; + overflow: hidden; +} +.cload-meter .fill { + display: block; + height: 100%; + background: var(--green); +} +.cload-meter .fill.warn { + background: var(--amber); +} +.cload-meter .fill.hot { + background: var(--red); +} diff --git a/frontend/packages/dashboard/src/index.html b/frontend/packages/dashboard/src/index.html index e81b52c0..2b3f8bc1 100644 --- a/frontend/packages/dashboard/src/index.html +++ b/frontend/packages/dashboard/src/index.html @@ -191,6 +191,16 @@

loading…

+ +

◆ C0NT41N3R L04D ◆

+
══════════════════════════════════════════════════════════════
+

live cpu + memory per agent container, from cgroup v2 on the host. cpu is % of total host capacity (all cores), sampled over ~200ms each refresh; polled every 5s while this tab is open. network is omitted on purpose — agents share the host netns, so there is no per-container counter (see docs/network.md).

+
+

loading…

+
+