Compare commits

...
2 Commits
Author SHA1 Message Date
james.maesandClaude Opus 5.5 186bfabc34 revert(alerts): drop the runtime alert-only mechanism
Setting alerts_type.notify=false from the adapter overrides an admin's
choice on every restart. Making STORAGE_DEBRIS and RESTORE_COMPLETED
alert-only waits on a proper notify flag in the alert type metadata (core
and qbit-alerts). The plan-named titles stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:39:00 -05:00
james.maesandClaude Opus 5.5 5ea7a99d5c fix(alerts): name the plan in alert titles, keep info alerts out of the bell
Per-plan alert titles were constants, so two plans looked identical in the
notification bell. Titles now carry the plan's display name; dedupe keys are
unchanged.

STORAGE_DEBRIS and RESTORE_COMPLETED are informational, so they are declared
alert-only: after the first raise the adapter switches notify off on the
Alerts qbit's alert type row (core alert type metadata has no such setting).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:30:40 -05:00
3 changed files with 8 additions and 7 deletions

No files matched your search

@@ -262,7 +262,7 @@ public class SlaChecker
if(missing)
{
BackupAlerts.raise(BackupAlerts.RUN_MISSING, planKey, BackupAlertSink.Severity.CRITICAL, "The latest backup is missing from storage",
BackupAlerts.raise(BackupAlerts.RUN_MISSING, planKey, BackupAlertSink.Severity.CRITICAL, "The latest backup of \"" + name + "\" is missing from storage",
"plan", planKey, "planName", name);
}
else
@@ -273,7 +273,7 @@ public class SlaChecker
if(late)
{
BackupAlerts.raise(BackupAlerts.PLAN_MISSED, planKey, critical ? BackupAlertSink.Severity.CRITICAL : BackupAlertSink.Severity.ERROR,
"A backup did not run in time", "plan", planKey, "planName", name, "slaHours", String.valueOf(slaHours(plan)));
"Backup \"" + name + "\" did not run in time", "plan", planKey, "planName", name, "slaHours", String.valueOf(slaHours(plan)));
}
else
{
@@ -283,7 +283,7 @@ public class SlaChecker
if(latestFailed || abandoned)
{
BackupAlerts.raise(BackupAlerts.RUN_FAILED, planKey, failing ? BackupAlertSink.Severity.ERROR : BackupAlertSink.Severity.WARNING,
failing ? "Backups have failed twice in a row" : "A backup run failed", "plan", planKey, "planName", name);
failing ? "Backup \"" + name + "\" has failed twice in a row" : "Backup \"" + name + "\" run failed", "plan", planKey, "planName", name);
}
else if(latestFinished != null)
{
@@ -292,7 +292,7 @@ public class SlaChecker
if(ownerBad)
{
BackupAlerts.raise(BackupAlerts.PLAN_OWNER_INVALID, planKey, BackupAlertSink.Severity.WARNING, "The backup plan owner is not valid",
BackupAlerts.raise(BackupAlerts.PLAN_OWNER_INVALID, planKey, BackupAlertSink.Severity.WARNING, "The owner of backup plan \"" + name + "\" is not valid",
"plan", planKey, "planName", name);
}
else
@@ -302,7 +302,7 @@ public class SlaChecker
if(unverified)
{
BackupAlerts.raise(BackupAlerts.VERIFY_OVERDUE, planKey, BackupAlertSink.Severity.WARNING, "No backup has been verified recently",
BackupAlerts.raise(BackupAlerts.VERIFY_OVERDUE, planKey, BackupAlertSink.Severity.WARNING, "No backup of \"" + name + "\" has been verified recently",
"plan", planKey, "planName", name, "verifySlaDays", String.valueOf(plan.getValueInteger("verifySlaDays")));
}
else
@@ -507,7 +507,7 @@ public class SlaChecker
LAST_AUDIT_AT.put(auditKey, now);
if(orphans + debris > 0)
{
BackupAlerts.raise(BackupAlerts.STORAGE_DEBRIS, planKey, BackupAlertSink.Severity.INFO, "Backup storage has orphans or debris",
BackupAlerts.raise(BackupAlerts.STORAGE_DEBRIS, planKey, BackupAlertSink.Severity.INFO, "Backup storage of \"" + planKey + "\" has orphans or debris",
"plan", planKey, "orphans", String.valueOf(orphans), "debris", String.valueOf(debris));
}
else
@@ -639,7 +639,7 @@ public class BackupVerifier
detail.put("level", outcome.level());
detail.put("mismatches", String.valueOf(outcome.mismatches()));
BackupAlerts.raiseWithKey(BackupAlerts.VERIFY_FAILED, BackupAlerts.verifyKey(planKey, outcome.level()), BackupAlertSink.Severity.ERROR,
"Backup verification failed (" + outcome.level() + ")", detail);
"Verification of backup \"" + (plan.getValueString("name") == null ? planKey : plan.getValueString("name")) + "\" failed (" + outcome.level() + ")", detail);
}
}
}
@@ -87,6 +87,7 @@ class SlaCheckerTest
assertThat(late.previousStatus()).isEqualTo(SlaChecker.UNKNOWN);
assertThat(reload(plan).getValueString("slaStatus")).isEqualTo("LATE");
BackupAlertsAssert.assertOpen("backups.plan.missed:nightly", BackupAlertSink.Severity.CRITICAL);
assertThat(sink.open.get("backups.plan.missed:nightly").title()).isEqualTo("Backup \"Nightly\" did not run in time");
}