From e1f9686e3f1dcc39613370530ab4e392d81dce4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 15 Jan 2019 22:12:23 +0000 Subject: [PATCH] feat(backend): allow stripping annotations This allows same filtering we already have with labels. Fixes #312 --- docs/CONFIGURATION.md | 19 ++++++++- internal/alertmanager/dedup.go | 3 +- internal/config/config.go | 5 +++ internal/config/config_test.go | 2 + internal/config/models.go | 2 + internal/transform/strip.go | 20 +++++++++ internal/transform/strip_test.go | 70 ++++++++++++++++++++++++++++++++ 7 files changed, 119 insertions(+), 2 deletions(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 35b72fe93..39646eef2 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -140,12 +140,21 @@ annotations: hidden: bool hidden: list of strings visible: list of strings + keep: list of strings + strip: list of strings ``` - `default:hidden` - bool, true if all annotations should be hidden by default. - `hidden` - list of annotations that should be hidden by default. - `visible` - list of annotations that should be visible by default when `default:hidden` is set to `true`. +- `keep` - list of allowed annotations, if empty all annotations are allowed. +- `strip` - list of ignored annotations. + +The difference between `hidden`/`visible` and `keep`/`strip` is that hidden +annotations are still accessible, but they are shown in the UI collapsed by +default (only name is visible, value is shown after clicking), while stripped +annotations are removed entirely and never presented to the user. Example where all annotations except `summary` are hidden by default. If there are additional annotation keys user will need to click on the `+` icon to see @@ -158,11 +167,16 @@ annotations: hidden: [] visible: - summary + keep: [] + strip: + - help + - verylong ``` Example where all annotations except `details` are visible by default. If `details` annotation is present on any alert user will need to click on the `+` -icon to see it. +icon to see it. Additionally `secret` annotation is stripped and never shown +in the UI. ```yaml annotations: @@ -171,6 +185,9 @@ annotations: hidden: - details visible: [] + keep: [] + strip: + - secret ``` Defaults: diff --git a/internal/alertmanager/dedup.go b/internal/alertmanager/dedup.go index 280fa1e76..5355671a9 100644 --- a/internal/alertmanager/dedup.go +++ b/internal/alertmanager/dedup.go @@ -70,8 +70,9 @@ func DedupAlerts() []models.AlertGroup { ag := models.AlertGroup(agList[0]) ag.Alerts = models.AlertList{} for _, alert := range alerts { - // strip labels user doesn't want to see in the UI + // strip labels and annotations user doesn't want to see in the UI alert.Labels = transform.StripLables(config.Config.Labels.Keep, config.Config.Labels.Strip, alert.Labels) + alert.Annotations = transform.StripAnnotations(config.Config.Annotations.Keep, config.Config.Annotations.Strip, alert.Annotations) // calculate final alert state based on the most important value found // in the list of states from all instances alertLFP := alert.LabelsFingerprint() diff --git a/internal/config/config.go b/internal/config/config.go index 6f0a60d70..713d09b67 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -39,6 +39,9 @@ func init() { "List of annotations that are hidden by default") pflag.StringSlice("annotations.visible", []string{}, "List of annotations that are visible by default") + pflag.StringSlice("annotations.keep", []string{}, + "List of annotations to keep, all other annotations will be stripped") + pflag.StringSlice("annotations.strip", []string{}, "List of annotations to ignore") pflag.String("config.file", "", "Full path to the configuration file") @@ -128,6 +131,8 @@ func (config *configSchema) Read() { config.Annotations.Default.Hidden = v.GetBool("annotations.default.hidden") config.Annotations.Hidden = v.GetStringSlice("annotations.hidden") config.Annotations.Visible = v.GetStringSlice("annotations.visible") + config.Annotations.Keep = v.GetStringSlice("annotations.keep") + config.Annotations.Strip = v.GetStringSlice("annotations.strip") config.Custom.CSS = v.GetString("custom.css") config.Custom.JS = v.GetString("custom.js") config.Debug = v.GetBool("debug") diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 3f64b6e77..f212ccc13 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -70,6 +70,8 @@ annotations: hidden: [] visible: - summary + keep: [] + strip: [] custom: css: /custom.css js: /custom.js diff --git a/internal/config/models.go b/internal/config/models.go index 4984bf567..f43edb76b 100644 --- a/internal/config/models.go +++ b/internal/config/models.go @@ -30,6 +30,8 @@ type configSchema struct { } Hidden []string Visible []string + Keep []string + Strip []string } Custom struct { CSS string diff --git a/internal/transform/strip.go b/internal/transform/strip.go index ac6aca737..81d1edd86 100644 --- a/internal/transform/strip.go +++ b/internal/transform/strip.go @@ -3,6 +3,7 @@ package transform import ( "strings" + "github.com/prymitive/karma/internal/models" "github.com/prymitive/karma/internal/slices" ) @@ -41,3 +42,22 @@ func StripReceivers(keptReceivers, ignoredReceivers []string, alertReceiver stri } return true } + +// StripAnnotations allows to ignore some annotations when pulling data +// Alertmanager, it will return true if passed annotation name should be +// stripped +func StripAnnotations(keptAnnotations, ignoredAnnotations []string, sourceAnnotations models.Annotations) models.Annotations { + // empty keep list means keep everything by default + keepAll := len(keptAnnotations) == 0 + annotations := models.Annotations{} + for _, annotation := range sourceAnnotations { + // is explicitly marked to be kept + inKeep := slices.StringInSlice(keptAnnotations, annotation.Name) + // is explicitly marked to be stripped + inStrip := slices.StringInSlice(ignoredAnnotations, annotation.Name) + if (keepAll || inKeep) && !inStrip { + annotations = append(annotations, annotation) + } + } + return annotations +} diff --git a/internal/transform/strip_test.go b/internal/transform/strip_test.go index a17c0260d..308e96ef9 100644 --- a/internal/transform/strip_test.go +++ b/internal/transform/strip_test.go @@ -4,6 +4,7 @@ import ( "reflect" "testing" + "github.com/prymitive/karma/internal/models" "github.com/prymitive/karma/internal/transform" ) @@ -162,3 +163,72 @@ func TestStripReceivers(t *testing.T) { } } } + +type stripAnnotationTest struct { + strip []string + keep []string + before models.Annotations + after models.Annotations +} + +var stripAnnotationTests = []stripAnnotationTest{ + { + strip: []string{}, + keep: []string{}, + before: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + after: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + }, + { + strip: []string{"foo"}, + keep: []string{}, + before: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + after: models.Annotations{}, + }, + { + strip: []string{"foo"}, + keep: []string{}, + before: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + models.Annotation{Name: "boo", Value: "baz"}, + }, + after: models.Annotations{ + models.Annotation{Name: "boo", Value: "baz"}, + }, + }, + { + strip: []string{}, + keep: []string{"foo"}, + before: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + after: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + }, + { + strip: []string{}, + keep: []string{"foo"}, + before: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + models.Annotation{Name: "boo", Value: "baz"}, + }, + after: models.Annotations{ + models.Annotation{Name: "foo", Value: "bar"}, + }, + }, +} + +func TestStripAnnotations(t *testing.T) { + for _, testCase := range stripAnnotationTests { + annotations := transform.StripAnnotations(testCase.keep, testCase.strip, testCase.before) + if !reflect.DeepEqual(annotations, testCase.after) { + t.Errorf("StripAnnotations failed, expected %v, got %v", testCase.after, annotations) + } + } +}