Files
homelabstack/scripts/check_uptime.py
T

89 lines
3.2 KiB
Python

import urllib.request
import re
import json
def check_uptime():
try:
# Fetch status page to extract monitor IDs and names
req = urllib.request.Request(
"https://uptime.ginnoir.com/status/default",
headers={"User-Agent": "Mozilla/5.0"}
)
with urllib.request.urlopen(req) as response:
html = response.read().decode('utf-8')
# Regex to find monitor mapping: {'id':29,'name':'auth.ginnoir.com','sendUrl':0,'type':'http'}
monitors = {}
matches = re.findall(r"\{'id':(\d+),'name':'([^']+)','sendUrl':\d+,'type':'[^']+'\}", html)
for mon_id, mon_name in matches:
monitors[int(mon_id)] = mon_name
if not monitors:
print("No monitors found in status page HTML.")
return
# Fetch heartbeats
req_hb = urllib.request.Request(
"https://uptime.ginnoir.com/api/status-page/heartbeat/default",
headers={"User-Agent": "Mozilla/5.0"}
)
with urllib.request.urlopen(req_hb) as response:
hb_data = json.loads(response.read().decode('utf-8'))
hb_list = hb_data.get("heartbeatList", {})
up_count = 0
down_count = 0
other_count = 0
status_summary = []
down_services = []
for mon_id, name in sorted(monitors.items(), key=lambda x: x[1]):
# Get heartbeats for this monitor
beats = hb_list.get(str(mon_id), [])
if not beats:
status_summary.append(f"- {name}: NO_DATA")
other_count += 1
continue
# Get latest beat
latest = beats[-1]
status_val = latest.get("status")
ping = latest.get("ping")
msg = latest.get("msg", "")
if status_val == 1:
status_str = "UP"
up_count += 1
ping_str = f" ({ping}ms)" if ping is not None else ""
status_summary.append(f"- {name}: {status_str}{ping_str}")
elif status_val == 0:
status_str = "DOWN"
down_count += 1
err_msg = f" - {msg}" if msg else ""
status_summary.append(f"- {name}: {status_str}{err_msg}")
down_services.append(name)
else:
status_str = "DEGRADED"
other_count += 1
err_msg = f" - {msg}" if msg else ""
status_summary.append(f"- {name}: {status_str}{err_msg}")
down_services.append(name)
print("=== MONITOR STATUS REPORT ===")
if down_services:
print(f"ALERT: {len(down_services)} service(s) down or degraded!")
print(f"DOWN SERVICES: {', '.join(down_services)}")
else:
print("STATUS: OK")
print(f"STATS: UP={up_count}, DOWN={down_count}, OTHER={other_count}")
print("\nDETAILS:")
print("\n".join(status_summary))
except Exception as e:
print(f"Error checking status: {e}")
if __name__ == "__main__":
check_uptime()