Tap each node's Beszel metrics (GPU/temps/disk-IO/network/per-container — beyond
our basic heartbeat) by reading the workspace's Beszel hub. The agents run in
WS-only mode with no locally-readable socket, so (per the de-risk) the server taps
the hub's PocketBase API instead of the daemon reading agents — no daemon changes.
- migrations: workspace_beszel (BYO hub URL + login, server-side only, mirrors the
Tailscale BYO pattern) + node_metrics (latest scalar columns + JSONB blob).
- cm-db: repo/fleet_beszel.rs, repo/node_metrics.rs; nodes SELECT joins node_metrics
(gpu_pct/temp_max surfaced on node_json for the live cards).
- cm-api: beszel.rs client (auth-with-password, poll `systems`, map to nodes by
hostname, upsert metrics) + a 15s spawn_poller; routes/beszel.rs (connect/status/
disconnect + GET /api/nodes/{id}/metrics with history proxied live from the hub).
- frontend: HostCard gains a GPU/temp readout + a Monitor button; NodeMonitor is a
full-width per-node page (current panel + CPU/mem/GPU/temp/net/disk charts from the
hub's 1m history); a "Beszel monitoring" connect form in the Local view.
Reachability confirmed: gw-04 → the hub over the tailnet (100.123.224.84:8090). Needs
the user to connect their hub login to activate the poller.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
22 lines
989 B
SQL
22 lines
989 B
SQL
-- Rich per-node metrics tapped from the workspace's Beszel hub (beyond the basic
|
|
-- heartbeat health). One latest snapshot per node: queryable scalar columns drive
|
|
-- the fleet card widgets + the rules engine; the JSONB `data` holds the full
|
|
-- snapshot (per-core CPU, per-GPU, per-interface network, per-container) for the
|
|
-- per-node monitor page. History for charts is proxied live from the hub.
|
|
CREATE TABLE node_metrics (
|
|
node_id UUID PRIMARY KEY REFERENCES nodes (id) ON DELETE CASCADE,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
cpu_pct DOUBLE PRECISION,
|
|
mem_pct DOUBLE PRECISION,
|
|
disk_pct DOUBLE PRECISION,
|
|
gpu_pct DOUBLE PRECISION,
|
|
temp_max DOUBLE PRECISION,
|
|
net_sent_ps BIGINT,
|
|
net_recv_ps BIGINT,
|
|
disk_read_ps BIGINT,
|
|
disk_write_ps BIGINT,
|
|
load1 DOUBLE PRECISION,
|
|
container_count INTEGER,
|
|
data JSONB NOT NULL DEFAULT '{}'::jsonb
|
|
);
|