add Jump node
This commit is contained in:
236
status.html
236
status.html
@ -23,6 +23,12 @@
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
.no-data {
|
||||
text-align: center;
|
||||
color: #fb7185;
|
||||
font-size: 1.2rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -136,6 +142,44 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-bg p-8 sm:p-10 mb-12">
|
||||
<h2 class="text-3xl minecraft-font mb-8 text-center bg-gradient-to-r from-teal-400 to-blue-500 bg-clip-text text-transparent">
|
||||
Jump Node Stats</h2>
|
||||
<div id="jump-no-data" class="no-data" style="display: none;">No Jump Node data available</div>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div class="feature-card tilt-card">
|
||||
<h3 class="text-xl minecraft-font mb-3 text-teal-400">Uptime</h3>
|
||||
<p class="text-lg opacity-90" id="jump-uptime">0 days</p>
|
||||
</div>
|
||||
<div class="feature-card tilt-card">
|
||||
<h3 class="text-xl minecraft-font mb-3 text-teal-400">AI Anomaly Count</h3>
|
||||
<p class="text-lg opacity-90" id="jump-ai-anomaly-count">0</p>
|
||||
</div>
|
||||
<div class="feature-card tilt-card">
|
||||
<h3 class="text-xl minecraft-font mb-3 text-teal-400">Disk Usage</h3>
|
||||
<p class="text-lg opacity-90" id="jump-disk-usage">0 GB</p>
|
||||
</div>
|
||||
<div class="feature-card tilt-card">
|
||||
<h3 class="text-xl minecraft-font mb-3 text-teal-400">Free Disk</h3>
|
||||
<p class="text-lg opacity-90" id="jump-free-disk">0 GB</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 class="text-xl minecraft-font mb-6 text-teal-400 text-center">CPU Usage</h3>
|
||||
<canvas id="jump-cpu-chart"></canvas>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl minecraft-font mb-6 text-teal-400 text-center">Network Traffic</h3>
|
||||
<canvas id="jump-net-chart"></canvas>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl minecraft-font mb-6 text-teal-400 text-center">Disk I/O</h3>
|
||||
<canvas id="jump-disk-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="bg-gray-900/20 backdrop-filter backdrop-blur-xl py-8 text-center relative z-10">
|
||||
@ -152,12 +196,14 @@
|
||||
let dockerNetHistory = [];
|
||||
let netHistory = [];
|
||||
let diskHistory = [];
|
||||
let jumpNetHistory = [];
|
||||
let jumpDiskHistory = [];
|
||||
const MAX_POINTS = 10;
|
||||
const SMOOTHING_WINDOW = 3;
|
||||
|
||||
// Helper to smooth data
|
||||
function smoothData(data, windowSize) {
|
||||
if (data.length < windowSize) return data;
|
||||
if (!data || data.length < windowSize) return data || [];
|
||||
return data.map((_, i) => {
|
||||
const start = Math.max(0, i - windowSize + 1);
|
||||
const slice = data.slice(start, i + 1);
|
||||
@ -173,6 +219,12 @@
|
||||
return { value: bytes.toFixed(2), unit: 'B/s' };
|
||||
}
|
||||
|
||||
// Helper to format uptime in days
|
||||
function formatUptime(seconds) {
|
||||
const days = Math.floor(seconds / (60 * 60 * 24));
|
||||
return `${days} days`;
|
||||
}
|
||||
|
||||
// Initialize Chart.js charts
|
||||
function initCharts() {
|
||||
if (typeof Chart === 'undefined') {
|
||||
@ -185,7 +237,10 @@
|
||||
cpu: document.getElementById('cpu-chart'),
|
||||
ram: document.getElementById('ram-chart'),
|
||||
net: document.getElementById('net-chart'),
|
||||
disk: document.getElementById('disk-chart')
|
||||
disk: document.getElementById('disk-chart'),
|
||||
jumpCpu: document.getElementById('jump-cpu-chart'),
|
||||
jumpNet: document.getElementById('jump-net-chart'),
|
||||
jumpDisk: document.getElementById('jump-disk-chart')
|
||||
};
|
||||
|
||||
for (const [key, canvas] of Object.entries(canvases)) {
|
||||
@ -322,11 +377,88 @@
|
||||
}
|
||||
});
|
||||
|
||||
charts.jumpCpu = new Chart(canvases.jumpCpu.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{ label: 'User (%)', data: [], borderColor: '#38bdf8', fill: false, tension: 0.3 },
|
||||
{ label: 'System (%)', data: [], borderColor: '#fb7185', fill: false, tension: 0.3 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
scales: {
|
||||
y: {
|
||||
...commonOptions.scales.y,
|
||||
max: 100,
|
||||
title: { display: true, text: 'Usage (%)', color: '#e5e7eb' }
|
||||
},
|
||||
x: commonOptions.scales.x
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
charts.jumpNet = new Chart(canvases.jumpNet.getContext('2d'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{ label: 'Received', data: [], backgroundColor: '#38bdf8', stack: 'Stack 0' },
|
||||
{ label: 'Sent', data: [], backgroundColor: '#fb7185', stack: 'Stack 0' }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
scales: {
|
||||
y: {
|
||||
...commonOptions.scales.y,
|
||||
stacked: true,
|
||||
title: { display: true, text: 'Speed', color: '#e5e7eb' }
|
||||
},
|
||||
x: {
|
||||
...commonOptions.scales.x,
|
||||
stacked: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
charts.jumpDisk = new Chart(canvases.jumpDisk.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{ label: 'Read', data: [], borderColor: '#38bdf8', fill: false, tension: 0.3 },
|
||||
{ label: 'Write', data: [], borderColor: '#fb7185', fill: false, tension: 0.3 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
scales: {
|
||||
y: {
|
||||
...commonOptions.scales.y,
|
||||
title: { display: true, text: 'Speed', color: '#e5e7eb' }
|
||||
},
|
||||
x: commonOptions.scales.x
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Charts initialized successfully.');
|
||||
}
|
||||
|
||||
// Update UI with data
|
||||
function updateUI(data) {
|
||||
if (!data) {
|
||||
console.error('Received empty WebSocket data.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Log full payload for debugging
|
||||
console.debug('Received WebSocket payload:', JSON.stringify(data, null, 2));
|
||||
|
||||
// Initialize defaults for missing data
|
||||
if (!data.docker) {
|
||||
console.warn('Missing docker data.');
|
||||
data.docker = {};
|
||||
@ -335,6 +467,22 @@
|
||||
console.warn('Missing netdata data.');
|
||||
data.netdata = { cpu: [], ram: [], net: [], disk: [], disk_space: [], anomaly: [] };
|
||||
}
|
||||
if (!data.jumpNode) {
|
||||
console.warn('Missing jump node data.');
|
||||
data.jumpNode = { cpu: [], ram: [], net: [], disk: [], anomaly: [], disk_space: [], uptime: [] };
|
||||
}
|
||||
|
||||
// Show/hide no-data message for Jump Node
|
||||
const jumpNoData = document.getElementById('jump-no-data');
|
||||
const hasJumpData = data.jumpNode && (
|
||||
(data.jumpNode.cpu && data.jumpNode.cpu.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) ||
|
||||
(data.jumpNode.disk_space && data.jumpNode.disk_space.length > 0) ||
|
||||
(data.jumpNode.uptime && data.jumpNode.uptime.length > 0)
|
||||
);
|
||||
jumpNoData.style.display = hasJumpData ? 'none' : 'block';
|
||||
|
||||
// Update Docker stats
|
||||
document.getElementById('total-containers').textContent = data.docker.totalContainers || 0;
|
||||
@ -354,6 +502,20 @@
|
||||
const latestAnomaly = anomalyData.length > 0 ? anomalyData[anomalyData.length - 1] : null;
|
||||
document.getElementById('ai-fault-count').textContent = latestAnomaly ? `${latestAnomaly.anomalous}` : '0';
|
||||
|
||||
// Update Jump Node stats
|
||||
const jumpDiskSpaceData = data.jumpNode.disk_space || [];
|
||||
const latestJumpDiskSpace = jumpDiskSpaceData.length > 0 ? jumpDiskSpaceData[jumpDiskSpaceData.length - 1] : null;
|
||||
document.getElementById('jump-disk-usage').textContent = latestJumpDiskSpace ? `${latestJumpDiskSpace.used.toFixed(2)} GB` : '0 GB';
|
||||
document.getElementById('jump-free-disk').textContent = latestJumpDiskSpace ? `${latestJumpDiskSpace.avail.toFixed(2)} GB` : '0 GB';
|
||||
|
||||
const jumpAnomalyData = data.jumpNode.anomaly || [];
|
||||
const latestJumpAnomaly = jumpAnomalyData.length > 0 ? jumpAnomalyData[jumpAnomalyData.length - 1] : null;
|
||||
document.getElementById('jump-ai-anomaly-count').textContent = latestJumpAnomaly ? `${latestJumpAnomaly.anomalous}` : '0';
|
||||
|
||||
const jumpUptimeData = data.jumpNode.uptime || [];
|
||||
const latestJumpUptime = jumpUptimeData.length > 0 ? jumpUptimeData[jumpUptimeData.length - 1] : null;
|
||||
document.getElementById('jump-uptime').textContent = latestJumpUptime ? formatUptime(latestJumpUptime.uptime) : '0 days';
|
||||
|
||||
// Update container tables
|
||||
const cpuTable = document.getElementById('cpu-table');
|
||||
const memoryTable = document.getElementById('memory-table');
|
||||
@ -413,6 +575,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Update Jump Node network and disk history
|
||||
if (data.jumpNode.net?.length) {
|
||||
const latestNet = data.jumpNode.net[data.jumpNode.net.length - 1];
|
||||
jumpNetHistory.push({
|
||||
time: latestNet.time,
|
||||
received: Math.abs(latestNet.received),
|
||||
sent: Math.abs(latestNet.sent)
|
||||
});
|
||||
if (jumpNetHistory.length > MAX_POINTS) {
|
||||
jumpNetHistory.shift();
|
||||
}
|
||||
} else {
|
||||
console.debug('No jump node network data available.');
|
||||
}
|
||||
|
||||
if (data.jumpNode.disk?.length) {
|
||||
const latestDisk = data.jumpNode.disk[data.jumpNode.disk.length - 1];
|
||||
jumpDiskHistory.push({
|
||||
time: latestDisk.time,
|
||||
in: Math.abs(latestDisk.in),
|
||||
out: Math.abs(latestDisk.out)
|
||||
});
|
||||
if (jumpDiskHistory.length > MAX_POINTS) {
|
||||
jumpDiskHistory.shift();
|
||||
}
|
||||
} else {
|
||||
console.debug('No jump node disk data available.');
|
||||
}
|
||||
|
||||
// Update charts with smoothing and dynamic units
|
||||
const defaultLabels = Array(MAX_POINTS).fill(0).map((_, i) => i);
|
||||
const defaultData = Array(MAX_POINTS).fill(0);
|
||||
@ -473,6 +664,47 @@
|
||||
charts.disk.options.scales.y.title.text = unitInfo.unit;
|
||||
charts.disk.update();
|
||||
}
|
||||
|
||||
if (charts.jumpCpu) {
|
||||
const userData = smoothData(data.jumpNode.cpu?.map(d => d.user) || [], SMOOTHING_WINDOW);
|
||||
const systemData = smoothData(data.jumpNode.cpu?.map(d => d.system) || [], SMOOTHING_WINDOW);
|
||||
charts.jumpCpu.data.labels = data.jumpNode.cpu?.length ? data.jumpNode.cpu.map((_, i) => i) : defaultLabels;
|
||||
charts.jumpCpu.data.datasets[0].data = userData.length ? userData : defaultData;
|
||||
charts.jumpCpu.data.datasets[1].data = systemData.length ? systemData : defaultData;
|
||||
charts.jumpCpu.update();
|
||||
} else {
|
||||
console.debug('Jump CPU chart not initialized.');
|
||||
}
|
||||
|
||||
if (charts.jumpNet) {
|
||||
const maxVal = Math.max(...jumpNetHistory.map(d => Math.max(d.received, d.sent)), 1);
|
||||
const unitInfo = formatBytes(maxVal);
|
||||
const scale = unitInfo.unit === 'GB/s' ? 1e9 : unitInfo.unit === 'MB/s' ? 1e6 : unitInfo.unit === 'KB/s' ? 1e3 : 1;
|
||||
const receivedData = smoothData(jumpNetHistory.map(d => d.received / scale), SMOOTHING_WINDOW);
|
||||
const sentData = smoothData(jumpNetHistory.map(d => d.sent / scale), SMOOTHING_WINDOW);
|
||||
charts.jumpNet.data.labels = jumpNetHistory.length ? jumpNetHistory.map((_, i) => i) : defaultLabels;
|
||||
charts.jumpNet.data.datasets[0].data = receivedData.length ? receivedData : defaultData;
|
||||
charts.jumpNet.data.datasets[1].data = sentData.length ? sentData : defaultData;
|
||||
charts.jumpNet.options.scales.y.title.text = unitInfo.unit;
|
||||
charts.jumpNet.update();
|
||||
} else {
|
||||
console.debug('Jump Network chart not initialized.');
|
||||
}
|
||||
|
||||
if (charts.jumpDisk) {
|
||||
const maxVal = Math.max(...jumpDiskHistory.map(d => Math.max(d.in, d.out)), 1);
|
||||
const unitInfo = formatBytes(maxVal);
|
||||
const scale = unitInfo.unit === 'GB/s' ? 1e9 : unitInfo.unit === 'MB/s' ? 1e6 : unitInfo.unit === 'KB/s' ? 1e3 : 1;
|
||||
const inData = smoothData(jumpDiskHistory.map(d => d.in / scale), SMOOTHING_WINDOW);
|
||||
const outData = smoothData(jumpDiskHistory.map(d => d.out / scale), SMOOTHING_WINDOW);
|
||||
charts.jumpDisk.data.labels = jumpDiskHistory.length ? jumpDiskHistory.map((_, i) => i) : defaultLabels;
|
||||
charts.jumpDisk.data.datasets[0].data = inData.length ? inData : defaultData;
|
||||
charts.jumpDisk.data.datasets[1].data = outData.length ? outData : defaultData;
|
||||
charts.jumpDisk.options.scales.y.title.text = unitInfo.unit;
|
||||
charts.jumpDisk.update();
|
||||
} else {
|
||||
console.debug('Jump Disk chart not initialized.');
|
||||
}
|
||||
}
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
|
136
system-status.js
136
system-status.js
@ -12,8 +12,23 @@ const server = http.createServer(app);
|
||||
const wss = new WebSocket.Server({ server });
|
||||
const docker = new Docker({ socketPath: process.env.DOCKER_SOCKET_PATH });
|
||||
const NETDATA_URL = process.env.NETDATA_URL;
|
||||
const NETDATA_JUMP_URL = process.env.NETDATA_JUMP_URL;
|
||||
const TOTAL_CORES = parseInt(process.env.TOTAL_CORES, 10);
|
||||
|
||||
// Verify environment variables
|
||||
if (!NETDATA_URL) {
|
||||
console.error('NETDATA_URL environment variable is not set.');
|
||||
}
|
||||
if (!NETDATA_JUMP_URL) {
|
||||
console.error('NETDATA_JUMP_URL environment variable is not set.');
|
||||
}
|
||||
if (!process.env.DOCKER_SOCKET_PATH) {
|
||||
console.error('DOCKER_SOCKET_PATH environment variable is not set.');
|
||||
}
|
||||
if (!TOTAL_CORES) {
|
||||
console.error('TOTAL_CORES environment variable is not set or invalid.');
|
||||
}
|
||||
|
||||
// Promisify exec for async/await
|
||||
const execPromise = util.promisify(exec);
|
||||
|
||||
@ -149,24 +164,33 @@ async function getDockerStats() {
|
||||
|
||||
// Fetch Netdata metrics
|
||||
async function getNetdataMetrics() {
|
||||
if (!NETDATA_URL) {
|
||||
console.error('Cannot fetch Netdata metrics: NETDATA_URL is undefined.');
|
||||
return { cpu: [], ram: [], net: [], disk: [], disk_space: [], anomaly: [] };
|
||||
}
|
||||
|
||||
try {
|
||||
const charts = [
|
||||
{ key: 'cpu', url: `${NETDATA_URL}/data?chart=system.cpu&after=-60&points=30`, map: d => ({ time: d[0], user: d[6], system: d[7] }) },
|
||||
{ key: 'ram', url: `${NETDATA_URL}/data?chart=system.ram&after=-60&points=30`, map: d => ({ time: d[0], used: d[2], free: d[3] }) },
|
||||
{ key: 'net', url: `${NETDATA_URL}/data?chart=system.net&after=-60&points=30`, map: d => ({ time: d[0], received: d[1], sent: d[2] }) },
|
||||
{ key: 'disk', url: `${NETDATA_URL}/data?chart=system.io&after=-60&points=30`, map: d => ({ time: d[0], in: d[1], out: d[2] }) },
|
||||
{ key: 'disk_space', url: `${NETDATA_URL}/data?chart=disk_space./&format=json&after=-60&points=30`, map: d => ({ time: d[0], avail: d[1], used: d[2], reserved: d[3] }) },
|
||||
{ key: 'anomaly', url: `${NETDATA_URL}/data?chart=anomaly_detection.dimensions_on_mchost&format=json&after=-60&points=30`, map: d => ({ time: d[0], anomalous: d[1], normal: d[2] }) }
|
||||
{ key: 'cpu', url: `${NETDATA_URL}/api/v1/data?chart=system.cpu&after=-60&points=30`, map: d => ({ time: d[0], user: d[6], system: d[7] }) },
|
||||
{ key: 'ram', url: `${NETDATA_URL}/api/v1/data?chart=system.ram&after=-60&points=30`, map: d => ({ time: d[0], used: d[2], free: d[3] }) },
|
||||
{ key: 'net', url: `${NETDATA_URL}/api/v1/data?chart=system.net&after=-60&points=30`, map: d => ({ time: d[0], received: d[1], sent: d[2] }) },
|
||||
{ key: 'disk', url: `${NETDATA_URL}/api/v1/data?chart=system.io&after=-60&points=30`, map: d => ({ time: d[0], in: d[1], out: d[2] }) },
|
||||
{ key: 'disk_space', url: `${NETDATA_URL}/api/v1/data?chart=disk_space./&format=json&after=-60&points=30`, map: d => ({ time: d[0], avail: d[1], used: d[2], reserved: d[3] }) },
|
||||
{ key: 'anomaly', url: `${NETDATA_URL}/api/v1/data?chart=anomaly_detection.dimensions_on_mchost&format=json&after=-60&points=30`, map: d => ({ time: d[0], anomalous: d[1], normal: d[2] }) }
|
||||
];
|
||||
|
||||
const results = await Promise.all(
|
||||
charts.map(async ({ key, url, map }) => {
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
const response = await axios.get(url, { timeout: 5000 });
|
||||
if (!response.data || !response.data.data) {
|
||||
console.warn(`No data returned for Netdata chart ${key} from ${url}`);
|
||||
return { key, data: [] };
|
||||
}
|
||||
const data = response.data.data.map(map);
|
||||
return { key, data };
|
||||
} catch (error) {
|
||||
console.warn(`Failed to fetch Netdata chart ${key}:`, error.message);
|
||||
console.warn(`Failed to fetch Netdata chart ${key} from ${url}:`, error.message, error.response ? `Status: ${error.response.status}` : '');
|
||||
return { key, data: [] };
|
||||
}
|
||||
})
|
||||
@ -184,6 +208,61 @@ async function getNetdataMetrics() {
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch Jump Node metrics
|
||||
async function getJumpNodeMetrics() {
|
||||
if (!NETDATA_JUMP_URL) {
|
||||
console.error('Cannot fetch Jump Node metrics: NETDATA_JUMP_URL is undefined.');
|
||||
return { cpu: [], ram: [], net: [], disk: [], anomaly: [], disk_space: [], uptime: [] };
|
||||
}
|
||||
|
||||
try {
|
||||
const charts = [
|
||||
{ key: 'cpu', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=system.cpu&after=-60&points=30`, map: d => ({ time: d[0], user: d[6], system: d[7] }) },
|
||||
{ key: 'net', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=system.net&after=-60&points=30`, map: d => ({ time: d[0], received: d[1], sent: d[2] }) },
|
||||
{ key: 'disk', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=system.io&after=-60&points=30`, map: d => ({ time: d[0], in: d[1], out: d[2] }) },
|
||||
{ key: 'anomaly', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=anomaly_detection.dimensions_on_my-mc-link&format=json&after=-60&points=30`, map: d => ({ time: d[0], anomalous: d[1], normal: d[2] }) },
|
||||
{ key: 'disk_space', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=disk_space./&format=json&after=-60&points=30`, map: d => ({ time: d[0], avail: d[1], used: d[2], reserved: d[3] }) },
|
||||
{ key: 'uptime', url: `${NETDATA_JUMP_URL}/api/v1/data?chart=system.uptime&format=json&after=-60&points=30`, map: d => ({ time: d[0], uptime: d[1] }) }
|
||||
];
|
||||
|
||||
const results = await Promise.all(
|
||||
charts.map(async ({ key, url, map }) => {
|
||||
try {
|
||||
const response = await axios.get(url, { timeout: 10000 });
|
||||
if (!response.data || !response.data.data) {
|
||||
console.warn(`No data returned for Jump Node chart ${key} from ${url}`);
|
||||
return { key, data: [] };
|
||||
}
|
||||
const data = response.data.data.map(map);
|
||||
return { key, data };
|
||||
} catch (error) {
|
||||
console.warn(`Failed to fetch Jump Node chart ${key} from ${url}:`, error.message, error.response ? `Status: ${error.response.status}` : '');
|
||||
return { key, data: [] };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const metrics = {};
|
||||
results.forEach(({ key, data }) => {
|
||||
metrics[key] = data;
|
||||
});
|
||||
|
||||
// Ensure all keys are present, even if empty
|
||||
return {
|
||||
cpu: metrics.cpu || [],
|
||||
ram: [], // RAM chart removed until verified
|
||||
net: metrics.net || [],
|
||||
disk: metrics.disk || [],
|
||||
anomaly: metrics.anomaly || [],
|
||||
disk_space: metrics.disk_space || [],
|
||||
uptime: metrics.uptime || []
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching Jump Node metrics:', error.message);
|
||||
return { cpu: [], ram: [], net: [], disk: [], anomaly: [], disk_space: [], uptime: [] };
|
||||
}
|
||||
}
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(__dirname + '/status.html');
|
||||
});
|
||||
@ -194,13 +273,42 @@ wss.on('connection', (ws) => {
|
||||
|
||||
// Send updates every 1 second
|
||||
const interval = setInterval(async () => {
|
||||
const [dockerStats, netdataMetrics, holesailProcessCount] = await Promise.all([
|
||||
getDockerStats(),
|
||||
getNetdataMetrics(),
|
||||
getHolesailProcessCount()
|
||||
]);
|
||||
let dockerStats = {};
|
||||
let netdataMetrics = { cpu: [], ram: [], net: [], disk: [], disk_space: [], anomaly: [] };
|
||||
let jumpNodeMetrics = { cpu: [], ram: [], net: [], disk: [], anomaly: [], disk_space: [], uptime: [] };
|
||||
let holesailProcessCount = 0;
|
||||
|
||||
ws.send(JSON.stringify({ docker: dockerStats, netdata: netdataMetrics, holesailProcessCount }));
|
||||
try {
|
||||
dockerStats = await getDockerStats();
|
||||
} catch (error) {
|
||||
console.error('Error in getDockerStats:', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
netdataMetrics = await getNetdataMetrics();
|
||||
} catch (error) {
|
||||
console.error('Error in getNetdataMetrics:', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
jumpNodeMetrics = await getJumpNodeMetrics();
|
||||
} catch (error) {
|
||||
console.error('Error in getJumpNodeMetrics:', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
holesailProcessCount = await getHolesailProcessCount();
|
||||
} catch (error) {
|
||||
console.error('Error in getHolesailProcessCount:', error.message);
|
||||
}
|
||||
|
||||
const payload = {
|
||||
docker: dockerStats,
|
||||
netdata: netdataMetrics,
|
||||
jumpNode: jumpNodeMetrics,
|
||||
holesailProcessCount
|
||||
};
|
||||
ws.send(JSON.stringify(payload));
|
||||
}, 1000);
|
||||
|
||||
ws.on('close', () => {
|
||||
|
Reference in New Issue
Block a user