const timeElement = document.querySelector("#local-time"); const refreshElement = document.querySelector("#refresh-indicator"); const fields = { cpu: document.querySelector("#cpu-value"), memory: document.querySelector("#memory-value"), uptime: document.querySelector("#uptime-value"), containers: document.querySelector("#containers-value"), targets: document.querySelector("#targets-value"), telemetry: document.querySelector("#telemetry-value"), opsCpu: document.querySelector("#ops-cpu-value"), opsMemory: document.querySelector("#ops-memory-value"), opsUptime: document.querySelector("#ops-uptime-value"), opsContainers: document.querySelector("#ops-containers-value"), opsTargets: document.querySelector("#ops-targets-value"), }; const telemetryHistory = { cpu: [], memory: [], }; let lastSuccessfulUpdate = null; let requestInFlight = false; function updateClock() { const now = new Date(); timeElement.textContent = new Intl.DateTimeFormat("en-US", { timeZone: "America/Detroit", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, }).format(now); } function formatUptime(totalSeconds) { const seconds = Math.max(0, Number(totalSeconds) || 0); const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) return days + "d " + hours + "h"; if (hours > 0) return hours + "h " + minutes + "m"; return minutes + "m"; } function setUnavailable() { for (const key of ["cpu", "memory", "uptime", "containers", "targets"]) { fields[key].textContent = "--"; } fields.telemetry.textContent = "UNAVAILABLE"; fields.telemetry.classList.add("metric-error"); fields.opsCpu.textContent = "--%"; fields.opsMemory.textContent = "--%"; fields.opsUptime.textContent = "--"; fields.opsContainers.textContent = "--"; fields.opsTargets.textContent = "--"; refreshElement.textContent = "TELEMETRY UNAVAILABLE"; refreshElement.classList.add("telemetry-error"); } function renderOpsBars(elementId, values) { const container = document.querySelector(elementId); if (!container) return; container.replaceChildren(); values.forEach((value) => { const bar = document.createElement("i"); bar.style.setProperty("--bar-height", Math.max(4, Math.min(100, value)) + "%"); container.appendChild(bar); }); } function pushHistory(series, value) { series.push(value); if (series.length > 24) series.shift(); } function renderStatus(data) { const cpu = Number(data.host.cpu_percent); const memory = Number(data.host.memory_percent); const uptime = formatUptime(data.host.uptime_seconds); const containers = String(data.containers.running); const targets = data.prometheus.up + "/" + data.prometheus.total; fields.cpu.textContent = cpu.toFixed(1); fields.memory.textContent = memory.toFixed(1); fields.uptime.textContent = uptime; fields.containers.textContent = containers; fields.targets.textContent = targets; fields.telemetry.textContent = "LIVE"; fields.opsCpu.textContent = cpu.toFixed(1) + "%"; fields.opsMemory.textContent = memory.toFixed(1) + "%"; fields.opsUptime.textContent = uptime; fields.opsContainers.textContent = containers; fields.opsTargets.textContent = targets; pushHistory(telemetryHistory.cpu, cpu); pushHistory(telemetryHistory.memory, memory); renderOpsBars("#ops-cpu-bars", telemetryHistory.cpu); renderOpsBars("#ops-memory-bars", telemetryHistory.memory); fields.telemetry.classList.remove("metric-error"); refreshElement.classList.remove("telemetry-error"); lastSuccessfulUpdate = Date.now(); updateRefreshLabel(); } function updateRefreshLabel() { if (!lastSuccessfulUpdate) return; const ageSeconds = Math.max(0, Math.floor((Date.now() - lastSuccessfulUpdate) / 1000)); refreshElement.textContent = "LIVE TELEMETRY | UPDATED " + String(ageSeconds).padStart(2, "0") + "s AGO"; } async function refreshTelemetry() { if (requestInFlight) return; requestInFlight = true; try { const response = await fetch("/api/status", { cache: "no-store", headers: { "Accept": "application/json" }, }); if (!response.ok) throw new Error("status " + response.status); const data = await response.json(); if (!data.ok) throw new Error("telemetry unavailable"); renderStatus(data); } catch (error) { console.error("ByteGeist telemetry request failed:", error); setUnavailable(); } finally { requestInFlight = false; } } updateClock(); refreshTelemetry(); window.setInterval(updateClock, 1000); window.setInterval(updateRefreshLabel, 1000); window.setInterval(refreshTelemetry, 15000);