mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
feat: support regular expressions in receiver configs
This allows using the `keep_re` and `strip_re` keys to specify which receivers should be shown in the dashboard. This makes it easy to select groups of receivers based on naming conventions.
This commit is contained in:
committed by
Łukasz Mierzwa
parent
60b0fa572a
commit
d8d97b8914
@@ -221,9 +221,11 @@ level=info msg="receivers:"
|
||||
level=info msg=" keep:"
|
||||
level=info msg=" - keep1"
|
||||
level=info msg=" - keep2"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip:"
|
||||
level=info msg=" - strip1"
|
||||
level=info msg=" - strip2"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 1s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -257,9 +257,11 @@ level=info msg="receivers:"
|
||||
level=info msg=" keep:"
|
||||
level=info msg=" - keep1"
|
||||
level=info msg=" - keep2"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip:"
|
||||
level=info msg=" - strip1"
|
||||
level=info msg=" - strip2"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 5m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -113,7 +113,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -113,7 +113,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -113,7 +113,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -123,7 +123,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -113,7 +113,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -92,7 +92,9 @@ level=info msg=" requests: false"
|
||||
level=info msg=" timestamp: false"
|
||||
level=info msg="receivers:"
|
||||
level=info msg=" keep: []"
|
||||
level=info msg=" keep_re: []"
|
||||
level=info msg=" strip: []"
|
||||
level=info msg=" strip_re: []"
|
||||
level=info msg="silences:"
|
||||
level=info msg=" expired: 10m0s"
|
||||
level=info msg=" comments:"
|
||||
|
||||
@@ -37,7 +37,13 @@ func DedupAlerts() []models.AlertGroup {
|
||||
alert := alert // scopelint pin
|
||||
// remove all alerts for receiver(s) that the user doesn't
|
||||
// want to see in the UI
|
||||
if transform.StripReceivers(config.Config.Receivers.Keep, config.Config.Receivers.Strip, alert.Receiver) {
|
||||
if transform.StripReceivers(
|
||||
config.Config.Receivers.Keep,
|
||||
config.Config.Receivers.Strip,
|
||||
config.Config.Receivers.CompiledKeepRegex,
|
||||
config.Config.Receivers.CompiledStripRegex,
|
||||
alert.Receiver,
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,12 @@ func SetupFlags(f *pflag.FlagSet) {
|
||||
|
||||
f.StringSlice("receivers.keep", []string{},
|
||||
"List of receivers to keep, all alerts with different receivers will be ignored")
|
||||
f.StringSlice("receivers.keep_re", []string{},
|
||||
"List of regular expressions to keep matching receivers, all other receivers will be ignored")
|
||||
f.StringSlice("receivers.strip", []string{},
|
||||
"List of receivers to not display alerts for")
|
||||
f.StringSlice("receivers.strip_re", []string{},
|
||||
"List of regular expressions to ignore matching receivers")
|
||||
|
||||
f.Duration("silences.expired", time.Minute*10, "Maximum age of expired silences to show on active alerts")
|
||||
f.StringSlice("silenceForm.strip.labels", []string{}, "List of labels to ignore when auto-filling silence form from alerts")
|
||||
@@ -413,6 +417,22 @@ func (config *configSchema) Read(flags *pflag.FlagSet) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
config.Receivers.CompiledKeepRegex = make([]*regexp.Regexp, len(config.Receivers.KeepRegex))
|
||||
for i, keepRegex := range config.Receivers.KeepRegex {
|
||||
config.Receivers.CompiledKeepRegex[i], err = regex.CompileAnchored(keepRegex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("keep regex rule '%s' is invalid: %w", keepRegex, err)
|
||||
}
|
||||
}
|
||||
|
||||
config.Receivers.CompiledStripRegex = make([]*regexp.Regexp, len(config.Receivers.StripRegex))
|
||||
for i, stripRegex := range config.Receivers.KeepRegex {
|
||||
config.Receivers.CompiledStripRegex[i], err = regex.CompileAnchored(stripRegex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("strip regex rule '%s' is invalid: %w", stripRegex, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !slices.StringInSlice([]string{"disabled", "startsAt", "label"}, config.Grid.Sorting.Order) {
|
||||
return "", fmt.Errorf("invalid grid.sorting.order value '%s', allowed options: disabled, startsAt, label", config.Grid.Sorting.Order)
|
||||
}
|
||||
|
||||
@@ -195,8 +195,12 @@ type configSchema struct {
|
||||
Timestamp bool
|
||||
}
|
||||
Receivers struct {
|
||||
Keep []string
|
||||
Strip []string
|
||||
Keep []string
|
||||
KeepRegex []string `yaml:"keep_re" koanf:"keep_re"`
|
||||
CompiledKeepRegex []*regexp.Regexp `yaml:"-"`
|
||||
Strip []string
|
||||
StripRegex []string `yaml:"strip_re" koanf:"strip_re"`
|
||||
CompiledStripRegex []*regexp.Regexp `yaml:"-"`
|
||||
}
|
||||
Silences struct {
|
||||
Expired time.Duration
|
||||
|
||||
@@ -40,13 +40,14 @@ func StripLables(keptLabels, ignoredLabels []string, keptLabelsRegex, ignoredLab
|
||||
|
||||
// StripReceivers allows filtering all alerts for specified receiver(s)
|
||||
// it will return true if alert uses receiver that should be stripped
|
||||
func StripReceivers(keptReceivers, ignoredReceivers []string, alertReceiver string) bool {
|
||||
// true if we keep by default
|
||||
keepAll := len(keptReceivers) == 0
|
||||
// is this receiver on the whitelist ?
|
||||
inKeep := slices.StringInSlice(keptReceivers, alertReceiver)
|
||||
// is this receiver on the blacklist ?
|
||||
inStrip := slices.StringInSlice(ignoredReceivers, alertReceiver)
|
||||
func StripReceivers(keptReceivers, ignoredReceivers []string, keptReceiversRegex, ignoredReceiversRegex []*regexp.Regexp, alertReceiver string) bool {
|
||||
// empty keep lists means keep everything by default
|
||||
keepAll := len(keptReceivers) == 0 && len(keptReceiversRegex) == 0
|
||||
// is explicitly marked to be kept
|
||||
inKeep := slices.StringInSlice(keptReceivers, alertReceiver) || slices.MatchesAnyRegex(alertReceiver, keptReceiversRegex)
|
||||
// is explicitly marked to be stripped
|
||||
inStrip := slices.StringInSlice(ignoredReceivers, alertReceiver) || slices.MatchesAnyRegex(alertReceiver, ignoredReceiversRegex)
|
||||
|
||||
if (keepAll || inKeep) && !inStrip {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -201,6 +201,8 @@ func getCompiledRegex(regexes []string, t *testing.T) []*regexp.Regexp {
|
||||
type stripReceiverTest struct {
|
||||
strip []string
|
||||
keep []string
|
||||
stripRe []string
|
||||
keepRe []string
|
||||
receiver string
|
||||
stripped bool
|
||||
}
|
||||
@@ -209,44 +211,82 @@ var stripReceiverTests = []stripReceiverTest{
|
||||
{
|
||||
strip: []string{},
|
||||
keep: []string{},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
{
|
||||
strip: []string{"default"},
|
||||
keep: []string{},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
{
|
||||
strip: []string{"default"},
|
||||
keep: []string{"default"},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
{
|
||||
strip: []string{},
|
||||
keep: []string{"default"},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
{
|
||||
strip: []string{"foo", "bar"},
|
||||
keep: []string{},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
{
|
||||
strip: []string{"foo", "default"},
|
||||
keep: []string{"foo", "bar"},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
{
|
||||
strip: []string{},
|
||||
keep: []string{},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{"default-.+"},
|
||||
receiver: "default-foo",
|
||||
stripped: false,
|
||||
},
|
||||
{
|
||||
strip: []string{},
|
||||
keep: []string{},
|
||||
stripRe: []string{},
|
||||
keepRe: []string{"default-.+"},
|
||||
receiver: "foo-bar",
|
||||
stripped: true,
|
||||
},
|
||||
{
|
||||
strip: []string{},
|
||||
keep: []string{"default-foo"},
|
||||
stripRe: []string{"default-.+"},
|
||||
keepRe: []string{},
|
||||
receiver: "default-foo",
|
||||
stripped: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestStripReceivers(t *testing.T) {
|
||||
for _, testCase := range stripReceiverTests {
|
||||
stripped := transform.StripReceivers(testCase.keep, testCase.strip, testCase.receiver)
|
||||
keepRegex := getCompiledRegex(testCase.keepRe, t)
|
||||
stripRegex := getCompiledRegex(testCase.keepRe, t)
|
||||
stripped := transform.StripReceivers(testCase.keep, testCase.strip, keepRegex, stripRegex, testCase.receiver)
|
||||
if stripped != testCase.stripped {
|
||||
t.Errorf("StripReceivers failed, expected %v, got %v", testCase.stripped, stripped)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user