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>
189 lines
8.0 KiB
Go
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
|
|
}
|