From f93b50f7cada3718845d7f6b412c46b947397196 Mon Sep 17 00:00:00 2001 From: swoga Date: Thu, 14 Sep 2023 20:25:56 +0200 Subject: [PATCH 1/2] feat: inhibit with label pairs Signed-off-by: swoga Signed-off-by: MonkZ --- config/config.go | 10 ++++++- inhibit/inhibit.go | 35 ++++++++++++++++++----- inhibit/inhibit_test.go | 61 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/config/config.go b/config/config.go index 6f54c52368..322cbbdee5 100644 --- a/config/config.go +++ b/config/config.go @@ -966,9 +966,11 @@ type InhibitRule struct { TargetMatchRE MatchRegexps `yaml:"target_match_re,omitempty" json:"target_match_re,omitempty"` // TargetMatchers defines a set of label matchers that have to be fulfilled for target alerts. TargetMatchers Matchers `yaml:"target_matchers,omitempty" json:"target_matchers,omitempty"` - // A set of labels that must be equal between the source and target alert + // A set of labels that must be equal between the source and target alert. // for them to be a match. Equal []string `yaml:"equal,omitempty" json:"equal,omitempty"` + // EqualPairs defines a set of pairs that have to be equal in the source and target alert. + EqualPairs []LabelPair `yaml:"equal_pairs,omitempty" json:"equal_pairs,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for InhibitRule. @@ -1000,6 +1002,12 @@ func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error { return nil } +// LabelPair defines a source / target label pair. +type LabelPair struct { + SourceLabel model.LabelName `yaml:"source_label,omitempty" json:"source_label,omitempty"` + TargetLabel model.LabelName `yaml:"target_label,omitempty" json:"target_label,omitempty"` +} + // Receiver configuration provides configuration on how to contact a receiver. type Receiver struct { // A unique identifier for this receiver. diff --git a/inhibit/inhibit.go b/inhibit/inhibit.go index 3650186e37..f399855d16 100644 --- a/inhibit/inhibit.go +++ b/inhibit/inhibit.go @@ -156,19 +156,29 @@ type InhibitRule struct { // The set of Filters which define the group of target alerts (which are // inhibited by the source alerts). TargetMatchers labels.Matchers - // A set of label names whose label values need to be identical in source and + // A set of label name pairs whose label values need to be identical in source and // target alerts in order for the inhibition to take effect. - Equal map[model.LabelName]struct{} + EqualPairs LabelPairs // Cache of alerts matching source labels. scache *store.Alerts } +// LabelPairs defines a set of source / target label pairs. +type LabelPairs []LabelPair + +// LabelPair defines a source / target label pair. +type LabelPair struct { + SourceLabel model.LabelName + TargetLabel model.LabelName +} + // NewInhibitRule returns a new InhibitRule based on a configuration definition. func NewInhibitRule(cr config.InhibitRule) *InhibitRule { var ( sourcem labels.Matchers targetm labels.Matchers + pairs LabelPairs ) // cr.SourceMatch will be deprecated. This for loop appends regex matchers. for ln, lv := range cr.SourceMatch { @@ -212,15 +222,26 @@ func NewInhibitRule(cr config.InhibitRule) *InhibitRule { // We append the new-style matchers. This can be simplified once the deprecated matcher syntax is removed. targetm = append(targetm, cr.TargetMatchers...) - equal := map[model.LabelName]struct{}{} for _, ln := range cr.Equal { - equal[model.LabelName(ln)] = struct{}{} + pair := LabelPair{ + SourceLabel: model.LabelName(ln), + TargetLabel: model.LabelName(ln), + } + pairs = append(pairs, pair) + } + + for _, p := range cr.EqualPairs { + pair := LabelPair{ + SourceLabel: p.SourceLabel, + TargetLabel: p.TargetLabel, + } + pairs = append(pairs, pair) } return &InhibitRule{ SourceMatchers: sourcem, TargetMatchers: targetm, - Equal: equal, + EqualPairs: pairs, scache: store.NewAlerts(), } } @@ -237,8 +258,8 @@ Outer: if a.ResolvedAt(now) { continue } - for n := range r.Equal { - if a.Labels[n] != lset[n] { + for _, p := range r.EqualPairs { + if a.Labels[p.SourceLabel] != lset[p.TargetLabel] { continue Outer } } diff --git a/inhibit/inhibit_test.go b/inhibit/inhibit_test.go index 59ff52b195..ecf55a7931 100644 --- a/inhibit/inhibit_test.go +++ b/inhibit/inhibit_test.go @@ -35,10 +35,11 @@ func TestInhibitRuleHasEqual(t *testing.T) { now := time.Now() cases := []struct { - initial map[model.Fingerprint]*types.Alert - equal model.LabelNames - input model.LabelSet - result bool + initial map[model.Fingerprint]*types.Alert + equal model.LabelNames + equalPairs LabelPairs + input model.LabelSet + result bool }{ { // No source alerts at all. @@ -118,16 +119,62 @@ func TestInhibitRuleHasEqual(t *testing.T) { input: model.LabelSet{"a": "b"}, result: false, }, + { + // Equal label pair does match + initial: map[model.Fingerprint]*types.Alert{ + 1: { + Alert: model.Alert{ + Labels: model.LabelSet{"a": "b"}, + StartsAt: now.Add(-time.Minute), + EndsAt: now.Add(time.Hour), + }, + }, + }, + equalPairs: LabelPairs{ + { + SourceLabel: "a", + TargetLabel: "x", + }, + }, + input: model.LabelSet{"x": "b"}, + result: true, + }, + { + // Equal label pair does not match + initial: map[model.Fingerprint]*types.Alert{ + 1: { + Alert: model.Alert{ + Labels: model.LabelSet{"a": "b"}, + StartsAt: now.Add(-time.Minute), + EndsAt: now.Add(time.Hour), + }, + }, + }, + equalPairs: LabelPairs{ + { + SourceLabel: "a", + TargetLabel: "x", + }, + }, + input: model.LabelSet{"x": "c"}, + result: false, + }, } for _, c := range cases { r := &InhibitRule{ - Equal: map[model.LabelName]struct{}{}, - scache: store.NewAlerts(), + EqualPairs: LabelPairs{}, + scache: store.NewAlerts(), } for _, ln := range c.equal { - r.Equal[ln] = struct{}{} + pair := LabelPair{ + SourceLabel: ln, + TargetLabel: ln, + } + r.EqualPairs = append(r.EqualPairs, pair) } + r.EqualPairs = append(r.EqualPairs, c.equalPairs...) + for _, v := range c.initial { r.scache.Set(v) } From f611d1c008dfd33a5b80e30140398ebd072859b0 Mon Sep 17 00:00:00 2001 From: swoga Date: Fri, 15 Sep 2023 14:41:11 +0200 Subject: [PATCH 2/2] docs: add docs for equal_pairs option Signed-off-by: swoga --- docs/configuration.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 731437f765..8005a59440 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -473,6 +473,18 @@ source_matchers: # Labels that must have an equal value in the source and target # alert for the inhibition to take effect. [ equal: '[' , ... ']' ] + +# Label pairs that must have an equal value in the source and target +# alert for the inhibition to take effect. +equal_pairs: + [ - ... ] + +``` + +#### `` +```yaml +source_label: +target_label: ``` ## Label matchers