diff --git a/rules/alerting.go b/rules/alerting.go index 2cadd3ac5..e357cc615 100644 --- a/rules/alerting.go +++ b/rules/alerting.go @@ -542,6 +542,13 @@ func (r *AlertingRule) ForEachActiveAlert(f func(*Alert)) { } } +func (r *AlertingRule) ActiveAlertsCount() int { + r.activeMtx.Lock() + defer r.activeMtx.Unlock() + + return len(r.active) +} + func (r *AlertingRule) sendAlerts(ctx context.Context, ts time.Time, resendDelay, interval time.Duration, notifyFunc NotifyFunc) { alerts := []*Alert{} r.ForEachActiveAlert(func(alert *Alert) { diff --git a/rules/alerting_test.go b/rules/alerting_test.go index 366297b4a..78f6d6715 100644 --- a/rules/alerting_test.go +++ b/rules/alerting_test.go @@ -1027,3 +1027,22 @@ func TestAlertingRule_SetNoDependencyRules(t *testing.T) { rule.SetNoDependencyRules(true) require.True(t, rule.NoDependencyRules()) } + +func TestAlertingRule_ActiveAlertsCount(t *testing.T) { + rule := NewAlertingRule( + "TestRule", + nil, + time.Minute, + 0, + labels.FromStrings("severity", "critical"), + labels.EmptyLabels(), labels.EmptyLabels(), "", true, nil, + ) + + // Set an active alert. + lbls := labels.FromStrings("a1", "1") + h := lbls.Hash() + al := &Alert{State: StateFiring, Labels: lbls, ActiveAt: time.Now()} + rule.active[h] = al + + require.Equal(t, 1, t rule.ActiveAlertsCount()) +} diff --git a/rules/group.go b/rules/group.go index c4331a465..28a0ff6e1 100644 --- a/rules/group.go +++ b/rules/group.go @@ -681,7 +681,8 @@ func (g *Group) RestoreForState(ts time.Time) { continue } - seriesByLabels := map[string]storage.Series{} + // While not technically the same number of series we expect, it's as good of an approximation as any. + seriesByLabels := make(map[string]storage.Series, alertRule.ActiveAlertsCount()) for sset.Next() { seriesByLabels[sset.At().Labels().DropMetricName().String()] = sset.At() }