fix(service): skip retained history for unavailable monitors at startup

Ignore history rows without initialized daily or monthly state so deleted and quarantined services cannot panic dashboard startup. Cover startup and statistics preservation with regression tests.

Thanks to Zachariah Mithani (@zachariah-mithani, AploSec) for privately reporting the retained service history startup panic.

Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
naibaandnaiba/CloudCode committed 2026-10-21 13:31:26 +00:00
1 parent b329755836
commit efd3e07b90
2 files changed
+106 -4

No files matched your search

+12 -4
View File
@@ -431,10 +431,18 @@ func (ss *ServiceSentinel) loadTodayStats(today time.Time) {
totalDelay := make(map[uint64]float64)
totalDelayCount := make(map[uint64]int)
for _, mh := range mhs {
ss.serviceStatusToday[mh.ServiceID].Up += mh.Up
ss.monthlyStatus[mh.ServiceID].TotalUp += mh.Up
ss.serviceStatusToday[mh.ServiceID].Down += mh.Down
ss.monthlyStatus[mh.ServiceID].TotalDown += mh.Down
todayStats := ss.serviceStatusToday[mh.ServiceID]
monthlyStats := ss.monthlyStatus[mh.ServiceID]
// History can outlive a deleted service or belong to a quarantined
// service. Neither has startup status entries; skip its rows before
// accumulating counts or delays so retained history cannot panic startup.
if todayStats == nil || monthlyStats == nil {
continue
}
todayStats.Up += mh.Up
monthlyStats.TotalUp += mh.Up
todayStats.Down += mh.Down
monthlyStats.TotalDown += mh.Down
totalDelay[mh.ServiceID] += mh.AvgDelay
totalDelayCount[mh.ServiceID]++
}