diff --git a/db/queries/metrics.sql b/db/queries/metrics.sql index 6cd805f..43171e5 100644 --- a/db/queries/metrics.sql +++ b/db/queries/metrics.sql @@ -2,12 +2,17 @@ INSERT INTO sandbox_metrics_snapshots (team_id, running_count, vcpus_reserved, memory_mb_reserved) VALUES ($1, $2, $3, $4); --- name: GetCurrentMetrics :one -SELECT running_count, vcpus_reserved, memory_mb_reserved, sampled_at -FROM sandbox_metrics_snapshots -WHERE team_id = $1 -ORDER BY sampled_at DESC -LIMIT 1; +-- name: GetLiveMetrics :one +-- Reads directly from sandboxes for accurate real-time current values. +-- CPU reserved = running + starting only (paused VMs release CPU). +-- RAM reserved = running + starting + ceil(paused/2) (capacity held for resume). +SELECT + (COUNT(*) FILTER (WHERE status IN ('running', 'starting')))::INTEGER AS running_count, + (COALESCE(SUM(vcpus) FILTER (WHERE status IN ('running', 'starting')), 0))::INTEGER AS vcpus_reserved, + (COALESCE(SUM(memory_mb) FILTER (WHERE status IN ('running', 'starting')), 0) + + CEIL(COALESCE(SUM(memory_mb) FILTER (WHERE status = 'paused'), 0)::NUMERIC / 2))::INTEGER AS memory_mb_reserved +FROM sandboxes +WHERE team_id = $1; -- name: GetPeakMetrics :one SELECT @@ -24,12 +29,12 @@ WHERE sampled_at < NOW() - INTERVAL '60 days'; -- name: SampleSandboxMetrics :many -- Aggregates per-team resource usage from the live sandboxes table. --- paused sandboxes count at 50% (ceil) for capacity reservation. +-- CPU reserved = running + starting only (paused VMs release CPU). +-- RAM reserved = running + starting + ceil(paused/2) (capacity held for resume). SELECT team_id, (COUNT(*) FILTER (WHERE status IN ('running', 'starting')))::INTEGER AS running_count, - (COALESCE(SUM(vcpus) FILTER (WHERE status IN ('running', 'starting')), 0) - + CEIL(COALESCE(SUM(vcpus) FILTER (WHERE status = 'paused'), 0)::NUMERIC / 2))::INTEGER AS vcpus_reserved, + (COALESCE(SUM(vcpus) FILTER (WHERE status IN ('running', 'starting')), 0))::INTEGER AS vcpus_reserved, (COALESCE(SUM(memory_mb) FILTER (WHERE status IN ('running', 'starting')), 0) + CEIL(COALESCE(SUM(memory_mb) FILTER (WHERE status = 'paused'), 0)::NUMERIC / 2))::INTEGER AS memory_mb_reserved FROM sandboxes diff --git a/frontend/src/lib/components/StatsPanel.svelte b/frontend/src/lib/components/StatsPanel.svelte index 948e520..f067447 100644 --- a/frontend/src/lib/components/StatsPanel.svelte +++ b/frontend/src/lib/components/StatsPanel.svelte @@ -85,8 +85,10 @@ // Chart colors (resolved from CSS vars, must match app.css) const C_ACCENT = '#5e8c58'; const C_ACCENT_FILL = 'rgba(94,140,88,0.08)'; + const C_BLUE = '#5a9fd4'; + const C_BLUE_FILL = 'rgba(90,159,212,0.07)'; const C_AMBER = '#d4a73c'; - const C_AMBER_FILL = 'rgba(212,167,60,0.06)'; + const C_AMBER_FILL = 'rgba(212,167,60,0.07)'; const C_GRID = 'rgba(255,255,255,0.04)'; const C_TICK = '#454340'; const FONT_MONO = "'JetBrains Mono', monospace"; @@ -160,14 +162,14 @@ { label: 'vCPUs', data: [], - borderColor: C_ACCENT, - backgroundColor: C_ACCENT_FILL, + borderColor: C_BLUE, + backgroundColor: C_BLUE_FILL, borderWidth: 1.5, fill: false, tension: 0, pointRadius: 0, pointHoverRadius: 4, - pointHoverBackgroundColor: C_ACCENT, + pointHoverBackgroundColor: C_BLUE, yAxisID: 'y', }, { @@ -248,148 +250,171 @@ } -
Resource consumption across all capsules.
+