Updating Worker Telemetry
This commit is contained in:
parent
0cb6fb8aa3
commit
211cdcc53c
|
|
@ -54,6 +54,10 @@ MVP - Minimum Viable Product Task List
|
||||||
- [ ] Show worker uptime in dashboard
|
- [ ] Show worker uptime in dashboard
|
||||||
- [ ] Display last seen as elapsed time in dashboard, not date
|
- [ ] Display last seen as elapsed time in dashboard, not date
|
||||||
- [ ] Track Username for sdl process
|
- [ ] Track Username for sdl process
|
||||||
|
- [ ] Web UI
|
||||||
|
- [ ] Progresive Web App
|
||||||
|
- [ ] Editable Dashboard
|
||||||
|
|
||||||
|
|
||||||
**Resource Management**
|
**Resource Management**
|
||||||
- [ ] CPU Reserve Capacity Allocation
|
- [ ] CPU Reserve Capacity Allocation
|
||||||
|
|
|
||||||
|
|
@ -602,8 +602,16 @@ function getUptimeDHMS() {
|
||||||
const h = Math.floor((uptimeSec % 86400) / 3600);
|
const h = Math.floor((uptimeSec % 86400) / 3600);
|
||||||
const m = Math.floor((uptimeSec % 3600) / 60);
|
const m = Math.floor((uptimeSec % 3600) / 60);
|
||||||
const s = Math.floor(uptimeSec % 60);
|
const s = Math.floor(uptimeSec % 60);
|
||||||
return `${d}.${h}.${m}.${s}`;
|
return `${d}d ${h}h ${m}m ${s}s`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOSUptimeDHMS() {
|
||||||
|
const uptimeSec = os.uptime();
|
||||||
|
const d = Math.floor(uptimeSec / 86400);
|
||||||
|
const h = Math.floor((uptimeSec % 86400) / 3600);
|
||||||
|
const m = Math.floor((uptimeSec % 3600) / 60);
|
||||||
|
const s = Math.floor(uptimeSec % 60);
|
||||||
|
return `${d}d ${h}h ${m}m ${s}s`;
|
||||||
|
}
|
||||||
|
|
||||||
export { load_config, log, ipToInt, intToIp, computeBroadcast, getProcessStartTs, getUptimeMs, getUptimeSec, getUptimeDHMS };
|
export { load_config, log, ipToInt, intToIp, computeBroadcast, getProcessStartTs, getUptimeMs, getUptimeSec, getUptimeDHMS, getOSUptimeDHMS };
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
const module = 'sdl-wkr'; // Module Name
|
const module = 'sdl-wkr'; // Module Name
|
||||||
import { load_config, log } from '../nwa-lib/index.js';
|
import { load_config, log, getUptimeDHMS, getOSUptimeDHMS } from '../nwa-lib/index.js';
|
||||||
import dgram from 'dgram';
|
import dgram from 'dgram';
|
||||||
import mqtt from 'mqtt';
|
import mqtt from 'mqtt';
|
||||||
import os from 'os';
|
import os, { platform } from 'os';
|
||||||
import { exec } from 'child_process';
|
import { exec, execSync } from 'child_process';
|
||||||
|
|
||||||
|
|
||||||
const config = load_config();
|
const config = load_config();
|
||||||
|
|
||||||
|
|
@ -19,6 +18,7 @@ let mqttClient = null;
|
||||||
let clusterConfig = null;
|
let clusterConfig = null;
|
||||||
let updating = false;
|
let updating = false;
|
||||||
let telemetryTimer = null;
|
let telemetryTimer = null;
|
||||||
|
let lastCpuInfo = null;
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Start UDP discovery
|
// Start UDP discovery
|
||||||
|
|
@ -306,14 +306,80 @@ function startTelemetry() {
|
||||||
}, telemetryInterval);
|
}, telemetryInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add this function for per-CPU usage
|
||||||
|
function getPerCPUUsage() {
|
||||||
|
const cpus = os.cpus();
|
||||||
|
|
||||||
|
if (!lastCpuInfo || !lastCpuInfo.perCpu) {
|
||||||
|
// First call - initialize
|
||||||
|
const perCpu = cpus.map(cpu => {
|
||||||
|
let total = 0;
|
||||||
|
for (let type in cpu.times) {
|
||||||
|
total += cpu.times[type];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
idle: cpu.times.idle,
|
||||||
|
total: total
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
lastCpuInfo = lastCpuInfo || {};
|
||||||
|
lastCpuInfo.perCpu = perCpu;
|
||||||
|
|
||||||
|
return cpus.map(() => 0); // Return 0% for all CPUs on first call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate per-CPU usage
|
||||||
|
const usage = cpus.map((cpu, i) => {
|
||||||
|
let total = 0;
|
||||||
|
for (let type in cpu.times) {
|
||||||
|
total += cpu.times[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
const idleDelta = cpu.times.idle - lastCpuInfo.perCpu[i].idle;
|
||||||
|
const totalDelta = total - lastCpuInfo.perCpu[i].total;
|
||||||
|
|
||||||
|
const cpuUsage = 100 - (100 * idleDelta / totalDelta);
|
||||||
|
|
||||||
|
// Update stored values
|
||||||
|
lastCpuInfo.perCpu[i] = {
|
||||||
|
idle: cpu.times.idle,
|
||||||
|
total: total
|
||||||
|
};
|
||||||
|
|
||||||
|
return Math.max(0, Math.min(100, Math.round(cpuUsage)));
|
||||||
|
});
|
||||||
|
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update getCPUUsagePercent to calculate average from per-CPU
|
||||||
|
function getCPUUsagePercent() {
|
||||||
|
const perCpuUsage = getPerCPUUsage();
|
||||||
|
if (perCpuUsage.length === 0) return 0;
|
||||||
|
|
||||||
|
const total = perCpuUsage.reduce((sum, usage) => sum + usage, 0);
|
||||||
|
return Math.round(total / perCpuUsage.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Publish telemetry
|
||||||
|
// -------------------------------
|
||||||
function publishTelemetry(topic) {
|
function publishTelemetry(topic) {
|
||||||
if (!mqttClient || !authorized) return;
|
if (!mqttClient || !authorized) return;
|
||||||
|
|
||||||
const gpuCount = Array.isArray(config.host.gpu) ? config.host.gpu.length : 0;
|
const gpuCount = Array.isArray(config.host.gpu) ? config.host.gpu.length : 0;
|
||||||
|
|
||||||
// ✅ Convert GB to bytes
|
// Get real-time memory usage
|
||||||
const memoryBytes = config.host.memory.total_gb
|
const totalMem = os.totalmem();
|
||||||
? config.host.memory.total_gb * 1024 * 1024 * 1024
|
const freeMem = os.freemem();
|
||||||
|
const usedMem = totalMem - freeMem;
|
||||||
|
|
||||||
|
// Get CPU usage
|
||||||
|
const perCpuUsage = getPerCPUUsage();
|
||||||
|
// const totalCpuUsage = getCPUUsagePercent();
|
||||||
|
const totalCpuUsage = perCpuUsage.length > 0
|
||||||
|
? Math.round(perCpuUsage.reduce((sum, usage) => sum + usage, 0) / perCpuUsage.length)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const telemetry = {
|
const telemetry = {
|
||||||
|
|
@ -323,25 +389,49 @@ function publishTelemetry(topic) {
|
||||||
host: config.identity.hostname,
|
host: config.identity.hostname,
|
||||||
type: 'worker-telemetry',
|
type: 'worker-telemetry',
|
||||||
msg: {
|
msg: {
|
||||||
sdl_id: config.identity.sdl_id,
|
system: {
|
||||||
hostname: config.identity.hostname,
|
platform: config.host.os.platform,
|
||||||
status: 'active',
|
arch: config.host.cpu.arch,
|
||||||
|
distro: config.host.os.pretty_name,
|
||||||
|
distro_name: config.host.os.name,
|
||||||
|
distro_version: config.host.os.version
|
||||||
|
},
|
||||||
|
uptime: {
|
||||||
|
process: Math.floor(process.uptime()),
|
||||||
|
proc_dhms: getUptimeDHMS(),
|
||||||
|
system: Math.floor(os.uptime()),
|
||||||
|
sys_dhms: getOSUptimeDHMS()
|
||||||
|
},
|
||||||
resources: {
|
resources: {
|
||||||
cpus: {
|
cpus: {
|
||||||
allocated: config.host.cpu.cores_logical,
|
allocated: config.host.cpu.cores_logical,
|
||||||
available: config.host.cpu.cores_logical,
|
available: config.host.cpu.cores_logical
|
||||||
used: 0
|
|
||||||
},
|
},
|
||||||
memory: {
|
memory: {
|
||||||
allocated: memoryBytes, // ✅ Fixed
|
allocated: totalMem
|
||||||
available: memoryBytes, // ✅ Fixed
|
|
||||||
used: 0
|
|
||||||
},
|
},
|
||||||
gpus: {
|
gpus: {
|
||||||
allocated: gpuCount,
|
allocated: gpuCount,
|
||||||
available: gpuCount,
|
available: gpuCount
|
||||||
used: 0
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
usage: {
|
||||||
|
cpu: {
|
||||||
|
total: totalCpuUsage,
|
||||||
|
per_core: perCpuUsage
|
||||||
|
},
|
||||||
|
memory: {
|
||||||
|
total: totalMem,
|
||||||
|
used: usedMem,
|
||||||
|
free: freeMem,
|
||||||
|
percent_used: Math.round((usedMem / totalMem) * 100)
|
||||||
|
},
|
||||||
|
gpu: getGPUUsage()
|
||||||
|
},
|
||||||
|
load: {
|
||||||
|
1: os.loadavg()[0],
|
||||||
|
5: os.loadavg()[1],
|
||||||
|
15: os.loadavg()[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -358,6 +448,55 @@ function publishTelemetry(topic) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add GPU telemetry function (exec-based)
|
||||||
|
function getGPUUsage() {
|
||||||
|
const gpuCount = Array.isArray(config.host.gpu) ? config.host.gpu.length : 0;
|
||||||
|
|
||||||
|
if (gpuCount === 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try nvidia-smi for NVIDIA GPUs
|
||||||
|
const output = execSync(
|
||||||
|
'nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv,noheader,nounits',
|
||||||
|
{ encoding: 'utf8', timeout: 5000 }
|
||||||
|
).toString();
|
||||||
|
|
||||||
|
const lines = output.trim().split('\n');
|
||||||
|
const gpus = lines.map((line, index) => {
|
||||||
|
const [util, memUsed, memTotal] = line.split(',').map(v => parseInt(v.trim()));
|
||||||
|
return {
|
||||||
|
id: index,
|
||||||
|
utilization: util,
|
||||||
|
memory_used_mb: memUsed,
|
||||||
|
memory_total_mb: memTotal,
|
||||||
|
memory_percent: Math.round((memUsed / memTotal) * 100)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate totals
|
||||||
|
const totalUtil = Math.round(gpus.reduce((sum, gpu) => sum + gpu.utilization, 0) / gpus.length);
|
||||||
|
const totalMemUsed = gpus.reduce((sum, gpu) => sum + gpu.memory_used_mb, 0);
|
||||||
|
const totalMemTotal = gpus.reduce((sum, gpu) => sum + gpu.memory_total_mb, 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
count: gpus.length,
|
||||||
|
total_utilization: totalUtil,
|
||||||
|
total_memory_used_mb: totalMemUsed,
|
||||||
|
total_memory_total_mb: totalMemTotal,
|
||||||
|
total_memory_percent: Math.round((totalMemUsed / totalMemTotal) * 100),
|
||||||
|
gpus: gpus
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
// nvidia-smi not available or failed
|
||||||
|
return { error: 'unavailable' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function stopTelemetry() {
|
function stopTelemetry() {
|
||||||
if (telemetryTimer) {
|
if (telemetryTimer) {
|
||||||
clearInterval(telemetryTimer);
|
clearInterval(telemetryTimer);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue