syncova-backup/packages/metrics/catalog.go
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

189 lines
8.0 KiB
Go

package metrics
// ChartDefinition beschreibt ein Diagramm des Katalogs.
//
// Der Katalog ist die ehrliche Antwort auf die zwoelf Diagramme aus
// SYNCOVA_IMPLEMENTATION_PLAN.md §15: Er nennt alle, und er sagt bei jedem, ob
// es dafuer eine Datengrundlage gibt. Ein weggelassenes Diagramm sieht aus wie
// ein vergessenes; ein leeres wie eine Anlage ohne Betrieb.
type ChartDefinition struct {
// Metric ist der Bezeichner im Pfad.
Metric string `json:"metric"`
// Title ist die Ueberschrift.
Title string `json:"title"`
// Description erklaert, was das Diagramm zeigt.
Description string `json:"description"`
// Unit ist die Einheit der Werte.
Unit SeriesUnit `json:"unit"`
// Source benennt die Herkunft der Daten.
//
// Sie steht im Katalog, weil sie die Aussagekraft bestimmt: Eine aus
// Laufdaten aggregierte Reihe ist so genau wie die Laeufe, eine aus
// Momentaufnahmen so dicht wie der Sammeltakt.
Source string `json:"source"`
// Available meldet, ob es eine Datengrundlage gibt.
Available bool `json:"available"`
// UnavailableReason erklaert eine fehlende Datengrundlage.
UnavailableReason string `json:"unavailable_reason,omitempty"`
}
// Bezeichner der Diagramme.
const (
// MetricBackupOutcome ist Erfolg und Fehlschlag der Sicherungen.
MetricBackupOutcome = "backup_outcome"
// MetricBackupDuration ist die Dauer der Sicherungslaeufe.
MetricBackupDuration = "backup_duration"
// MetricBackupThroughput ist der Durchsatz der Sicherungslaeufe.
MetricBackupThroughput = "backup_throughput"
// MetricBackupVolume ist die verarbeitete und geschriebene Datenmenge.
MetricBackupVolume = "backup_volume"
// MetricStorageGrowth ist das Wachstum der Repository-Belegung.
MetricStorageGrowth = "storage_growth"
// MetricDeduplication ist die Wirkung der Deduplizierung.
MetricDeduplication = "deduplication"
// MetricCompression ist die Wirkung der Kompression.
MetricCompression = "compression"
// MetricRepositoryCapacity ist die Auslastung der Repositories.
MetricRepositoryCapacity = "repository_capacity"
// MetricSecurityScore ist der Verlauf der Sicherheitsbewertung.
MetricSecurityScore = "security_score"
// MetricAgentResources ist die Ressourcenlast der Agenten.
MetricAgentResources = "agent_resources"
// MetricRecoveryPointAge ist das Alter des juengsten Wiederherstellungspunkts.
MetricRecoveryPointAge = "recovery_point_age"
// MetricRecoveryDuration ist die Dauer der Wiederherstellungen.
MetricRecoveryDuration = "recovery_duration"
// MetricVerificationOutcome ist das Ergebnis der Pruefungen.
MetricVerificationOutcome = "verification_outcome"
)
// Catalog liefert alle Diagramme in Anzeigereihenfolge.
func Catalog() []ChartDefinition {
return []ChartDefinition{
{
Metric: MetricBackupOutcome,
Title: "Sicherungen: Erfolg und Fehlschlag",
Description: "Zahl der abgeschlossenen Laeufe je Zeitfenster, getrennt nach Ausgang. Ein Teilfehler zaehlt nicht als Erfolg.",
Unit: UnitCount,
Source: "backup_job_runs",
Available: true,
},
{
Metric: MetricBackupDuration,
Title: "Dauer der Sicherungen",
Description: "Mittlere Laufzeit je Zeitfenster. Abgebrochene Laeufe bleiben aussen vor — ihre Dauer sagt nichts ueber die Leistung.",
Unit: UnitSeconds,
Source: "backup_job_runs",
Available: true,
},
{
Metric: MetricBackupThroughput,
Title: "Durchsatz der Sicherungen",
Description: "Mittlerer Lesedurchsatz je Zeitfenster, berechnet aus verarbeiteter Menge und Laufzeit.",
Unit: UnitBytesPerSecond,
Source: "backup_job_runs",
Available: true,
},
{
Metric: MetricBackupVolume,
Title: "Verarbeitete und abgelegte Datenmenge",
Description: "Gelesene Menge gegen tatsaechlich geschriebene. Der Abstand zwischen beiden Linien ist die Ersparnis durch Deduplizierung und Kompression.",
Unit: UnitBytes,
Source: "backup_job_runs",
Available: true,
},
{
Metric: MetricStorageGrowth,
Title: "Wachstum der Belegung",
Description: "Belegung der Dateisysteme, auf denen die Repositories liegen. Gemessen wird das Dateisystem, nicht das Repository: Bei geteilter Ablage waechst die Kurve auch durch fremde Daten. Die Reihe beginnt bei der ersten Erfassung — vor ihr gibt es keine Werte, keine Nullen.",
Unit: UnitBytes,
Source: "metric_samples",
Available: true,
},
{
Metric: MetricDeduplication,
Title: "Wirkung der Deduplizierung",
Description: "Anteil der Daten, die dank Deduplizierung nicht erneut abgelegt wurden. Ein negativer Wert ist moeglich und kein Fehler: Bei inkompressiblen Daten ohne Wiederholungen kostet die Verschluesselung je Block ein paar Bytes mehr, als sie einspart.",
Unit: UnitPercent,
Source: "backups",
Available: true,
},
{
Metric: MetricCompression,
Title: "Wirkung der Kompression",
Description: "Anteil, den die Kompression zusaetzlich zur Deduplizierung einspart.",
Unit: UnitPercent,
Source: "—",
Available: false,
UnavailableReason: "Die Groesse nach der Kompression wird nicht festgehalten. Die Engine " +
"komprimiert und verschluesselt in einem Zug und meldet nur die abgelegte Menge; " +
"die Spalte compressed_bytes bleibt deshalb leer. Sie mit der abgelegten Menge zu " +
"fuellen waere falsch — der Verschluesselungsaufwand erschiene dann als schlechte " +
"Kompression. Die Gesamtersparnis zeigt das Diagramm 'Verarbeitete und abgelegte " +
"Datenmenge'.",
},
{
Metric: MetricRepositoryCapacity,
Title: "Auslastung der Repositories",
Description: "Auslastung des Dateisystems je Repository, gemittelt ueber alle erfassten. Ein Mittelwert und keine Summe: Zwei zu 80 Prozent gefuellte Repositories ergeben 80 Prozent, nicht 160.",
Unit: UnitPercent,
Source: "metric_samples",
Available: true,
},
{
Metric: MetricRecoveryPointAge,
Title: "Alter des juengsten Wiederherstellungspunkts",
Description: "Abstand zwischen Zeitfenster und dem bis dahin juengsten abgeschlossenen Backup. Die Kurve steigt, solange nichts gesichert wird, und faellt bei jedem Lauf auf null.",
Unit: UnitSeconds,
Source: "backups",
Available: true,
},
{
Metric: MetricRecoveryDuration,
Title: "Dauer der Wiederherstellungen",
Description: "Laufzeit abgeschlossener Wiederherstellungen. Sie ist die einzige belastbare Grundlage fuer die Aussage, ob eine Wiederherstellungsdauer eingehalten wird.",
Unit: UnitSeconds,
Source: "restore_jobs",
Available: true,
},
{
Metric: MetricSecurityScore,
Title: "Sicherheitsbewertung",
Description: "Verlauf des Security Score. Die Reihe beginnt bei der ersten Erfassung; vor ihr gibt es keine Werte, keine Nullen. Ein Einbruch bedeutet einen neuen Befund, kein Messproblem.",
Unit: UnitPercent,
Source: "metric_samples",
Available: true,
},
{
Metric: MetricVerificationOutcome,
Title: "Ergebnisse der Pruefungen",
Description: "Zahl der Pruefungen je Zeitfenster, getrennt nach Ergebnis.",
Unit: UnitCount,
Source: "verification_jobs",
Available: true,
},
{
Metric: MetricAgentResources,
Title: "Ressourcenlast der Agenten",
Description: "Prozessor-, Speicher- und Datentraegerlast der aufgenommenen Agenten.",
Unit: UnitPercent,
Source: "—",
Available: false,
UnavailableReason: "Die Agenten melden keine Ressourcendaten. Ihre Lebendmeldung traegt " +
"Version und Zeitpunkt, sonst nichts. Eine Kurve aus geschaetzten Werten waere " +
"eine erfundene Statistik; die Erfassung muss zuerst im Agenten entstehen.",
},
}
}
// FindChartDefinition sucht ein Diagramm im Katalog.
func FindChartDefinition(metricName string) (ChartDefinition, bool) {
for _, chartDefinition := range Catalog() {
if chartDefinition.Metric == metricName {
return chartDefinition, true
}
}
return ChartDefinition{}, false
}