|
|
@@ -252,32 +252,130 @@ function updateSystemMetrics() {
|
|
|
const v = state.vpnStatus;
|
|
|
if (!s) return;
|
|
|
|
|
|
- // Sidebar
|
|
|
- document.getElementById('side-hostname').innerText = s.hostname || 'debian-lxc';
|
|
|
- document.getElementById('side-uptime').innerText = s.uptime_human || '0m';
|
|
|
- document.getElementById('side-gateway-ip').innerText = s.default_gateway ? `GW: ${s.default_gateway}` : 'GW: Isolated';
|
|
|
-
|
|
|
+ // Sidebar Host & Uptime
|
|
|
+ const sideHost = document.getElementById('side-hostname');
|
|
|
+ if (sideHost) sideHost.innerText = s.hostname || 'debian-lxc';
|
|
|
+ const sideUp = document.getElementById('side-uptime');
|
|
|
+ if (sideUp) sideUp.innerText = s.uptime_human || '0m';
|
|
|
+ const sideGw = document.getElementById('side-gateway-ip');
|
|
|
+ if (sideGw) sideGw.innerText = s.default_gateway ? `GW: ${s.default_gateway}` : 'GW: Isolated';
|
|
|
+
|
|
|
+ // Compute CPU Metrics
|
|
|
+ let cpuPct = 0;
|
|
|
if (s.cpu_pct !== undefined) {
|
|
|
- const pct = s.cpu_pct;
|
|
|
- document.getElementById('side-cpu-val').innerText = `${pct.toFixed(1)}%`;
|
|
|
- document.getElementById('side-cpu-bar').style.width = `${Math.max(4, Math.min(100, pct))}%`;
|
|
|
- const loadStr = s.cpu_load ? s.cpu_load.join(', ') : '-';
|
|
|
- document.getElementById('side-cpu-bar').title = `Container: ${pct}% | Host Loadavg: ${loadStr} (${s.cpu_cores || 1} cores)`;
|
|
|
+ cpuPct = s.cpu_pct;
|
|
|
} else if (s.cpu_load && s.cpu_load.length > 0) {
|
|
|
- const cores = s.cpu_cores || 4;
|
|
|
- const pct = Math.min(100, Math.round((parseFloat(s.cpu_load[0]) / cores) * 100));
|
|
|
- document.getElementById('side-cpu-val').innerText = `${pct}%`;
|
|
|
- document.getElementById('side-cpu-bar').style.width = `${Math.max(4, pct)}%`;
|
|
|
+ const cores = s.cpu_cores || 1;
|
|
|
+ cpuPct = Math.min(100, Math.round((parseFloat(s.cpu_load[0]) / cores) * 100));
|
|
|
+ }
|
|
|
+ const cpuPctStr = `${cpuPct.toFixed(1)}%`;
|
|
|
+ const cpuWidth = `${Math.max(3, Math.min(100, cpuPct))}%`;
|
|
|
+ const loadStr = s.cpu_load ? s.cpu_load.join(', ') : '-';
|
|
|
+
|
|
|
+ // Sidebar CPU
|
|
|
+ const sideCpuVal = document.getElementById('side-cpu-val');
|
|
|
+ if (sideCpuVal) sideCpuVal.innerText = cpuPctStr;
|
|
|
+ const sideCpuBar = document.getElementById('side-cpu-bar');
|
|
|
+ if (sideCpuBar) {
|
|
|
+ sideCpuBar.style.width = cpuWidth;
|
|
|
+ sideCpuBar.title = `Container: ${cpuPctStr} | Host Loadavg: ${loadStr} (${s.cpu_cores || 1} cores)`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Dashboard CPU Card
|
|
|
+ const dashCpuVal = document.getElementById('dash-cpu-val');
|
|
|
+ if (dashCpuVal) dashCpuVal.innerText = cpuPctStr;
|
|
|
+ const dashCpuBar = document.getElementById('dash-cpu-bar');
|
|
|
+ if (dashCpuBar) {
|
|
|
+ dashCpuBar.style.width = cpuWidth;
|
|
|
+ if (cpuPct > 85) {
|
|
|
+ dashCpuBar.className = 'h-full rounded-full bg-rose-500 transition-all duration-500';
|
|
|
+ } else if (cpuPct > 65) {
|
|
|
+ dashCpuBar.className = 'h-full rounded-full bg-amber-500 transition-all duration-500';
|
|
|
+ } else {
|
|
|
+ dashCpuBar.className = 'h-full rounded-full bg-emerald-500 transition-all duration-500';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const dashCpuCores = document.getElementById('dash-cpu-cores');
|
|
|
+ if (dashCpuCores) dashCpuCores.innerText = `${s.cpu_cores || 1} Cores`;
|
|
|
+ const dashCpuLoad = document.getElementById('dash-cpu-load');
|
|
|
+ if (dashCpuLoad) dashCpuLoad.innerText = loadStr;
|
|
|
+ const dashCpuStatus = document.getElementById('dash-cpu-status');
|
|
|
+ if (dashCpuStatus) {
|
|
|
+ if (cpuPct > 85) {
|
|
|
+ dashCpuStatus.innerText = 'High';
|
|
|
+ dashCpuStatus.className = 'text-[11px] font-semibold text-rose-400 uppercase px-2 py-0.5 rounded bg-rose-500/10';
|
|
|
+ } else if (cpuPct > 65) {
|
|
|
+ dashCpuStatus.innerText = 'Heavy';
|
|
|
+ dashCpuStatus.className = 'text-[11px] font-semibold text-amber-400 uppercase px-2 py-0.5 rounded bg-amber-500/10';
|
|
|
+ } else {
|
|
|
+ dashCpuStatus.innerText = 'Normal';
|
|
|
+ dashCpuStatus.className = 'text-[11px] font-semibold text-emerald-400 uppercase px-2 py-0.5 rounded bg-emerald-500/10';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Compute RAM Metrics
|
|
|
+ const memPct = Math.round(s.mem_usage_pct || 0);
|
|
|
+ const memPctStr = `${memPct}%`;
|
|
|
+ const memWidth = `${Math.max(3, Math.min(100, memPct))}%`;
|
|
|
+ const usedMB = s.mem_used_mb || 0;
|
|
|
+ const totalMB = s.mem_total_mb || 0;
|
|
|
+ const freeMB = totalMB > usedMB ? totalMB - usedMB : 0;
|
|
|
+
|
|
|
+ function fmtMemMB(mb) {
|
|
|
+ if (mb >= 1024) {
|
|
|
+ return `${(mb / 1024).toFixed(1)} GB`;
|
|
|
+ }
|
|
|
+ return `${mb} MB`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Sidebar RAM
|
|
|
+ const sideRamVal = document.getElementById('side-ram-val');
|
|
|
+ if (sideRamVal) sideRamVal.innerText = memPctStr;
|
|
|
+ const sideRamBar = document.getElementById('side-ram-bar');
|
|
|
+ if (sideRamBar) sideRamBar.style.width = memWidth;
|
|
|
+
|
|
|
+ // Dashboard RAM Card
|
|
|
+ const dashRamVal = document.getElementById('dash-ram-val');
|
|
|
+ if (dashRamVal) dashRamVal.innerText = memPctStr;
|
|
|
+ const dashRamBar = document.getElementById('dash-ram-bar');
|
|
|
+ if (dashRamBar) {
|
|
|
+ dashRamBar.style.width = memWidth;
|
|
|
+ if (memPct > 85) {
|
|
|
+ dashRamBar.className = 'h-full rounded-full bg-rose-500 transition-all duration-500';
|
|
|
+ } else if (memPct > 70) {
|
|
|
+ dashRamBar.className = 'h-full rounded-full bg-amber-500 transition-all duration-500';
|
|
|
+ } else {
|
|
|
+ dashRamBar.className = 'h-full rounded-full bg-indigo-500 transition-all duration-500';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const dashRamUsedTotal = document.getElementById('dash-ram-used-total');
|
|
|
+ if (dashRamUsedTotal) {
|
|
|
+ dashRamUsedTotal.innerText = `${fmtMemMB(usedMB)} / ${fmtMemMB(totalMB)}`;
|
|
|
+ }
|
|
|
+ const dashRamFree = document.getElementById('dash-ram-free');
|
|
|
+ if (dashRamFree) {
|
|
|
+ dashRamFree.innerText = fmtMemMB(freeMB);
|
|
|
+ }
|
|
|
+ const dashRamStatus = document.getElementById('dash-ram-status');
|
|
|
+ if (dashRamStatus) {
|
|
|
+ if (memPct > 85) {
|
|
|
+ dashRamStatus.innerText = 'High';
|
|
|
+ dashRamStatus.className = 'text-[11px] font-semibold text-rose-400 uppercase px-2 py-0.5 rounded bg-rose-500/10';
|
|
|
+ } else {
|
|
|
+ dashRamStatus.innerText = 'Active';
|
|
|
+ dashRamStatus.className = 'text-[11px] font-semibold text-indigo-400 uppercase px-2 py-0.5 rounded bg-indigo-500/10';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- document.getElementById('side-ram-val').innerText = `${Math.round(s.mem_usage_pct || 0)}%`;
|
|
|
- document.getElementById('side-ram-bar').style.width = `${Math.max(5, Math.round(s.mem_usage_pct || 0))}%`;
|
|
|
-
|
|
|
- // Dashboard Stats
|
|
|
- document.getElementById('stat-ifaces-up').innerText = s.up_ifaces || 0;
|
|
|
- document.getElementById('stat-ifaces-total').innerText = `${s.total_ifaces || 0} Total`;
|
|
|
- document.getElementById('stat-ifaces-down').innerText = `${s.down_ifaces || 0} DOWN`;
|
|
|
- document.getElementById('stat-vlans-count').innerText = s.vlan_ifaces || 0;
|
|
|
+ // Legacy Dashboard Stats (Safe checks)
|
|
|
+ const elIfacesUp = document.getElementById('stat-ifaces-up');
|
|
|
+ if (elIfacesUp) elIfacesUp.innerText = s.up_ifaces || 0;
|
|
|
+ const elIfacesTot = document.getElementById('stat-ifaces-total');
|
|
|
+ if (elIfacesTot) elIfacesTot.innerText = `${s.total_ifaces || 0} Total`;
|
|
|
+ const elIfacesDown = document.getElementById('stat-ifaces-down');
|
|
|
+ if (elIfacesDown) elIfacesDown.innerText = `${s.down_ifaces || 0} DOWN`;
|
|
|
+ const elVlans = document.getElementById('stat-vlans-count');
|
|
|
+ if (elVlans) elVlans.innerText = s.vlan_ifaces || 0;
|
|
|
|
|
|
// VPN Status Indicators
|
|
|
if (v) {
|