diff --git a/.gitignore b/.gitignore index 78d00ab..a32754f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,4 @@ # Бинарники (только в корне проекта, не директории cmd/) -/iot-operator -/mqtt-bridge -/kafka-consumer -/sqs-consumer bin/ ws-probe/ws-probe /iot-service diff --git a/internal/service/api/ui/iot-admin.html b/internal/service/api/ui/iot-admin.html index 68d503a..b30da89 100644 --- a/internal/service/api/ui/iot-admin.html +++ b/internal/service/api/ui/iot-admin.html @@ -1,9 +1,9 @@ @@ -95,23 +95,6 @@ .card-ok { color: #34d399; } .card-err { color: #f87171; } - /* Pod status card */ - .pod-card { - background: #001929; border: 1px solid #0b2d50; border-radius: 10px; - padding: 20px; display: flex; flex-direction: column; gap: 8px; - } - .pod-name { font-size: 13px; font-weight: 600; color: #7fc8f8; font-family: monospace; } - .pod-row { display: flex; justify-content: space-between; font-size: 12px; } - .pod-label { color: #6b8eaa; } - .pod-val { color: #e2ecf6; } - .badge { - display: inline-block; padding: 2px 8px; border-radius: 4px; - font-size: 11px; font-weight: 700; - } - .badge-ok { background: #052e16; color: #34d399; border: 1px solid #064e3b; } - .badge-warn { background: #2d1c00; color: #f59e0b; border: 1px solid #4d3000; } - .badge-err { background: #300; color: #f87171; border: 1px solid #500; } - /* Tenant table */ .tenant-table { width: 100%; border-collapse: collapse; font-size: 13px; } .tenant-table th { @@ -142,18 +125,6 @@ /* Last updated */ .last-updated { font-size: 12px; color: #2d5070; text-align: center; margin-top: 16px; } - /* Status dot */ - .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; } - .dot-ok { background: #34d399; } - .dot-warn { background: #f59e0b; } - .dot-err { background: #f87171; } - - /* Kafka lag bar */ - .lag-bar-wrap { background: #001120; border-radius: 4px; height: 6px; margin-top: 8px; overflow: hidden; } - .lag-bar { height: 100%; border-radius: 4px; transition: width 0.5s; min-width: 2px; } - .lag-bar-ok { background: #34d399; } - .lag-bar-warn { background: #f59e0b; } - /* Spinner */ .spinner { border: 3px solid #0b2d50; border-top-color: #1a7fd4; @@ -223,26 +194,26 @@ `; return; } - - const lag = kafka.consumer_lag || 0; - const latest = kafka.latest_offset || 0; - const committed = kafka.committed_offset || 0; - const lagClass = lag === 0 ? 'card-ok' : lag < 100 ? 'card-warn' : 'card-err'; - const barClass = lag === 0 ? 'lag-bar-ok' : 'lag-bar-warn'; - const barWidth = latest > 0 ? Math.max(2, Math.round((committed / latest) * 100)) : 100; - + const pending = sqs.approximate_messages || 0; + const inFlight = sqs.approximate_messages_not_visible || 0; + const pendingClass = pending === 0 ? 'card-ok' : pending < 100 ? 'card-warn' : 'card-err'; el.innerHTML = `
-
Consumer Lag
-
${lag}
-
iot-pg-consumer / iot.telemetry
-
+
Ожидают обработки
+
${pending.toLocaleString()}
+
ApproximateNumberOfMessages
-
Latest Offset (всего прошло)
-
${latest.toLocaleString()}
-
Kafka log end offset
-
-
-
Committed Offset
-
${committed.toLocaleString()}
-
Consumer обработал
+
В обработке
+
${inFlight.toLocaleString()}
+
ApproximateNumberOfMessagesNotVisible
`; } -// Pods section -function renderPods(pods) { - const el = document.getElementById('podCards'); - el.innerHTML = ''; - - const labels = { - 'iot-mqtt-bridge': 'MQTT Bridge', - 'iot-kafka-consumer': 'Kafka Consumer' - }; - - for (const [key, pod] of Object.entries(pods)) { - const title = labels[key] || key; - if (pod.error || pod.status === 'not found') { - el.innerHTML += ` -
-
${esc(title)}
-
${esc(pod.error || 'Pod not found')}
-
`; - continue; - } - - const readyBadge = pod.ready - ? 'Ready' - : 'Not Ready'; - const restartColor = pod.restarts > 5 ? 'card-err' : pod.restarts > 0 ? 'card-warn' : 'card-ok'; - - el.innerHTML += ` -
-
- ${esc(title)} -
-
Pod${esc(pod.name)}
-
Phase${esc(pod.phase)} ${readyBadge}
-
Restarts${pod.restarts}
-
Age${esc(pod.age)}
-
`; - } +// Рантайм процесса +function renderRuntime(rt) { + const el = document.getElementById('runtimeCards'); + const uptime = rt.uptime_sec || 0; + const h = Math.floor(uptime / 3600); + const m = Math.floor((uptime % 3600) / 60); + const s = uptime % 60; + const uptimeStr = h > 0 ? `${h}ч ${m}м` : m > 0 ? `${m}м ${s}с` : `${s}с`; + el.innerHTML = ` +
+
Версия
+
${esc(rt.version || '—')}
+
iot-service
+
+
+
Uptime
+
${uptimeStr}
+
с ${esc(rt.started_at || '—')}
+
`; } // Postgres section