From 0edd5841d69689f129d19a0e93d9b020558e113e Mon Sep 17 00:00:00 2001 From: John Haverlack Date: Sun, 8 Feb 2026 10:54:36 -0900 Subject: [PATCH] Refactoing Worker Dashboard --- sdl-mgr/html/js/dash.js | 66 +++++++++++++++++++++------- sdl-wkr/app/modules/sdl-wkr/index.js | 3 +- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/sdl-mgr/html/js/dash.js b/sdl-mgr/html/js/dash.js index c883858..a73b87f 100644 --- a/sdl-mgr/html/js/dash.js +++ b/sdl-mgr/html/js/dash.js @@ -502,27 +502,35 @@ function renderWorkersTable(msg) { html += ''; html += 'Hostname'; html += 'Status'; - html += 'Hardware'; html += ' CPU'; html += ' RAM'; html += ' GPU'; - html += 'Uptime'; - html += 'Last Seen'; html += ''; html += ''; html += ''; + const nowSec = Math.floor(Date.now() / 1000); + const staleThresholdSec = 60; + for (const [sdl_id, worker] of Object.entries(workers)) { - const status = worker.status === 'active' + const ageSec = nowSec - worker.last_seen_utime; + const isActive = ageSec <= staleThresholdSec; + + // Status badge + const statusBadge = isActive ? 'Active' - : 'Inactive'; + : 'Inactive'; // ✅ Red instead of grey // Hardware info const hwType = worker.hardware?.type || 'unknown'; const hwIcon = hwType === 'hw' ? '🖥️' : hwType === 'vm' ? '💠' : '❓'; const hwManuf = worker.hardware?.manufacturer || 'Unknown'; const hwModel = worker.hardware?.model || 'Unknown'; - const hardware = `${hwIcon} ${hwType === 'vm' ? hwModel : hwManuf}`; + + // ✅ Full hardware display with model + const hardwareDisplay = hwType === 'vm' + ? `${hwIcon} ${hwModel}` + : `${hwIcon} ${hwManuf} ${hwModel}`; // CPU const cpuAvail = worker.resources?.cpus?.available || 0; @@ -536,7 +544,6 @@ function renderWorkersTable(msg) { const memAvailGB = Math.round(memAvail / (1024 * 1024 * 1024)); const memTotalGB = Math.round(memTotal / (1024 * 1024 * 1024)); - const memUsedGB = Math.round(memUsed / (1024 * 1024 * 1024)); const memPercent = worker.usage?.memory?.percent_used || 0; // GPU @@ -548,32 +555,57 @@ function renderWorkersTable(msg) { const gpuMemGB = Math.round(gpuMemMB / 1024); // Uptime - const uptime = worker.uptime?.proc_dhms || 'N/A'; + const procUptime = worker.uptime?.proc_dhms || 'N/A'; + const sysUptime = worker.uptime?.sys_dhms || 'N/A'; - // Last seen - const lastSeen = worker.last_seen - ? new Date(worker.last_seen).toLocaleString() - : 'N/A'; + // ✅ Last seen age + const days = Math.floor(ageSec / 86400); + const hours = Math.floor((ageSec % 86400) / 3600); + const minutes = Math.floor((ageSec % 3600) / 60); + const seconds = Math.floor(ageSec % 60); + + let lastSeenAge = ''; + if (days > 0) lastSeenAge += `${days}d `; + if (hours > 0 || days > 0) lastSeenAge += `${hours}h `; + if (minutes > 0 || hours > 0 || days > 0) lastSeenAge += `${minutes}m `; + lastSeenAge += `${seconds}s ago`; html += ''; - html += `${worker.hostname}
${worker.sdl_id.substring(0, 8)}...`; - html += `${status}`; - html += `${hardware}`; + + // ✅ Hostname column with hardware underneath + html += ` + ${worker.hostname}
+ ${worker.sdl_id}
+ ${hardwareDisplay} + `; + + // ✅ Status column with uptime and last seen + html += ` + ${statusBadge}
+ SDL: ${procUptime}
+ OS: ${sysUptime}
+ ${lastSeenAge} + `; + + // CPU html += ` ${cpuAvail} / ${cpuTotal} ${cpuUsed > 0 ? `
${cpuUsed}% load` : ''} `; + + // Memory html += ` ${memAvailGB} / ${memTotalGB} GB ${memPercent > 0 ? `
${memPercent}% used` : ''} `; + + // GPU html += ` ${gpuAvail} / ${gpuTotal} ${gpuMemGB > 0 ? `
(${gpuMemGB} GB)` : ''} ${gpuUsed > 0 ? `
${gpuUsed}% load` : ''} `; - html += `${uptime}`; - html += `${lastSeen}`; + html += ''; } diff --git a/sdl-wkr/app/modules/sdl-wkr/index.js b/sdl-wkr/app/modules/sdl-wkr/index.js index e64af4f..79d684c 100644 --- a/sdl-wkr/app/modules/sdl-wkr/index.js +++ b/sdl-wkr/app/modules/sdl-wkr/index.js @@ -525,11 +525,12 @@ function getSystemHardware() { try { const piModel = fs.readFileSync('/proc/device-tree/model', 'utf8') .replace(/\0/g, '') + .replace(/Raspberry Pi/, '') .trim(); if (piModel) { hardware.type = 'hw'; // ✅ Changed from 'physical' - hardware.manufacturer = 'Raspberry Pi Foundation'; + hardware.manufacturer = 'Raspberry Pi'; hardware.model = piModel; return hardware; }