English Version
Zurück zur Übersicht
| Baustein |
Einsatz |
| PHP 8.4 und Symfony 8.1 |
Anwendung |
| FrankenPHP (Caddy) |
Webserver, auf Live im Worker-Modus |
| SQLite über Doctrine ORM |
Datenbank und Warteschlange |
| Symfony Messenger |
Asynchrone Ausführung von Checks und E-Mail-Versand |
| Symfony Scheduler |
Minütliche Fälligkeitsprüfung und tägliche Bereinigung |
| Twig und Tailwind CSS |
Oberfläche |
graph LR
U["Admin im Browser"] -->|"HTTP Basic Auth"| APP["app: Oberfläche und API"]
APP --> DB["SQLite: data.db"]
SCH["scheduler"] -->|"jede Minute"| Q["Warteschlange in SQLite"]
Q --> W["worker"]
W -->|"HTTP, TCP, DNS, Docker"| T["Überwachte Ziele"]
W -->|"SMTP"| M["Mail-Server"]
W --> DB
AG["agent"] -->|"Bearer-Token"| APP
| Dienst |
Befehl |
Aufgabe |
app |
FrankenPHP |
Oberfläche und Agenten-API |
worker |
php bin/console messenger:consume async notifications --time-limit=3600 --memory-limit=128M |
Führt Dashboard-Checks aus und versendet E-Mails |
scheduler |
php bin/console messenger:consume scheduler_checks --time-limit=3600 --memory-limit=128M --no-interaction |
Prüft jede Minute, welche Checks fällig sind, und räumt täglich auf |
agent |
php bin/console watchdog:agent:run |
Führt Agenten-Checks aus und meldet die Ergebnisse |
mailpit |
axllent/mailpit |
Mail-Fänger, nur lokal und auf Stage |
Alle Container außer agent und mailpit teilen sich das Volume mit /app/var und damit die SQLite-Datei. Ein einzelner Worker arbeitet die Nachrichten nacheinander ab. Checks mit langen Zeitlimits verzögern daher andere Checks.
sequenceDiagram
participant S as scheduler
participant Q as Warteschlange
participant W as worker
participant D as SQLite
participant M as SMTP
S->>Q: RunSiteChecks je fälligem Check
Q->>W: Nachricht
W->>D: Ergebnis speichern, Status vergleichen
W->>Q: MailNotification bei Statuswechsel
Q->>W: Nachricht
W->>M: eine E-Mail je Kontakt
- Der Scheduler prüft jede Minute alle aktiven Dashboard-Checks aktiver Clients. Ein Check ist fällig, wenn noch kein Ergebnis existiert oder seit dem letzten Ergebnis mindestens
Intervall - 30 Sekunden vergangen sind. Bei einer täglichen Uhrzeit ist er fällig, sobald die Uhrzeit erreicht ist und das letzte Ergebnis älter als diese Uhrzeit ist.
- Für jeden fälligen Check landet eine Nachricht
RunSiteChecksMessage in der Warteschlange async.
- Der Worker führt den Check aus, speichert das Ergebnis und vergleicht es mit dem bisherigen Status (
alert_states).
- Bei einem Wechsel legt er eine
MailNotificationMessage in die Warteschlange notifications, die derselbe Worker verarbeitet.
- Agenten-Ergebnisse gelangen über die API direkt in Schritt 3.
| Wert |
Dauer |
| Fälligkeitsprüfung der Dashboard-Checks |
jede Minute |
| Bereinigung alter Ergebnisse |
täglich 03:00 Uhr |
| Tick des Agenten |
30 Sekunden |
| Abruf der Check-Liste durch den Agenten |
alle 300 Sekunden |
| Agent gilt als online |
Kontakt in den letzten 10 Minuten |
| Wiederholungen fehlgeschlagener Nachrichten |
3, mit doppeltem Abstand |
| Zeitlimit der Container-Prozesse |
3600 Sekunden oder 128 MB, dann Neustart durch Docker |
| Tabelle |
Inhalt |
clients |
Clients mit Name und Aktiv-Kennzeichen |
contacts |
Kontakte mit Name und eindeutiger E-Mail-Adresse |
client_contacts |
Zuordnung Client und Kontakt |
client_urls |
URLs je Client mit Label und optionalen BasicAuth-Zugangsdaten |
site_checks |
Checks: Typ, Konfiguration (JSON), Intervall, tägliche Uhrzeit, Aufbewahrung, Runner, Agent, Aktiv-Kennzeichen, Run-now-Kennzeichen |
check_results |
Ergebnisse: Status, HTTP-Code, Antwortzeit, Meldung, Zeitpunkt |
alert_states |
Aktueller Status je Check, Zeitpunkt des letzten Statuswechsels, Zähler aufeinanderfolgender Warnungen und Fehler |
agents |
Agenten mit Name, Token-Hash und letztem Kontakt |
messenger_messages |
Warteschlange und Transport failed |
Alle Pfade liegen unter /api/v1/agent und verlangen Authorization: Bearer <Token>. Antworten sind JSON. Ohne gültiges Token antwortet Watchdog mit 401 und {"error": "Unauthorized"}, bei Überschreitung des Limits von 60 Anfragen pro Minute und IP mit 429.
| Methode |
Pfad |
Zweck |
GET |
/config |
Check-Liste des Agenten. Aktualisiert den Zeitpunkt des letzten Kontakts |
GET |
/run-now |
Checks mit gesetztem Run-now-Kennzeichen, auch für inaktive Clients. Setzt das Kennzeichen zurück |
POST |
/results |
Ergebnisse eines Ticks entgegennehmen |
Antwort von /config:
{
"agent": {"id": 1, "name": "host-server"},
"checks": [
{"id": 7, "type": "disk_space", "config": {"path": "/"}, "check_interval_minutes": 5, "run_at_time": null, "run_now": false}
]
}
Anfrage an /results:
{
"results": [
{"site_check_id": 7, "status": "ok", "message": "42% used (58 GB free of 100 GB)", "response_time_ms": 12, "checked_at": "2026-01-01T12:00:00+01:00"}
]
}
| Antwort |
Bedeutung |
200 |
{"accepted": <n>, "skipped": [{"site_check_id": <id>, "reason": "..."}]} |
422 |
Ungültiges JSON, fehlendes Feld results oder mehr als 500 Ergebnisse |
401 |
Token fehlt oder ist ungültig |
Ein Ergebnis wird übersprungen (skipped), wenn site_check_id fehlt, der Check nicht existiert oder nicht diesem Agenten zugewiesen ist, oder der Status keiner der Werte ok, warn, fail, unknown ist.
| Werkzeug |
Aufruf |
| PHPUnit |
make test |
| PHPStan Level 9 |
make stan |
| PHP-CS-Fixer |
make cs (Prüfung), make fix (Korrektur) |
| Lint und Smoke-Test |
make lint, make smoke |
Die CI führt Code-Style, PHPStan und die Tests aus und baut das Agenten-Image.