diff --git a/index.html b/index.html index 5a428c7..5389379 100644 --- a/index.html +++ b/index.html @@ -119,11 +119,32 @@
- GRAFANA / BYTEGEIST OPERATIONS - FULL RES ↗ + BYTEGEIST / LIVE OPERATIONS + PROMETHEUS / NODE EXPORTER / CADVISOR
- Grafana operations dashboard snapshot from the ByteGeist monitoring stack -

CAPTURED OCT 2026 · GRAFANA OPERATIONS SNAPSHOT · LIVE VALUES ABOVE REFRESH EVERY 15s

+
+
+
+ CPU LOAD + --% +
+ +
+
+
+ MEMORY + --% +
+ +
+
+
HOST UPTIME--
+
CONTAINERS--
+
SCRAPE TARGETS--
+
REFRESH15s
+
+
+

LIVE OPERATIONS VIEW · VALUES COME FROM THE SAME SANITIZED /API/STATUS TELEMETRY FEED

diff --git a/script.js b/script.js index a7a49b8..46c8caa 100644 --- a/script.js +++ b/script.js @@ -8,6 +8,16 @@ const fields = { 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; @@ -41,17 +51,56 @@ function setUnavailable() { } 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) { - fields.cpu.textContent = Number(data.host.cpu_percent).toFixed(1); - fields.memory.textContent = Number(data.host.memory_percent).toFixed(1); - fields.uptime.textContent = formatUptime(data.host.uptime_seconds); - fields.containers.textContent = String(data.containers.running); - fields.targets.textContent = data.prometheus.up + "/" + data.prometheus.total; + 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"); diff --git a/style.css b/style.css index bc01dda..3da7a9e 100644 --- a/style.css +++ b/style.css @@ -460,6 +460,94 @@ h1 { border: 1px solid #20232a; } +.live-ops-panel { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1px; + border: 1px solid #20232a; + background: var(--line); +} + +.ops-chart, +.ops-status-grid { + background: #070a0f; +} + +.ops-chart { + min-height: 150px; + padding: 16px; +} + +.ops-chart-head { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 12px; +} + +.ops-chart-head span, +.ops-status-grid span { + color: var(--dim); + font: .56rem var(--mono); + letter-spacing: .08em; +} + +.ops-chart-head strong { + color: var(--green); + font: 500 1.1rem var(--mono); +} + +.ops-bars { + height: 86px; + margin-top: 18px; + display: flex; + align-items: flex-end; + gap: 4px; + border-bottom: 1px solid #26313c; + background: + linear-gradient(to top, transparent 24%, #121820 25%, transparent 26%, transparent 49%, #121820 50%, transparent 51%, transparent 74%, #121820 75%, transparent 76%); +} + +.ops-bars i { + flex: 1 1 0; + min-width: 3px; + height: var(--bar-height, 4%); + background: var(--green); + opacity: .72; + transition: height .25s ease; +} + +.ops-chart:nth-child(2) .ops-bars i { + background: var(--cyan); +} + +.ops-status-grid { + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1px; + background: var(--line); +} + +.ops-status-grid div { + min-height: 70px; + padding: 13px 16px; + background: #080c12; +} + +.ops-status-grid strong { + display: block; + margin-top: 9px; + color: var(--muted); + font: 500 .82rem var(--mono); +} + +.window-bar small { + color: var(--dim); + font: .52rem var(--mono); + letter-spacing: .05em; +} + .activity-panel { padding: 24px 18px; border-left: 1px solid var(--line); @@ -1191,6 +1279,19 @@ footer { grid-template-columns: 1fr 1fr; } + .live-ops-panel { + grid-template-columns: 1fr; + } + + .ops-status-grid { + grid-column: 1; + grid-template-columns: 1fr 1fr; + } + + .window-bar small { + display: none; + } + .metric { min-height: 112px; }