Add server-side metrics ring buffer, seed dashboard charts from server history
Background task samples system (CPU/RAM/GPU) and per-target (FPS/timing) metrics every 1s into a 120-sample ring buffer (~2 min). New API endpoint GET /system/metrics-history returns the buffer. Dashboard charts now seed from server history on load instead of sessionStorage, surviving page refreshes. Also removes emoji from brightness source labels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,35 +1,19 @@
|
||||
/**
|
||||
* Performance charts — real-time CPU, RAM, GPU usage with Chart.js.
|
||||
* History is seeded from the server-side ring buffer on init.
|
||||
*/
|
||||
|
||||
import { API_BASE, getHeaders } from '../core/api.js';
|
||||
import { t } from '../core/i18n.js';
|
||||
import { dashboardPollInterval } from '../core/state.js';
|
||||
|
||||
const MAX_SAMPLES = 60;
|
||||
const STORAGE_KEY = 'perf_history';
|
||||
const MAX_SAMPLES = 120;
|
||||
|
||||
let _pollTimer = null;
|
||||
let _charts = {}; // { cpu: Chart, ram: Chart, gpu: Chart }
|
||||
let _history = _loadHistory();
|
||||
let _history = { cpu: [], ram: [], gpu: [] };
|
||||
let _hasGpu = null; // null = unknown, true/false after first fetch
|
||||
|
||||
function _loadHistory() {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(STORAGE_KEY);
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed.cpu && parsed.ram && parsed.gpu) return parsed;
|
||||
}
|
||||
} catch {}
|
||||
return { cpu: [], ram: [], gpu: [] };
|
||||
}
|
||||
|
||||
function _saveHistory() {
|
||||
try { sessionStorage.setItem(STORAGE_KEY, JSON.stringify(_history)); }
|
||||
catch {}
|
||||
}
|
||||
|
||||
/** Returns the static HTML for the perf section (canvas placeholders). */
|
||||
export function renderPerfSection() {
|
||||
return `<div class="perf-charts-grid">
|
||||
@@ -88,20 +72,41 @@ function _createChart(canvasId, color, fillColor) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Seed charts from server-side metrics history. */
|
||||
async function _seedFromServer() {
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE}/system/metrics-history`, { headers: getHeaders() });
|
||||
if (!resp.ok) return;
|
||||
const data = await resp.json();
|
||||
const samples = data.system || [];
|
||||
_history.cpu = samples.map(s => s.cpu).filter(v => v != null);
|
||||
_history.ram = samples.map(s => s.ram_pct).filter(v => v != null);
|
||||
_history.gpu = samples.map(s => s.gpu_util).filter(v => v != null);
|
||||
|
||||
// Detect GPU availability from history
|
||||
if (_history.gpu.length > 0) {
|
||||
_hasGpu = true;
|
||||
}
|
||||
|
||||
for (const key of ['cpu', 'ram', 'gpu']) {
|
||||
if (_charts[key] && _history[key].length > 0) {
|
||||
_charts[key].data.datasets[0].data = [..._history[key]];
|
||||
_charts[key].data.labels = _history[key].map(() => '');
|
||||
_charts[key].update();
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Silently ignore — charts will fill from polling
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize Chart.js instances on the already-mounted canvases. */
|
||||
export function initPerfCharts() {
|
||||
export async function initPerfCharts() {
|
||||
_destroyCharts();
|
||||
_charts.cpu = _createChart('perf-chart-cpu', '#2196F3', 'rgba(33,150,243,0.15)');
|
||||
_charts.ram = _createChart('perf-chart-ram', '#4CAF50', 'rgba(76,175,80,0.15)');
|
||||
_charts.gpu = _createChart('perf-chart-gpu', '#FF9800', 'rgba(255,152,0,0.15)');
|
||||
// Restore any existing history data into the freshly created charts
|
||||
for (const key of ['cpu', 'ram', 'gpu']) {
|
||||
if (_charts[key] && _history[key].length > 0) {
|
||||
_charts[key].data.datasets[0].data = [..._history[key]];
|
||||
_charts[key].data.labels = _history[key].map(() => '');
|
||||
_charts[key].update();
|
||||
}
|
||||
}
|
||||
await _seedFromServer();
|
||||
}
|
||||
|
||||
function _destroyCharts() {
|
||||
@@ -158,8 +163,6 @@ async function _fetchPerformance() {
|
||||
card.appendChild(noGpu);
|
||||
}
|
||||
}
|
||||
|
||||
_saveHistory();
|
||||
} catch {
|
||||
// Silently ignore fetch errors (e.g., network issues, tab hidden)
|
||||
}
|
||||
@@ -176,5 +179,4 @@ export function stopPerfPolling() {
|
||||
clearInterval(_pollTimer);
|
||||
_pollTimer = null;
|
||||
}
|
||||
_saveHistory();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user