83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
import re
|
|
import sqlite3
|
|
import subprocess
|
|
|
|
CONTAINER = "uptime-kuma"
|
|
DATABASE = "/opt/docker/uptime-kuma/data/kuma.db"
|
|
|
|
|
|
def _failure(detail):
|
|
return {
|
|
"state": "offline", "health": "unavailable", "summary": "Unavailable",
|
|
"detail": detail, "container_available": False, "version": None,
|
|
"active_monitors": 0, "up_count": 0, "down_count": 0, "unknown_count": 0,
|
|
}
|
|
|
|
|
|
def _container_info():
|
|
result = subprocess.run(
|
|
["docker", "inspect", "--format",
|
|
"{{.State.Status}}\t{{.State.Health.Status}}\t{{.Config.Image}}",
|
|
CONTAINER], capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
return None
|
|
fields = result.stdout.strip().split("\t")
|
|
if len(fields) != 3:
|
|
return None
|
|
status, health, image = fields
|
|
match = re.search(r":([^:@]+)$", image)
|
|
return status, health, match.group(1) if match else None
|
|
|
|
|
|
def _database_counts():
|
|
connection = sqlite3.connect(f"file:{DATABASE}?mode=ro", uri=True, timeout=5)
|
|
try:
|
|
rows = connection.execute(
|
|
"""
|
|
SELECT m.id,
|
|
(SELECT h.status FROM heartbeat h
|
|
WHERE h.monitor_id = m.id
|
|
ORDER BY h.id DESC LIMIT 1) AS latest_status
|
|
FROM monitor m
|
|
WHERE m.active = 1
|
|
"""
|
|
).fetchall()
|
|
finally:
|
|
connection.close()
|
|
counts = {"active": len(rows), "up": 0, "down": 0, "unknown": 0}
|
|
for _, status in rows:
|
|
if status == 1:
|
|
counts["up"] += 1
|
|
elif status == 0:
|
|
counts["down"] += 1
|
|
else:
|
|
counts["unknown"] += 1
|
|
return counts
|
|
|
|
|
|
def collect():
|
|
container = _container_info()
|
|
if container is None:
|
|
return _failure("Uptime Kuma container unavailable")
|
|
container_status, container_health, version = container
|
|
if container_status != "running":
|
|
return _failure("Uptime Kuma container is not running")
|
|
try:
|
|
counts = _database_counts()
|
|
except (OSError, sqlite3.Error):
|
|
return _failure("Uptime Kuma aggregate query unavailable")
|
|
active, up = counts["active"], counts["up"]
|
|
down, unknown = counts["down"], counts["unknown"]
|
|
degraded = container_health == "unhealthy" or down > 0 or unknown > 0
|
|
version_detail = f"Uptime Kuma {version}" if version else "Uptime Kuma"
|
|
return {
|
|
"state": "warning" if degraded else "online",
|
|
"health": "partial" if degraded else "healthy",
|
|
"summary": f"{up}/{active} monitors up",
|
|
"detail": f"{version_detail} · edge01 monitoring operational",
|
|
"container_available": True, "container_health": container_health,
|
|
"version": version, "active_monitors": active, "up_count": up,
|
|
"down_count": down, "unknown_count": unknown,
|
|
}
|