Files

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,
}