From 0da10d51392df6bca842c3e45b8515b32d3ac140 Mon Sep 17 00:00:00 2001 From: MCHost Date: Mon, 14 Jul 2025 23:31:42 -0400 Subject: [PATCH] Add Jump Node RAM Graph --- status.html | 55 +++++++++++++++++++++++++++++++++++++++++++++++- system-status.js | 3 ++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/status.html b/status.html index b021c99..bc3587a 100644 --- a/status.html +++ b/status.html @@ -265,6 +265,10 @@

CPU Usage

+
+

RAM Usage

+ +

Network Traffic

@@ -300,6 +304,7 @@ let jumpDiskHistory = []; let hostLoadHistory = []; let jumpLoadHistory = []; + let jumpRamHistory = []; const MAX_POINTS = 30; // Match to points in API query const SMOOTHING_WINDOW = 3; @@ -342,6 +347,7 @@ disk: document.getElementById('disk-chart'), load: document.getElementById('load-chart'), jumpCpu: document.getElementById('jump-cpu-chart'), + jumpRam: document.getElementById('jump-ram-chart'), jumpNet: document.getElementById('jump-net-chart'), jumpDisk: document.getElementById('jump-disk-chart'), jumpLoad: document.getElementById('jump-load-chart') @@ -526,6 +532,27 @@ } }); + charts.jumpRam = new Chart(canvases.jumpRam.getContext('2d'), { + type: 'line', + data: { + labels: [], + datasets: [ + { label: 'Used (MB)', data: [], borderColor: '#38bdf8', borderWidth: 2, fill: false, tension: 0 }, + { label: 'Free (MB)', data: [], borderColor: '#fb7185', borderWidth: 2, fill: false, tension: 0 } + ] + }, + options: { + ...commonOptions, + scales: { + y: { + ...commonOptions.scales.y, + title: { display: true, text: 'Memory (MB)', color: '#e5e7eb' } + }, + x: commonOptions.scales.x + } + } + }); + charts.jumpNet = new Chart(canvases.jumpNet.getContext('2d'), { type: 'bar', data: { @@ -625,6 +652,7 @@ const jumpNoData = document.getElementById('jump-no-data'); const hasJumpData = data.jumpNode && ( (data.jumpNode.cpu && data.jumpNode.cpu.length > 0) || + (data.jumpNode.ram && data.jumpNode.ram.length > 0) || (data.jumpNode.net && data.jumpNode.net.length > 0) || (data.jumpNode.disk && data.jumpNode.disk.length > 0) || (data.jumpNode.anomaly && data.jumpNode.anomaly.length > 0) || @@ -753,7 +781,7 @@ } } - // Update Jump Node network, disk, and load history + // Update Jump Node network, disk, ram, and load history if (data.jumpNode.net?.length) { const latestNet = data.jumpNode.net[data.jumpNode.net.length - 1]; jumpNetHistory.push({ @@ -782,6 +810,20 @@ console.debug('No jump node disk data available.'); } + if (data.jumpNode.ram?.length) { + const latestRam = data.jumpNode.ram[data.jumpNode.ram.length - 1]; + jumpRamHistory.push({ + time: latestRam.time, + used: Math.abs(latestRam.used), + free: Math.abs(latestRam.free) + }); + if (jumpRamHistory.length > MAX_POINTS) { + jumpRamHistory.shift(); + } + } else { + console.debug('No jump node RAM data available.'); + } + if (data.jumpNode.load?.length) { const latestLoad = data.jumpNode.load[data.jumpNode.load.length - 1]; jumpLoadHistory.push({ @@ -880,6 +922,17 @@ console.debug('Jump CPU chart not initialized.'); } + if (charts.jumpRam) { + const usedData = smoothData(jumpRamHistory.map(d => d.used) || [], SMOOTHING_WINDOW); + const freeData = smoothData(jumpRamHistory.map(d => d.free) || [], SMOOTHING_WINDOW); + charts.jumpRam.data.labels = jumpRamHistory.length ? jumpRamHistory.map((_, i) => i) : defaultLabels; + charts.jumpRam.data.datasets[0].data = usedData.length ? usedData : defaultData; + charts.jumpRam.data.datasets[1].data = freeData.length ? freeData : defaultData; + charts.jumpRam.update(); + } else { + console.debug('Jump RAM chart not initialized.'); + } + if (charts.jumpNet) { const maxVal = Math.max(...jumpNetHistory.map(d => Math.max(d.received, d.sent)), 1); const unitInfo = formatBytes(maxVal); diff --git a/system-status.js b/system-status.js index e3d8d51..74219a8 100644 --- a/system-status.js +++ b/system-status.js @@ -220,6 +220,7 @@ async function getJumpNodeMetrics() { try { const charts = [ { key: 'cpu', url: `${NETDATA_JUMP_URL}/api/v3/data?contexts=system.cpu&group_by=dimension&group=average&after=-60&points=30&format=json`, map: d => ({ time: d[0], user: d[6], system: d[7] }) }, + { key: 'ram', url: `${NETDATA_JUMP_URL}/api/v3/data?contexts=system.ram&group_by=dimension&group=average&after=-60&points=30&format=json`, map: d => ({ time: d[0], used: d[2], free: d[1] }) }, { key: 'net', url: `${NETDATA_JUMP_URL}/api/v3/data?contexts=system.net&group_by=dimension&group=average&after=-60&points=30&format=json`, map: d => ({ time: d[0], received: d[1], sent: d[2] }) }, { key: 'disk', url: `${NETDATA_JUMP_URL}/api/v3/data?contexts=system.io&group_by=dimension&group=average&after=-60&points=30&format=json`, map: d => ({ time: d[0], in: d[1], out: d[2] }) }, { key: 'anomaly', url: `${NETDATA_JUMP_URL}/api/v3/data?contexts=anomaly_detection.dimensions&scope_nodes=my-mc-link&group_by=dimension&group=average&after=-60&points=30&format=json`, map: d => ({ time: d[0], anomalous: d[1], normal: d[2] }) }, @@ -253,7 +254,7 @@ async function getJumpNodeMetrics() { // Ensure all keys are present, even if empty return { cpu: metrics.cpu || [], - ram: [], // RAM chart removed until verified + ram: metrics.ram || [], net: metrics.net || [], disk: metrics.disk || [], anomaly: metrics.anomaly || [],