ADR-0021: Agent-Intervall 6h+Jitter, Debug-Modus, Health-Monitoring
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
eb828fcd06
commit
a48ef99739
104
adr/0021-agent-intervall-debug-modus-health-monitoring.md
Normal file
104
adr/0021-agent-intervall-debug-modus-health-monitoring.md
Normal file
@ -0,0 +1,104 @@
|
||||
# ADR-0021: Agent-Standardintervall 6h+Jitter, Debug-Modus, Health-Monitoring
|
||||
|
||||
**Status:** Beschlossen
|
||||
**Datum:** 26.08.2026
|
||||
|
||||
## Kontext
|
||||
|
||||
Der Provisioning-Agent (`provisioning-agent/agent.py`) checkte bislang alle
|
||||
5 Minuten ein (`AGENT_POLL_INTERVAL_SECONDS`, fest über eine
|
||||
Server-Umgebungsvariable) — sinnvoll für die Entwicklungsphase, aber bei
|
||||
einer wachsenden Geräteflotte unnötig häufig für den Normalbetrieb. Es gab
|
||||
außerdem keine Möglichkeit, ein einzelnes Gerät gezielt kurzfristig
|
||||
engmaschiger abzufragen (z.B. um eine frisch zugewiesene Rolle zeitnah zu
|
||||
beobachten), ohne das Intervall global zu ändern. Und: der Agent sammelte
|
||||
nur einmalig bei der Installation eine statische Hardware-Inventur
|
||||
(`hardware_snapshots`, siehe `10_hardware.sh`) — es gab keine periodische
|
||||
Sicht auf den *aktuellen* Gerätezustand (Diskbelegung, Auslastung, Uptime).
|
||||
|
||||
Der Boot-Checkin selbst (Agent meldet sich direkt beim Start) war entgegen
|
||||
der ursprünglichen Annahme bereits vorhanden — `agent.py:main()` ruft
|
||||
`run_once()` grundsätzlich vor der ersten `sleep()`-Anweisung auf, daher
|
||||
hier nicht angefasst.
|
||||
|
||||
## Entscheidung
|
||||
|
||||
**Standardintervall:** `AGENT_POLL_INTERVAL_SECONDS`-Default von 300 auf
|
||||
21600 (6 Stunden) angehoben. **Jitter** kommt bewusst aus dem Agenten
|
||||
selbst, nicht vom Server (der kennt keinen sinnvollen Zufallszustand pro
|
||||
Gerät): `agent.py`s `main()`-Loop addiert 0–30 Minuten zufällig auf das
|
||||
zurückgelieferte Intervall, aber **nur** wenn es „groß" ist
|
||||
(`JITTER_THRESHOLD_SECONDS = 3600`) — der kurze Debug-Modus (60s) und der
|
||||
Fallback-Retry bei Fehlern (`FALLBACK_INTERVAL_SECONDS = 60`) bleiben
|
||||
bewusst unverjittert, sonst würde Jitter genau den Zweck des schnellen
|
||||
Debug-Zyklus untergraben.
|
||||
|
||||
**Debug-Modus:** neue Spalte `devices.debug_mode_until` (Migration
|
||||
`0022_agent_debug_mode_und_health.sql`) ist der einzige Zustand — kein
|
||||
separates Enum, kein Cron-Job zum Zurücksetzen. `agent_checkin()`
|
||||
vergleicht bei jeder Anfrage `debug_mode_until` mit der aktuellen Zeit und
|
||||
liefert `poll_interval_seconds` entsprechend (60s im Debug-Modus, sonst
|
||||
6h) — das automatische Zurückfallen nach Ablauf passiert rein durch
|
||||
Zeitvergleich, ohne dass irgendetwas aktiv zurückgesetzt werden muss.
|
||||
Aktivieren (`POST /api/v1/devices/{id}/debug-mode`, setzt `now()+6h`) und
|
||||
Deaktivieren (`DELETE`, setzt `NULL`) sind eigene, dünne Endpunkte, gegen
|
||||
`require_service_token()` wie üblich — Organisationszugehörigkeitsprüfung
|
||||
bleibt Aufgabe der aufrufenden Kundenplattform
|
||||
(`find_device_in_organization()`), nicht dieses Endpunkts. Bewusst **kein
|
||||
zusätzliches Rechte-Gate**: jeder eingeloggte Nutzer der eigenen
|
||||
Organisation darf den Debug-Modus für die eigenen Geräte umschalten,
|
||||
gleiches Muster wie die bestehenden Auftragskatalog-Aktionen.
|
||||
|
||||
**Health-Monitoring:** sechs neue, nullable `devices`-Spalten
|
||||
(`health_disk_used_percent`, `health_ram_used_percent`,
|
||||
`health_uptime_seconds`, `health_load_1m/5m/15m`, `health_collected_at`) —
|
||||
halten bewusst nur den jeweils letzten Stand, keine wachsende Historie
|
||||
(konsistent mit dem Plattenplatz-Bewusstsein an anderer Stelle, siehe
|
||||
`iso_builds`-Aufräumung). Der Agent sammelt die Werte bei jedem Checkin
|
||||
rein über Python-Stdlib (`shutil.disk_usage("/")`, `/proc/meminfo`,
|
||||
`/proc/uptime`, `os.getloadavg()`) — keine neue Abhängigkeit, jeder
|
||||
Einzelwert einzeln per `try/except`, damit ein fehlschlagender Wert (z.B.
|
||||
Load Average auf einem ungewöhnlichen System) die übrigen nicht
|
||||
verhindert. Bewusst ausgeschlossen: Temperatur/SMART-Werte — hätten
|
||||
zusätzliche Pakete/Berechtigungen gebraucht, war nicht Teil der
|
||||
25./26.08.-Planung.
|
||||
|
||||
`agent_checkin()` schreibt `agent_last_checkin` und die Health-Felder in
|
||||
einem kombinierten `UPDATE ... RETURNING debug_mode_until` statt separater
|
||||
Round-Trips. Fehlt das `health`-Objekt in einem einzelnen Checkin (z.B.
|
||||
Sammel-Fehler im Agenten), bleiben die zuvor gespeicherten Health-Werte
|
||||
unverändert stehen statt auf `NULL` zurückzufallen — ein `CASE WHEN`
|
||||
pro Spalte statt eines bedingungslosen Überschreibens.
|
||||
|
||||
`fetch_devices_for_organization()`/`fetch_all_devices()` liefern
|
||||
`debug_mode_until` und `health` jetzt mit aus (gemeinsame SQL-Spaltenliste
|
||||
`GERAETE_HEALTH_SPALTEN_SQL`, gemeinsame Aufbereitung
|
||||
`_health_felder_aus_row()`) — Kundenplattform braucht dafür keinen
|
||||
zusätzlichen Request, das Device-Dict aus der ohnehin schon vorhandenen
|
||||
Besitz-Validierung (`find_device_in_organization()`) trägt die Felder
|
||||
direkt mit.
|
||||
|
||||
**Kundenplattform-UI:** neue Sektion „Debug-Modus" auf der
|
||||
Auftragskatalog-Seite (Kunden- **und** Admin-Bereich, gleiches
|
||||
`zurueck_url`-Präfix-Muster wie die bestehenden Select/Deselect-Formulare
|
||||
aus ADR-0015), neue Sektion „Aktueller Zustand (letzter Checkin)" auf der
|
||||
Hardware-Seite (klar getrennt von der bestehenden statischen
|
||||
Install-Zeit-Inventur), Debug-Badge in beiden Geräte-Listen, und „Zuletzt
|
||||
gemeldet" jetzt auch auf der Log-Seite (vorher nur in der Geräteliste
|
||||
sichtbar, nicht in der Detail-Historie).
|
||||
|
||||
## Konsequenzen
|
||||
|
||||
Migration `0022_agent_debug_mode_und_health.sql` (8 neue `devices`-Spalten,
|
||||
alle nullable, kein Backfill nötig). Kein neuer Cron/Scheduler-Prozess für
|
||||
den Debug-Modus-Rückfall — reine Zeitvergleichslogik im bestehenden
|
||||
Checkin-Pfad.
|
||||
|
||||
Live auf anode verifiziert: `agent_checkin()` mit Health-Payload
|
||||
durchlaufen, `debug_mode_until` korrekt in `poll_interval_seconds`
|
||||
übersetzt (Debug-Endpunkt aktiviert → nächster Checkin liefert 60s, nach
|
||||
Ablauf/Deaktivieren wieder 21600s). `collect_health()` gegen ein echtes
|
||||
Linux-System (enterprise) getestet, liefert plausible Werte ohne
|
||||
Zusatzpaket. UI-Änderungen lokal mit gemocktem Kontext gerendert
|
||||
(Debug-Toggle in beiden Zuständen, Health-Sektion mit/ohne Daten, Log-Seite
|
||||
mit Zeitstempel).
|
||||
Loading…
x
Reference in New Issue
Block a user