monitoring: Cody-Watchdog als no_agent-Script (keine LLM-Kosten)
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 13m57s
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 13m57s
- Ersetzt Agent-Watchdog (deepseek-v4-pro, alle 5 Min = teuer) - Reines Python-Script: pgrep Hermes + Profil-Check - Still bei OK, Alarm nur bei Problemen - /usr/bin/bash.00 Kosten, Peak-Zeiten irrelevant
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Cody-Watchdog — Prüft ob das Cody-Profil läuft (Hermes Daemon + Profil intakt).
|
||||
|
||||
Ausgabe: LEER wenn alles OK. Nur bei Problemen wird ein Alarm-Text ausgegeben.
|
||||
Läuft als Hermes-Cronjob (no_agent=True, alle 5 Minuten).
|
||||
Kostet $0.00 — kein LLM-Aufruf.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
|
||||
CODY_PROFILE = os.path.expanduser("~/.hermes/profiles/cody")
|
||||
CONFIG_FILE = os.path.join(CODY_PROFILE, "config.yaml")
|
||||
|
||||
|
||||
def check_hermes_daemon():
|
||||
"""Prüfe ob mindestens ein Hermes-Prozess läuft."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["pgrep", "-f", "hermes"],
|
||||
capture_output=True, text=True, timeout=5
|
||||
)
|
||||
pids = [p for p in result.stdout.strip().split("\n") if p]
|
||||
return len(pids) > 0, pids
|
||||
except Exception as e:
|
||||
return False, []
|
||||
|
||||
|
||||
def check_profile():
|
||||
"""Prüfe ob Cody-Profil existiert und Config lesbar ist."""
|
||||
if not os.path.isdir(CODY_PROFILE):
|
||||
return False, f"Profil-Verzeichnis fehlt: {CODY_PROFILE}"
|
||||
if not os.path.isfile(CONFIG_FILE):
|
||||
return False, f"Config fehlt: {CONFIG_FILE}"
|
||||
try:
|
||||
with open(CONFIG_FILE, "r") as f:
|
||||
content = f.read()
|
||||
if not content.strip():
|
||||
return False, "Config ist leer"
|
||||
# Minimaler YAML-Check: muss "profile" oder "model" enthalten
|
||||
if "cody" not in content.lower() and "model" not in content.lower():
|
||||
return False, "Config scheint nicht für Cody-Profil"
|
||||
return True, None
|
||||
except Exception as e:
|
||||
return False, f"Config nicht lesbar: {e}"
|
||||
|
||||
|
||||
def main():
|
||||
now = datetime.now(timezone.utc).strftime("%d.%m.%Y %H:%M UTC")
|
||||
alerts = []
|
||||
|
||||
# 1. Hermes-Daemon
|
||||
daemon_ok, pids = check_hermes_daemon()
|
||||
if not daemon_ok:
|
||||
alerts.append("❌ Kein Hermes-Prozess gefunden — Daemon down")
|
||||
|
||||
# 2. Cody-Profil
|
||||
profile_ok, profile_err = check_profile()
|
||||
if not profile_ok:
|
||||
alerts.append(f"❌ Cody-Profil fehlerhaft: {profile_err}")
|
||||
|
||||
# 3. Gateway (optional: nur prüfen wenn Daemon läuft)
|
||||
if daemon_ok:
|
||||
try:
|
||||
gw = subprocess.run(
|
||||
["pgrep", "-f", "hermes.*gateway.*cody"],
|
||||
capture_output=True, text=True, timeout=5
|
||||
)
|
||||
if not gw.stdout.strip():
|
||||
# Gateway nicht aktiv — bei on-demand normal, nur warnen wenn Profil da ist
|
||||
pass # Cody ist on-demand, kein Alarm
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if alerts:
|
||||
print(f"🚨 Cody-Watchdog-Alarm {now}\n" + "\n".join(alerts))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user