@@ -33,24 +33,27 @@ import (
3333// currently active alerts and a set of inhibition rules. It implements the
3434// Muter interface.
3535type Inhibitor struct {
36- alerts provider.Alerts
37- rules []* InhibitRule
38- marker types.AlertMarker
39- logger * slog.Logger
36+ alerts provider.Alerts
37+ rules []* InhibitRule
38+ marker types.AlertMarker
39+ logger * slog.Logger
40+ metrics * InhibitorMetrics
4041
4142 mtx sync.RWMutex
4243 cancel func ()
4344}
4445
4546// NewInhibitor returns a new Inhibitor.
46- func NewInhibitor (ap provider.Alerts , rs []config.InhibitRule , mk types.AlertMarker , logger * slog.Logger ) * Inhibitor {
47+ func NewInhibitor (ap provider.Alerts , rs []config.InhibitRule , mk types.AlertMarker , logger * slog.Logger , metrics * InhibitorMetrics ) * Inhibitor {
4748 ih := & Inhibitor {
48- alerts : ap ,
49- marker : mk ,
50- logger : logger ,
49+ alerts : ap ,
50+ marker : mk ,
51+ logger : logger ,
52+ metrics : metrics ,
5153 }
54+
5255 for _ , cr := range rs {
53- r := NewInhibitRule (cr )
56+ r := NewInhibitRule (cr , NewRuleMetrics ( cr . Name , metrics ) )
5457 ih .rules = append (ih .rules , r )
5558 }
5659 return ih
@@ -70,16 +73,22 @@ func (ih *Inhibitor) run(ctx context.Context) {
7073 continue
7174 }
7275 // Update the inhibition rules' cache.
76+ cached := 0
77+ indexed := 0
7378 for _ , r := range ih .rules {
7479 if r .SourceMatchers .Matches (a .Labels ) {
7580 if err := r .scache .Set (a ); err != nil {
7681 ih .logger .Error ("error on set alert" , "err" , err )
7782 continue
7883 }
79-
8084 r .updateIndex (a )
85+ cached += r .scache .Len ()
86+ indexed += r .sindex .Len ()
87+ r .metrics .ObserveSourceAlertsCacheSize (cached )
8188 }
8289 }
90+ ih .metrics .ObserveSourceAlertsIndexSize (indexed )
91+ ih .metrics .ObserveSourceAlertsCacheSize (cached )
8392 }
8493 }
8594}
@@ -128,21 +137,28 @@ func (ih *Inhibitor) Stop() {
128137// Mutes returns true iff the given label set is muted. It implements the Muter
129138// interface.
130139func (ih * Inhibitor ) Mutes (lset model.LabelSet ) bool {
140+ start := time .Now ()
131141 fp := lset .Fingerprint ()
132142
133143 for _ , r := range ih .rules {
144+ ruleStart := time .Now ()
134145 if ! r .TargetMatchers .Matches (lset ) {
135146 // If target side of rule doesn't match, we don't need to look any further.
147+ r .metrics .ObserveRuleMatchesDuration ("false" , time .Since (ruleStart ))
136148 continue
137149 }
150+ r .metrics .ObserveRuleMatchesDuration ("true" , time .Since (ruleStart ))
138151 // If we are here, the target side matches. If the source side matches, too, we
139152 // need to exclude inhibiting alerts for which the same is true.
140153 if inhibitedByFP , eq := r .hasEqual (lset , r .SourceMatchers .Matches (lset )); eq {
141154 ih .marker .SetInhibited (fp , inhibitedByFP .String ())
155+ r .metrics .ObserveRuleMutesDuration ("true" , time .Since (ruleStart ))
142156 return true
143157 }
158+ r .metrics .ObserveRuleMutesDuration ("false" , time .Since (ruleStart ))
144159 }
145160 ih .marker .SetInhibited (fp )
161+ ih .metrics .ObserveRuleMutesDuration ("none" , "false" , time .Since (start ))
146162
147163 return false
148164}
@@ -173,14 +189,17 @@ type InhibitRule struct {
173189 // The index items might overwrite eachother if multiple source alerts have exact equal labels.
174190 // Overwrites only happen if the new source alert has bigger EndsAt value.
175191 sindex * index
192+
193+ metrics * RuleMetrics
176194}
177195
178196// NewInhibitRule returns a new InhibitRule based on a configuration definition.
179- func NewInhibitRule (cr config.InhibitRule ) * InhibitRule {
197+ func NewInhibitRule (cr config.InhibitRule , metrics * RuleMetrics ) * InhibitRule {
180198 var (
181199 sourcem labels.Matchers
182200 targetm labels.Matchers
183201 )
202+
184203 // cr.SourceMatch will be deprecated. This for loop appends regex matchers.
185204 for ln , lv := range cr .SourceMatch {
186205 matcher , err := labels .NewMatcher (labels .MatchEqual , ln , lv )
@@ -235,6 +254,7 @@ func NewInhibitRule(cr config.InhibitRule) *InhibitRule {
235254 Equal : equal ,
236255 scache : store .NewAlerts (),
237256 sindex : newIndex (),
257+ metrics : metrics ,
238258 }
239259
240260 rule .scache .SetGCCallback (rule .gcCallback )
@@ -262,6 +282,7 @@ func (r *InhibitRule) updateIndex(alert *types.Alert) {
262282 if ! ok {
263283 // If not, add it.
264284 r .sindex .Set (eq , fp )
285+ r .metrics .ObserveSourceAlertsIndexSize (r .sindex .Len ())
265286 return
266287 }
267288 // If the indexed fingerprint is the same as the new fingerprint, do nothing.
@@ -274,12 +295,14 @@ func (r *InhibitRule) updateIndex(alert *types.Alert) {
274295 if err != nil {
275296 // failed to get the existing alert, overwrite the index.
276297 r .sindex .Set (eq , fp )
298+ r .metrics .ObserveSourceAlertsIndexSize (r .sindex .Len ())
277299 return
278300 }
279301
280302 // If the new alert resolves after the existing alert, replace the index.
281303 if existing .ResolvedAt (alert .EndsAt ) {
282304 r .sindex .Set (eq , fp )
305+ r .metrics .ObserveSourceAlertsIndexSize (r .sindex .Len ())
283306 return
284307 }
285308 // If the existing alert resolves after the new alert, do nothing.
@@ -310,6 +333,8 @@ func (r *InhibitRule) gcCallback(alerts []types.Alert) {
310333 fp := r .fingerprintEquals (a .Labels )
311334 r .sindex .Delete (fp )
312335 }
336+ r .metrics .ObserveSourceAlertsCacheSize (r .scache .Len ())
337+ r .metrics .ObserveSourceAlertsIndexSize (r .sindex .Len ())
313338}
314339
315340// hasEqual checks whether the source cache contains alerts matching the equal
0 commit comments