Enrich backup notifications
This commit is contained in:
@@ -12,10 +12,18 @@ func TestNotificationMessageIncludesBackupStatistics(t *testing.T) {
|
||||
started := time.Date(2026, 6, 14, 12, 0, 0, 0, time.UTC)
|
||||
finished := started.Add(2*time.Minute + 8*time.Second)
|
||||
run := model.Run{TaskType: "backup", Status: "success", StartedAt: &started, FinishedAt: &finished, SnapshotID: "abc123", BytesAdded: 1536, FilesNew: 7, FilesChanged: 2, BytesProcessed: 5 * 1024 * 1024, FilesProcessed: 120}
|
||||
message := notificationMessage(run, finished)
|
||||
for _, expected := range []string{"Status: Erfolgreich", "Dauer: 2 Min. 8 Sek.", "Neu gespeichert: 1.5 KiB", "Neue Dateien: 7", "Geänderte Dateien: 2", "Gesamtgröße dieses Backups: 5.0 MiB", "Dateien insgesamt: 120", "Snapshot: abc123"} {
|
||||
message := notificationMessage("Freigaben", "LV-426", run, finished)
|
||||
for _, expected := range []string{"📊 URBM-Zusammenfassung", "Status: Erfolgreich", "Job: Freigaben", "Repository: LV-426", "Dauer: 2 Min. 8 Sek.", "Snapshot: abc123", "Verarbeitete Daten: 5.0 MiB", "Verarbeitete Dateien: 120", "Neu gespeichert: 1.5 KiB", "Neue Dateien: 7", "Geänderte Dateien: 2"} {
|
||||
if !strings.Contains(message, expected) {
|
||||
t.Errorf("message %q does not contain %q", message, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotificationTitleIncludesRepositoryAndStatus(t *testing.T) {
|
||||
run := model.Run{TaskType: "backup", Status: "failed"}
|
||||
title := notificationTitle("Freigaben", "LV-426", run)
|
||||
if title != "❌ URBM Backup: LV-426" {
|
||||
t.Fatalf("title = %q", title)
|
||||
}
|
||||
}
|
||||
|
||||
+51
-14
@@ -746,17 +746,24 @@ func (s *Service) executeRestore(ctx context.Context, run model.Run) model.Run {
|
||||
|
||||
func (s *Service) finishJob(run model.Run, job model.Job, result model.Run) model.Run {
|
||||
if result.Status == "success" || result.Status == "warning" || result.Status == "failed" {
|
||||
go s.notify(job.Name, result)
|
||||
repoName := ""
|
||||
if job.RepositoryID != "" {
|
||||
if repo, ok := s.repository(job.RepositoryID); ok {
|
||||
repoName = repo.Name
|
||||
}
|
||||
}
|
||||
go s.notify(job.Name, repoName, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Service) notify(name string, run model.Run) {
|
||||
message := notificationMessage(run, time.Now().UTC())
|
||||
func (s *Service) notify(name, repository string, run model.Run) {
|
||||
title := notificationTitle(name, repository, run)
|
||||
message := notificationMessage(name, repository, run, time.Now().UTC())
|
||||
for _, target := range s.Config().Notifications {
|
||||
for _, event := range target.Events {
|
||||
if event == run.Status {
|
||||
if err := s.notifier.Send(context.Background(), target, "URBM: "+name, message, run.Status); err != nil {
|
||||
if err := s.notifier.Send(context.Background(), target, title, message, run.Status); err != nil {
|
||||
s.log.Warn("send notification failed", "target", target.ID, "type", target.Type, "error", err)
|
||||
}
|
||||
break
|
||||
@@ -765,12 +772,36 @@ func (s *Service) notify(name string, run model.Run) {
|
||||
}
|
||||
}
|
||||
|
||||
func notificationMessage(run model.Run, now time.Time) string {
|
||||
func notificationTitle(name, repository string, run model.Run) string {
|
||||
icon := map[string]string{"success": "✅", "warning": "⚠️", "failed": "❌"}[run.Status]
|
||||
if icon == "" {
|
||||
icon = "ℹ️"
|
||||
}
|
||||
task := map[string]string{"backup": "Backup", "rsync": "Rsync", "restore": "Restore", "check": "Prüfung", "prune": "Bereinigung"}[run.TaskType]
|
||||
if task == "" {
|
||||
task = run.TaskType
|
||||
if task != "" {
|
||||
task = strings.ToUpper(task[:1]) + task[1:]
|
||||
}
|
||||
}
|
||||
if repository != "" {
|
||||
return fmt.Sprintf("%s URBM %s: %s", icon, task, repository)
|
||||
}
|
||||
return fmt.Sprintf("%s URBM %s: %s", icon, task, name)
|
||||
}
|
||||
|
||||
func notificationMessage(name, repository string, run model.Run, now time.Time) string {
|
||||
status := map[string]string{"success": "Erfolgreich", "warning": "Mit Warnung", "failed": "Fehlgeschlagen"}[run.Status]
|
||||
if status == "" {
|
||||
status = run.Status
|
||||
}
|
||||
lines := []string{"Status: " + status}
|
||||
lines := []string{"📊 URBM-Zusammenfassung", "", "Status: " + status}
|
||||
if name != "" {
|
||||
lines = append(lines, "Job: "+name)
|
||||
}
|
||||
if repository != "" {
|
||||
lines = append(lines, "Repository: "+repository)
|
||||
}
|
||||
if run.StartedAt != nil {
|
||||
finished := now
|
||||
if run.FinishedAt != nil {
|
||||
@@ -781,16 +812,22 @@ func notificationMessage(run model.Run, now time.Time) string {
|
||||
}
|
||||
}
|
||||
if (run.TaskType == "backup" || run.TaskType == "rsync") && (run.Status == "success" || run.Status == "warning") {
|
||||
lines = append(lines,
|
||||
"Neu gespeichert: "+formatBytes(run.BytesAdded),
|
||||
fmt.Sprintf("Neue Dateien: %d", run.FilesNew),
|
||||
fmt.Sprintf("Geänderte Dateien: %d", run.FilesChanged),
|
||||
"Gesamtgröße dieses Backups: "+formatBytes(run.BytesProcessed),
|
||||
fmt.Sprintf("Dateien insgesamt: %d", run.FilesProcessed),
|
||||
)
|
||||
if run.SnapshotID != "" {
|
||||
if run.TaskType == "backup" && run.SnapshotID != "" {
|
||||
lines = append(lines, "Snapshot: "+run.SnapshotID)
|
||||
}
|
||||
lines = append(lines,
|
||||
"Verarbeitete Daten: "+formatBytes(run.BytesProcessed),
|
||||
fmt.Sprintf("Verarbeitete Dateien: %d", run.FilesProcessed),
|
||||
)
|
||||
if run.TaskType == "backup" {
|
||||
lines = append(lines,
|
||||
"Neu gespeichert: "+formatBytes(run.BytesAdded),
|
||||
fmt.Sprintf("Neue Dateien: %d", run.FilesNew),
|
||||
fmt.Sprintf("Geänderte Dateien: %d", run.FilesChanged),
|
||||
)
|
||||
} else {
|
||||
lines = append(lines, "Kopierte Daten: "+formatBytes(run.BytesAdded))
|
||||
}
|
||||
}
|
||||
if run.Message != "" && run.Message != "backup completed" && run.Message != "rsync completed" {
|
||||
lines = append(lines, "Details: "+run.Message)
|
||||
|
||||
Reference in New Issue
Block a user