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 || [],