feat(T3.3): cpu load readout + lifeguard health score

rpc.rs: Add read_cpu_load_1m() (/proc/loadavg), compute_health_score()
(hot>90% +1, fs>90% +1, load>4 +1, failed timers +1), expose both in
DashboardStatusReply. NodeStatusV2 and api.ts propagated.

NodeCard: cpu load row in facts grid (amber when >4), healthOf() now
driven by server-side health_score (>= 3 → err, 1-2 → warn) with
client-side fs/timer fallback for older daemons.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-23 17:45:25 +00:00
co-authored by Claude Sonnet 4.6
parent 70ad863006
commit 01ba85b2dd
4 changed files with 88 additions and 0 deletions
+10
View File
@@ -368,6 +368,12 @@ pub struct NodeStatusV2 {
/// Unix timestamp (seconds) when the peer's daemon last started.
#[serde(default)]
pub daemon_started_unix: Option<u64>,
/// 1-minute load average. None on non-Linux or when the peer is offline.
#[serde(default)]
pub cpu_load_1m: Option<f32>,
/// Lifeguard-style health score: 0 = healthy, higher = stressed (T3.3).
#[serde(default)]
pub health_score: u8,
/// `true` when the aggregator successfully talked to the peer;
/// `false` when the RPC failed. Frontend uses this to badge the
/// card as offline.
@@ -395,6 +401,8 @@ impl NodeStatusV2 {
cache: r.cache,
timers: r.timers,
daemon_started_unix: r.daemon_started_unix,
cpu_load_1m: r.cpu_load_1m,
health_score: r.health_score,
online: true,
error: None,
};
@@ -421,6 +429,8 @@ impl NodeStatusV2 {
cache: None,
timers: Vec::new(),
daemon_started_unix: None,
cpu_load_1m: None,
health_score: 0,
online: false,
error: Some(e),
}