syncova-backup/docs/metrics.md
Jerrit Fritzsche 610719c316
Some checks failed
CI / Backend (Go) (push) Failing after 3m7s
CI / Frontend (React/TypeScript) (push) Successful in 37s
CI / Sicherheitsprüfungen (push) Successful in 44s
Syncova Backups V1
Enterprise-Backup-, Recovery-, Verification-, Security- und
Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme.

Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als
vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit
nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem
tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes
geht in keine Bewertung als "gut" ein.

Umfang (Phasen 0-23):

- Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll,
  Katalogaufbau allein aus den Manifesten — ohne Datenbank
- Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz
  Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck
- Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell)
- Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive
- Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit
- Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center,
  Ransomware-Heuristik (meldet, handelt nie)
- Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing
- Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository
- Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64

Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup
Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs.

Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die
systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine
wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md
und docs/release-candidate.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 09:10:54 +02:00

8.7 KiB
Raw Blame History

Kennzahlen und Diagramme

Phase 13. Zwölf Diagramme über sieben Zeiträume — und die eine Regel, die darüber entscheidet, ob eine Kurve etwas wert ist:

Eine Lücke ist keine Null.

Ein Zeitfenster ohne Sicherungslauf hat keinen Durchsatz. Nicht null Byte je Sekunde — keinen. Wer Lücken als Nullen zeichnet, erzeugt eine Kurve, die nachts auf den Boden fällt: Die Anlage sieht aus, als wäre ihre Leistung eingebrochen, obwohl sie nur nichts zu tun hatte.

Deshalb trägt jeder Punkt ein has_value, und das Diagramm unterbricht die Linie, statt sie durch den Nullpunkt zu ziehen.

Woher die Daten kommen

Zehn der zwölf Reihen werden aus Tabellen aggregiert, die es bereits gibt:

Quelle Reihen
backup_job_runs Erfolg/Fehlschlag, Dauer, Durchsatz, Datenmengen
backups Deduplizierung, Alter des jüngsten Wiederherstellungspunkts
restore_jobs Dauer der Wiederherstellungen
verification_jobs Ergebnisse der Prüfungen
metric_samples Speicherwachstum, Auslastung

Diese Zahlen ein zweites Mal als Zeitreihe abzulegen wäre die übliche Lösung und die schlechtere: Zwei Quellen für dieselbe Aussage laufen auseinander, und man merkt es erst, wenn jemand nachrechnet.

metric_samples nimmt deshalb nur auf, was sonst verloren geht — Momentaufnahmen, die beim nächsten Schreiben überschrieben werden. repositories.used_bytes ist genau das: der heutige Stand, ohne jede Erinnerung an gestern.

Was nicht gemessen wird

Diagramm Warum nicht
Ressourcenlast der Agenten Die Agenten melden keine Ressourcendaten. Ihre Lebendmeldung trägt Version und Zeitpunkt, sonst nichts.
Wirkung der Kompression Die Engine komprimiert und verschlüsselt in einem Zug und meldet nur die abgelegte Menge; compressed_bytes bleibt leer.

Beide erscheinen im Katalog mit dieser Begründung. Die zweite Lücke fiel erst im Nachweis auf: Das Diagramm war als verfügbar geführt und blieb leer — die unangenehmste Sorte Fehler, weil sie funktionsfähig aussieht.

compressed_bytes mit der abgelegten Menge zu füllen wäre falsch: Der Verschlüsselungsaufwand von 28 Byte je Block erschiene dann als schlechte Kompression.

Zeiträume und Auflösung

Zeitraum Fensterbreite Punkte
1h 1 Minute 60
24h 15 Minuten 96
7d 1 Stunde 168
30d 6 Stunden 120
90d 1 Tag 90
1y 7 Tage 53
custom abgeleitet, mindestens 1 Minute ≤ 500

Die Breite folgt dem Zeitraum und ist nicht frei wählbar: Eine Kurve, deren Punktabstand der Aufrufer bestimmt, lässt sich zwischen zwei Ansichten nicht vergleichen. Ein Jahr in Minutenschritten ergäbe über eine halbe Million Punkte.

Der letzte Abschnitt wird aufgerundet

Ein Jahr geteilt durch sieben Tage ergibt 52,14 Fenster. Abgerundet fielen die letzten ein bis sieben Tage aus der Auswertung — ausgerechnet die jüngsten Ereignisse. Im Nachweis zeigte der Jahresverlauf null Messungen, obwohl am selben Tag mehrere Läufe stattgefunden hatten.

Das letzte Fenster ist dadurch schmaler als die übrigen. Der bessere Tausch: Ein leicht kürzerer Rand fällt niemandem auf, eine fehlende Woche schon.

Was die Zahlen bedeuten

  • Ein Teilfehler zählt nicht als Erfolg. Die Reihen succeeded, partial_failure und failed stehen getrennt.
  • Abgebrochene Läufe fehlen in der Dauer. Ihre Laufzeit ist die Zeit bis zum Abbruch und sagt nichts über die Leistung.
  • Der Durchsatz wird neu berechnet, nicht aus throughput_bps gelesen: Die Spalte bleibt bei kurzen Läufen leer, und ein Mittelwert über teils fehlende Werte wäre schief. Läufe unter einer Sekunde fallen heraus — bei ihnen bestimmt die Messungenauigkeit das Ergebnis.
  • Eine negative Deduplizierungsersparnis ist möglich und kein Fehler: Bei inkompressiblen Daten ohne Wiederholungen kostet die Verschlüsselung je Block ein paar Bytes mehr, als sie einspart.
  • Das Alter des jüngsten Wiederherstellungspunkts entsteht nicht durch Gruppieren: Gefragt ist für jedes Zeitfenster der Abstand zum bis dahin jüngsten Backup, auch wenn in diesem Fenster keines lief. Genau das ist der Sinn der Kurve — sie steigt, solange nichts gesichert wird. Vor dem ersten Backup gibt es keinen Wert, nicht das Alter null.
  • Speicherwachstum misst das Dateisystem, nicht das Repository. Bei geteilter Ablage wächst die Kurve auch durch fremde Daten. Die genaue Repositorygröße verlangte einen Durchlauf über Millionen Blöcke — im Fünfminutentakt liefe der Dienst nur noch damit.
  • Die Auslastung ist ein Mittelwert, keine Summe. Zwei zu 80 % gefüllte Repositories ergeben 80 %, nicht 160.

