Add historical sparklines to host cards
24h of snapshots were already being retained but never read. Adds a windowed query (last ~40 samples/host, one query total via ROW_NUMBER() OVER PARTITION BY, not N+1) embedded in the existing /api/hosts response, rendered as small hand-rolled SVG sparklines (cpu/mem/disk overlaid) -- no charting library needed at this scale. Closes #10. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -101,8 +101,35 @@ export function getLatestSnapshots(db: Database.Database): LatestRow[] {
|
||||
.all() as LatestRow[];
|
||||
}
|
||||
|
||||
// Old snapshots aren't useful yet (no charting in Phase 1) and would grow unbounded
|
||||
// on a poll-every-30s cadence, so trim anything older than the retention window.
|
||||
export interface HistoryPoint {
|
||||
host_id: string;
|
||||
ts: string;
|
||||
cpu_pct: number | null;
|
||||
mem_pct: number | null;
|
||||
disk_pct: number | null;
|
||||
}
|
||||
|
||||
// Last N samples per host (not a time window) — at the default 30s poll interval
|
||||
// that's ~20 minutes of trend, enough for a sparkline without needing to
|
||||
// downsample. A window function keeps this to one query instead of one per host.
|
||||
export function getRecentHistory(db: Database.Database, samplesPerHost = 40): HistoryPoint[] {
|
||||
return db
|
||||
.prepare(
|
||||
`
|
||||
SELECT host_id, ts, cpu_pct, mem_pct, disk_pct FROM (
|
||||
SELECT host_id, ts, cpu_pct, mem_pct, disk_pct,
|
||||
ROW_NUMBER() OVER (PARTITION BY host_id ORDER BY id DESC) AS rn
|
||||
FROM metric_snapshots
|
||||
)
|
||||
WHERE rn <= @samplesPerHost
|
||||
ORDER BY host_id, ts ASC
|
||||
`
|
||||
)
|
||||
.all({ samplesPerHost }) as HistoryPoint[];
|
||||
}
|
||||
|
||||
// Sparklines only ever read the last ~40 samples (see getRecentHistory), so
|
||||
// anything older than the retention window is just dead weight — trim it.
|
||||
export function pruneOldSnapshots(db: Database.Database, retentionHours: number): void {
|
||||
db.prepare(`DELETE FROM metric_snapshots WHERE ts < datetime('now', @cutoff)`).run({
|
||||
cutoff: `-${retentionHours} hours`,
|
||||
|
||||
Reference in New Issue
Block a user