feat(errors, watchdog): Fehler-Stream mit Ignore-Regeln, Metrik-Verlauf, Abhängigkeits-Alarme
Fehler-Schnittstelle - Neuer schlanker Eingang POST /api/errors/v1/report für den globalen Exception-Handler einer Anwendung. Titel und Dringlichkeit leitet der Server ab; gespeichert wird in derselben Tabelle wie der Bugtracker. Ein zweiter Speicher wäre nur ein zweiter Ort, an dem man suchen müsste. - error_level (fatal/error/warning) trennt die technische Art des Ereignisses von der geschäftlichen Dringlichkeit. Ein Duplicate-Entry ist technisch ein error, geschäftlich belanglos — beides zu vermischen war der Grund, warum solche Meldungen als Bug im Dashboard landeten. Ignore-Regeln gegen bekanntes Rauschen - bugtracker_ignore_rules mit contains/regex/exception_class, Pflichtfeld für die Begründung und optionaler Alarmschwelle. - Ein Treffer bedeutet nicht "wegwerfen": Der Fehler wird weiterhin erfasst und hochgezählt, bleibt aber aus der Übersicht heraus und löst keine Benachrichtigung aus. Der Zähler ist der eigentliche Zweck — dass ein bekannter Fehler auftritt, ist normal; dass er plötzlich hundertmal so oft auftritt, ist ein Signal. Dafür das rollende Stundenfenster und error.rate_exceeded. - Neue Regeln lassen sich rückwirkend auf bestehende Einträge anwenden. Gruppierung überarbeitet - Der Schlüssel nahm bisher 300 Zeichen Stacktrace auf. Derselbe Fehler zersplitterte dadurch, sobald ein Aufrufer den Stack einmal mitschickte und einmal nicht. Jetzt zählt der Ursprungsort: bevorzugt die Dateiangabe, sonst der erste Rahmen des Stacktrace. - Die Normalisierung ersetzte nur Zahlen ab vier Stellen, wodurch 'AA-1' und 'BB-2' getrennt blieben. Werte in Anführungszeichen, die Ziffern enthalten, gelten jetzt als veränderlich — der Schlüsselname bleibt erhalten, sodass verschiedene Unique-Keys unterscheidbar sind. Mit 9 Testfällen belegt. Metrik-Verlauf - watchdog_metrics speichert numerische Heartbeat-Werte mit Zeitstempel. Zuvor wurde metrics_json bei jedem Heartbeat überschrieben; damit ließ sich "die Platte läuft seit drei Tagen voll" nicht erkennen, nur "sie ist voll". - GET /api/watchdog/v1/metrics liefert den verdichteten Verlauf und die Abweichung vom eigenen Sieben-Tage-Durchschnitt. Dieser relative Ansatz braucht keine projektspezifischen Schwellwerte. - Aufbewahrung 14 Tage, Bereinigung stündlich durch den Evaluator. Health-Checks per Push statt Abruf - Der Heartbeat nimmt ein checks-Objekt entgegen, das die Anwendung selbst ermittelt. Das Deploymentcenter interpretiert die Namen nicht, es liest nur ok und message — was "gesund" bedeutet, entscheidet jede Anwendung selbst. Schlägt eine Prüfung fehl, wird ein als ok gemeldeter Heartbeat auf warning herabgestuft. - Bewusst ausgehend: auf den Zielmaschinen müssen keine Ports geöffnet werden. Abhängigkeitsbewusste Alarmierung - Fällt ein Monitor aus, dessen Parent selbst unten ist, wird der Alarm unterdrückt. Der Zustand bleibt sichtbar. Vorher erzeugte ein ausgefallener Hypervisor mit zwölf VMs dreizehn Meldungen für ein Problem. - Mehrere Ebenen und fehlerhafte Hierarchien (Zyklen, gelöschte Parents) sind abgesichert; mit 10 Testfällen belegt. WebUI - Neue Ansicht "Fehler-Stream" mit Filtern nach Projekt, Fehlerklasse, Umgebung, Zeitraum und Sichtbarkeit sowie Volltextsuche und Pagination. Stummgeschaltete Einträge sind standardmäßig ausgeblendet. - Verwaltung der Ignore-Regeln inklusive Trefferzähler. - Die Detailansicht zeigt Fehlerklasse, Stummschaltungsgrund und die Häufung im laufenden Stundenfenster. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a74c6fd990
commit
60e34b29f6
@@ -0,0 +1,101 @@
|
||||
-- Migration 007: Fehler-Stream, Ignore-Regeln, Metrik-Verlauf, Health-Checks
|
||||
--
|
||||
-- Additive Migration. Der Migrator toleriert 1050/1060/1061/1062.
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. Fehlerklasse getrennt vom Schweregrad
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- severity beschreibt die geschaeftliche Dringlichkeit (low ... critical),
|
||||
-- error_level die technische Art des Ereignisses. Ein "Duplicate entry" ist
|
||||
-- technisch ein error, geschaeftlich aber belanglos - beides zu vermischen
|
||||
-- war der Grund, warum solche Meldungen bisher als Bug im Dashboard landeten.
|
||||
ALTER TABLE bugtracker_items
|
||||
ADD COLUMN error_level ENUM('fatal','error','warning') NULL AFTER severity;
|
||||
|
||||
-- Status "ignored": bekannt, harmlos, wird weiter gezaehlt, aber nicht gemeldet.
|
||||
ALTER TABLE bugtracker_items
|
||||
MODIFY COLUMN status ENUM('open','planned','in_progress','resolved','closed','rejected','ignored')
|
||||
NOT NULL DEFAULT 'open';
|
||||
|
||||
-- Rollendes Stundenfenster fuer die Ratenerkennung. Interessant ist nicht,
|
||||
-- DASS ein bekannter Fehler auftritt, sondern wenn er ploetzlich viel
|
||||
-- haeufiger auftritt.
|
||||
ALTER TABLE bugtracker_items ADD COLUMN rate_window_start DATETIME NULL AFTER occurrence_count;
|
||||
ALTER TABLE bugtracker_items ADD COLUMN rate_window_count INT NOT NULL DEFAULT 0 AFTER rate_window_start;
|
||||
ALTER TABLE bugtracker_items ADD COLUMN rate_alerted_at DATETIME NULL AFTER rate_window_count;
|
||||
|
||||
-- Welche Regel hat dieses Item stummgeschaltet?
|
||||
ALTER TABLE bugtracker_items ADD COLUMN ignore_rule_id INT NULL AFTER error_level;
|
||||
|
||||
ALTER TABLE bugtracker_items ADD KEY ix_bt_error_level (error_level, last_seen_at);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. Ignore-Regeln
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS bugtracker_ignore_rules (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
project_slug VARCHAR(64) NULL, -- NULL = gilt fuer alle Projekte
|
||||
match_type ENUM('contains','regex','exception_class') NOT NULL DEFAULT 'contains',
|
||||
pattern VARCHAR(255) NOT NULL,
|
||||
-- Warum ist das harmlos? Pflichtfeld, damit in sechs Monaten noch
|
||||
-- nachvollziehbar ist, weshalb hier weggeschaut wird.
|
||||
reason TEXT NOT NULL,
|
||||
-- Ab wie vielen Vorkommnissen pro Stunde soll trotzdem alarmiert werden?
|
||||
-- NULL = nie alarmieren.
|
||||
alert_on_rate INT NULL,
|
||||
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
||||
match_count BIGINT NOT NULL DEFAULT 0,
|
||||
last_match_at DATETIME NULL,
|
||||
created_by VARCHAR(100) NOT NULL DEFAULT 'admin',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY ix_ignore_project (project_slug, enabled)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. Metrik-Verlauf
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Bisher wurde metrics_json bei jedem Heartbeat ueberschrieben - es gab immer
|
||||
-- nur den letzten Moment. Damit laesst sich "Platte laeuft seit drei Tagen
|
||||
-- voll" nicht erkennen, sondern nur "Platte ist voll".
|
||||
CREATE TABLE IF NOT EXISTS watchdog_metrics (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
source VARCHAR(100) NOT NULL,
|
||||
instance VARCHAR(100) NOT NULL DEFAULT 'default',
|
||||
metric_key VARCHAR(64) NOT NULL,
|
||||
metric_value DOUBLE NOT NULL,
|
||||
recorded_utc DATETIME NOT NULL,
|
||||
KEY ix_metric_lookup (source, instance, metric_key, recorded_utc),
|
||||
KEY ix_metric_time (recorded_utc)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 4. Health-Checks per Push
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Die Anwendung sendet ihren Gesundheitszustand im Heartbeat mit. Das
|
||||
-- Deploymentcenter interpretiert die Namen der Pruefungen nicht - es liest
|
||||
-- nur ok und message. Damit muessen auf den Zielmaschinen keine Ports
|
||||
-- geoeffnet werden.
|
||||
ALTER TABLE watchdog_monitors ADD COLUMN health_json JSON NULL AFTER metrics_json;
|
||||
ALTER TABLE watchdog_monitors ADD COLUMN failing_checks VARCHAR(255) NULL AFTER health_json;
|
||||
|
||||
-- Alarme fuer Kinder unterdruecken, solange der Parent unten ist.
|
||||
ALTER TABLE watchdog_monitors ADD COLUMN alert_suppressed_by VARCHAR(100) NULL AFTER failing_checks;
|
||||
|
||||
-- Aufraeumauftrag fuer den Metrik-Verlauf
|
||||
INSERT INTO watchdog_cron_jobs (name, interval_sec, enabled) VALUES
|
||||
('metrics_cleanup', 86400, 1)
|
||||
ON DUPLICATE KEY UPDATE interval_sec = VALUES(interval_sec);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 5. Beispielregel, damit der Aufbau sofort erkennbar ist
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Bewusst deaktiviert (enabled = 0): sie dient als Vorlage und greift erst,
|
||||
-- wenn sie im WebUI bewusst eingeschaltet wird.
|
||||
INSERT INTO bugtracker_ignore_rules
|
||||
(project_slug, match_type, pattern, reason, alert_on_rate, enabled, created_by)
|
||||
SELECT 'polytrader', 'contains', 'Duplicate entry',
|
||||
'Marktdaten kommen doppelt aus dem Feed. Der Eintrag wird ohnehin nur einmal benoetigt, die Verarbeitung laeuft normal weiter. Alarm erst bei auffaelliger Haeufung.',
|
||||
500, 0, 'system:vorlage'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM bugtracker_ignore_rules WHERE project_slug = 'polytrader' AND pattern = 'Duplicate entry'
|
||||
);
|
||||
Reference in New Issue
Block a user