Einordnung statt Schönfärberei

Jedes Diagramm bekommt einen Hinweis, wenn die Zahlen zwar stimmen, aber wenig hergeben:

  • Keine Messung im Zeitraum → „Die leere Fläche bedeutet ‚keine Daten', nicht ‚Wert null'."
  • Weniger als drei Messungen → „Das ist zu wenig für eine Aussage über eine Entwicklung."

Zwei Punkte sehen aus wie ein Trend und sind keiner.

Darstellung

Das Liniendiagramm ist selbst geschrieben (SVG, rund 300 Zeilen). Die gängigen Bibliotheken bringen mehr Code mit als die ganze Oberfläche — und beherrschen die eine Eigenschaft, auf die es hier ankommt, standardmäßig falsch: Sie zeichnen Lücken als Nullen.

  • Die Werteachse beginnt immer bei null. Eine abgeschnittene Achse lässt kleine Schwankungen wie Einbrüche aussehen — der häufigste Weg, mit korrekten Zahlen etwas Falsches zu zeigen.
  • Eine einzelne Messung wird als Punkt gezeichnet. Als Linie hätte sie die Länge null und wäre unsichtbar; die Kurve sähe aus wie „nichts gemessen".
  • Jede Lücke trennt die Linie in einen eigenen Zug. Geprüft durch einen Test, der die gezeichneten Pfade auszählt.

Endpunkte

Methode Pfad Recht
GET /api/v1/metrics monitoring.read
GET /api/v1/metrics/{metric}?range=7d monitoring.read

Ein Diagramm ohne Datengrundlage antwortet mit 501, nicht 404: Es ist vorgesehen, es fehlt nur die Messung. Der Unterschied entscheidet, was der Aufrufer tut — warten oder den Namen korrigieren.

curl "/api/v1/metrics"                                   # Katalog
curl "/api/v1/metrics/backup_throughput?range=24h"       # eine Reihe
curl "/api/v1/metrics/storage_growth?range=custom&from=…&to=…"

Erfassung

Der Sammler läuft neben Sicherung, Wiederherstellung und Prüfung. Alle fünf Minuten misst er Belegung und Kapazität jedes Repositorys über einen statfs-Aufruf.

  • Der erste Durchgang läuft sofort, nicht erst nach fünf Minuten. Sonst begänne jede Verlaufsreihe verspätet, und ein kurz laufender Dienst erfasste nie etwas.
  • Ein nicht erreichbares Repository trägt keine Null ein, sondern gar nichts. Eine Null ließe die Kurve auf den Boden fallen, obwohl die Daten da sind.
  • Der Messzeitpunkt wird auf die volle Minute gerundet. Ohne diese Rundung entstünden bei zwei gleichzeitig sammelnden Control-Servern zwei Messungen mit Millisekundenabstand; der Eindeutigkeitsindex griffe nicht, und die Belegung erschiene doppelt.
  • Aufbewahrung 400 Tage. Das deckt den längsten Zeitraum von einem Jahr ab und lässt Raum für einen Jahresvergleich. Ohne Aufräumen wüchse die Tabelle unbegrenzt.

NaN wird abgelehnt

Ein einziger NaN-Wert verseucht jede Summe und jeden Durchschnitt der Reihe — das Ergebnis ist danach selbst NaN, ohne dass irgendwo ein Fehler auftaucht. Die Prüfung lautet ausdrücklich value <> 'NaN' und nicht das übliche value = value: PostgreSQL wertet NaN = NaN als wahr, anders als IEEE 754. Der Standardtrick greift hier nicht — real geprüft, der erste Anlauf ließ NaN durch.

Nachgewiesen

Gegen den laufenden Dienst mit echten Läufen:

  • Katalog: 10 von 12 Diagrammen mit Datengrundlage, zwei mit Begründung.
  • Alle sieben Zeiträume liefern brauchbare Punktzahlen (60 bis 180).
  • Durchsatz aus einem 172-MB-Lauf: 155,8 MiB/s, mit dem Hinweis „nur eine Messung".
  • Erfolg und Fehlschlag in derselben Kurve: Aufträge früherer Phasen scheitern mit REPOSITORY_UNAVAILABLE, weil ihre Verzeichnisse entfernt wurden.
  • 501 für agent_resources, 404 für einen unbekannten Namen, 422 für einen ungültigen Zeitraum.

Bekannte Grenzen

  • Keine Verdichtung alter Messungen. Nach 400 Tagen werden sie gelöscht statt zusammengefasst. Bei wenigen Repositories ist das unkritisch.
  • Kein Filter je Auftrag in den Laufreihen. Der Endpunkt kennt repository_id nur für die Speicherreihen.
  • Keine Zeitachsenbeschriftung im Diagramm. Die Zeitpunkte stehen in den Daten, gezeichnet wird nur die Werteachse.
  • Kein automatisches Aktualisieren. Die Seite lädt beim Öffnen und beim Wechsel des Zeitraums.