mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
Add --receivers.keep for consistency with other options
there's --labels.keep so same should apply to receivers, add new option, tests and fixes as it wasn't working properly
This commit is contained in:
+13
-6
@@ -355,19 +355,19 @@ jira: []
|
||||
### Receivers
|
||||
|
||||
`receivers` section allows configuring how alerts from different receivers are
|
||||
handled by unsee.
|
||||
handled by unsee. If alerts are routed to multiple receivers they can be
|
||||
duplicated in the UI, each instance will have different value for `@receiver`.
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
receivers:
|
||||
keep: list of strings
|
||||
strip: list of strings
|
||||
```
|
||||
|
||||
* `strip` - list of receiver names that should be ignored when collecting data
|
||||
from Alertmanager API. If alerts are routed to multiple receivers they can be
|
||||
duplicated in the UI, each instance will have different value for `@receiver`.
|
||||
This options allows to set a list of receivers that will not be shown in the
|
||||
UI.
|
||||
* `keep` - list of receivers name that are allowed, if empty all receivers are
|
||||
allowed.
|
||||
* `strip` - list of receiver names that will not be shown in the UI.
|
||||
|
||||
Example where alerts that are routed to the `alertmanage2es` receiver are
|
||||
ignored by unsee.
|
||||
@@ -433,3 +433,10 @@ Exaceptions:
|
||||
Environment variables are mapped in a similiar way as command line flags,
|
||||
`alertmanager:interval` is accessible as `ALERTMANAGER_INTERVAL` env.
|
||||
Same exceptions apply as with command line flags.
|
||||
|
||||
* `HOST` - used by gin webserver, same effect as setting `listen:address` config
|
||||
option
|
||||
* `PORT` - used by gin webserver, same effect as setting `listen:port` config
|
||||
option
|
||||
* `SENTRY_DSN` - is used by Sentry itself, same effect as passing value to
|
||||
`sentry:private` config option.
|
||||
|
||||
@@ -31,6 +31,11 @@ func DedupAlerts() []models.AlertGroup {
|
||||
alerts := map[string]models.Alert{}
|
||||
for _, ag := range agList {
|
||||
for _, alert := range ag.Alerts {
|
||||
// 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) {
|
||||
continue
|
||||
}
|
||||
alertLFP := alert.LabelsFingerprint()
|
||||
a, found := alerts[alertLFP]
|
||||
if found {
|
||||
@@ -60,14 +65,13 @@ func DedupAlerts() []models.AlertGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip empty groups
|
||||
if len(alerts) == 0 {
|
||||
continue
|
||||
}
|
||||
ag := models.AlertGroup(agList[0])
|
||||
ag.Alerts = models.AlertList{}
|
||||
for _, alert := range alerts {
|
||||
// remove all alerts for receiver(s) that the user doesn't
|
||||
// want to see in the UI
|
||||
if transform.StripReceivers(config.Config.Receivers.Strip, alert.Receiver) {
|
||||
continue
|
||||
}
|
||||
// strip labels user doesn't want to see in the UI
|
||||
alert.Labels = transform.StripLables(config.Config.Labels.Keep, config.Config.Labels.Strip, alert.Labels)
|
||||
// calculate final alert state based on the most important value found
|
||||
|
||||
@@ -99,3 +99,16 @@ func TestDedupColors(t *testing.T) {
|
||||
t.Errorf("Expected %d color keys, got %d", expected, len(colors))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripReceivers(t *testing.T) {
|
||||
os.Setenv("RECEIVERS_STRIP", "by-name by-cluster-service")
|
||||
os.Setenv("ALERTMANAGER_URI", "http://localhost")
|
||||
config.Config.Read()
|
||||
if err := pullAlerts(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
alerts := alertmanager.DedupAlerts()
|
||||
if len(alerts) > 0 {
|
||||
t.Errorf("Expected no alerts after stripping all receivers, got %d", len(alerts))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ func init() {
|
||||
pflag.String("log.level", "info",
|
||||
"Log level, one of: debug, info, warning, error, fatal and panic")
|
||||
|
||||
pflag.StringSlice("receivers.keep", []string{},
|
||||
"List of receivers to keep, all alerts with different receivers will be ignored")
|
||||
pflag.StringSlice("receivers.strip", []string{},
|
||||
"List of receivers to not display alerts for")
|
||||
|
||||
@@ -121,6 +123,7 @@ func (config *configSchema) Read() {
|
||||
config.Listen.Prefix = v.GetString("listen.prefix")
|
||||
config.Log.Config = v.GetBool("log.config")
|
||||
config.Log.Level = v.GetString("log.level")
|
||||
config.Receivers.Keep = v.GetStringSlice("receivers.keep")
|
||||
config.Receivers.Strip = v.GetStringSlice("receivers.strip")
|
||||
config.Sentry.Private = v.GetString("sentry.private")
|
||||
config.Sentry.Public = v.GetString("sentry.public")
|
||||
|
||||
@@ -36,8 +36,8 @@ type configSchema struct {
|
||||
Default []string
|
||||
}
|
||||
Labels struct {
|
||||
Strip []string
|
||||
Keep []string
|
||||
Strip []string
|
||||
}
|
||||
Listen struct {
|
||||
Address string
|
||||
@@ -50,6 +50,7 @@ type configSchema struct {
|
||||
}
|
||||
JIRA []jiraRule
|
||||
Receivers struct {
|
||||
Keep []string
|
||||
Strip []string
|
||||
}
|
||||
Sentry struct {
|
||||
|
||||
@@ -28,11 +28,16 @@ func StripLables(keptLabels, ignoredLabels []string, sourceLabels map[string]str
|
||||
}
|
||||
|
||||
// StripReceivers allows filtering all alerts for specified receiver(s)
|
||||
func StripReceivers(ignoredReceivers []string, alertReceiver string) bool {
|
||||
for _, ignoredReceiver := range ignoredReceivers {
|
||||
if alertReceiver == ignoredReceiver {
|
||||
return true
|
||||
}
|
||||
// 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)
|
||||
if (keepAll || inKeep) && !inStrip {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
"github.com/cloudflare/unsee/internal/transform"
|
||||
)
|
||||
|
||||
type stripTest struct {
|
||||
type stripLabelTest struct {
|
||||
strip []string
|
||||
keep []string
|
||||
before map[string]string
|
||||
after map[string]string
|
||||
}
|
||||
|
||||
var stripTests = []stripTest{
|
||||
stripTest{
|
||||
var stripLabelTests = []stripLabelTest{
|
||||
stripLabelTest{
|
||||
strip: []string{"env"},
|
||||
keep: []string{},
|
||||
before: map[string]string{
|
||||
@@ -28,7 +28,7 @@ var stripTests = []stripTest{
|
||||
"level": "info",
|
||||
},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{"server"},
|
||||
keep: []string{},
|
||||
before: map[string]string{
|
||||
@@ -42,7 +42,7 @@ var stripTests = []stripTest{
|
||||
"level": "info",
|
||||
},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{},
|
||||
keep: []string{},
|
||||
before: map[string]string{
|
||||
@@ -56,7 +56,7 @@ var stripTests = []stripTest{
|
||||
"level": "info",
|
||||
},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{"host"},
|
||||
keep: []string{},
|
||||
before: map[string]string{
|
||||
@@ -64,7 +64,7 @@ var stripTests = []stripTest{
|
||||
},
|
||||
after: map[string]string{},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{},
|
||||
keep: []string{"env"},
|
||||
before: map[string]string{
|
||||
@@ -76,7 +76,7 @@ var stripTests = []stripTest{
|
||||
"env": "production",
|
||||
},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{"env"},
|
||||
keep: []string{"host"},
|
||||
before: map[string]string{
|
||||
@@ -88,7 +88,7 @@ var stripTests = []stripTest{
|
||||
"host": "localhost",
|
||||
},
|
||||
},
|
||||
stripTest{
|
||||
stripLabelTest{
|
||||
strip: []string{},
|
||||
keep: []string{"env"},
|
||||
before: map[string]string{
|
||||
@@ -100,10 +100,65 @@ var stripTests = []stripTest{
|
||||
}
|
||||
|
||||
func TestStripLables(t *testing.T) {
|
||||
for _, testCase := range stripTests {
|
||||
for _, testCase := range stripLabelTests {
|
||||
labels := transform.StripLables(testCase.keep, testCase.strip, testCase.before)
|
||||
if !reflect.DeepEqual(labels, testCase.after) {
|
||||
t.Errorf("StripLables failed, expected %v, got %v", testCase.after, labels)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type stripReceiverTest struct {
|
||||
strip []string
|
||||
keep []string
|
||||
receiver string
|
||||
stripped bool
|
||||
}
|
||||
|
||||
var stripReceiverTests = []stripReceiverTest{
|
||||
stripReceiverTest{
|
||||
strip: []string{},
|
||||
keep: []string{},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
stripReceiverTest{
|
||||
strip: []string{"default"},
|
||||
keep: []string{},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
stripReceiverTest{
|
||||
strip: []string{"default"},
|
||||
keep: []string{"default"},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
stripReceiverTest{
|
||||
strip: []string{},
|
||||
keep: []string{"default"},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
stripReceiverTest{
|
||||
strip: []string{"foo", "bar"},
|
||||
keep: []string{},
|
||||
receiver: "default",
|
||||
stripped: false,
|
||||
},
|
||||
stripReceiverTest{
|
||||
strip: []string{"foo", "default"},
|
||||
keep: []string{"foo", "bar"},
|
||||
receiver: "default",
|
||||
stripped: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestStripReceivers(t *testing.T) {
|
||||
for _, testCase := range stripReceiverTests {
|
||||
stripped := transform.StripReceivers(testCase.keep, testCase.strip, testCase.receiver)
|
||||
if stripped != testCase.stripped {
|
||||
t.Errorf("StripReceivers failed, expected %v, got %v", testCase.stripped, stripped)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user