#!/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, }