diff --git a/Makefile b/Makefile index 6ceddb3b8..4aea27c62 100644 --- a/Makefile +++ b/Makefile @@ -63,8 +63,8 @@ clean: .PHONY: run run: $(NAME) ALERTMANAGER_URI=$(ALERTMANAGER_URI) \ - COLORS_LABELS_UNIQUE="@receiver instance cluster" \ - COLORS_LABELS_STATIC="job" \ + LABELS_COLOR_UNIQUE="@receiver instance cluster" \ + LABELS_COLOR_STATIC="job" \ DEBUG="$(GIN_DEBUG)" \ FILTER_DEFAULT="@state=active" \ PORT=$(PORT) \ @@ -82,8 +82,8 @@ run-docker: docker-image $(DOCKER_ARGS) \ -v $(MOCK_PATH):$(MOCK_PATH) \ -e ALERTMANAGER_URI=$(ALERTMANAGER_URI) \ - -e COLOR_LABELS_UNIQUE="instance cluster" \ - -e COLOR_LABELS_STATIC="job" \ + -e LABELS_COLOR_UNIQUE="instance cluster" \ + -e LABELS_COLOR_STATIC="job" \ -e DEBUG="$(GIN_DEBUG)" \ -e PORT=$(PORT) \ -p $(PORT):$(PORT) \ diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 951fe4cf3..af2e60da6 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -124,68 +124,6 @@ annotations: visible: [] ``` -### Colors - -`colors` section allows configuring which labels should have colors applied -to label background in the UI. Colors can help visually identify alerts -with shared labels, for example coloring hostname label will allow to quickly -spot all alerts for the same host. -Syntax: - -```yaml -colors: - labels: - static: list of strings - unique: list of strings -``` - -* `static` - list of label names that will all have the same color applied - (different than the default label color). This allows to quickly spot a - specific label that can have high range of values, but it's important when - reading the dashboard. For example coloring the instance label allows to - quickly learn which instance is affected by given alert. -* `unique` - list of label names that should have unique colors generated in - the UI. - -Example with static color for the `job` label (every `job` label will have the -same color regardless of the value) and unique color for the `@receiver` label -(every `@receiver` label will have color unique for each value). - -```yaml -colors: - labels: - static: - - job - unique: - - "@receiver" -``` - -Defaults: - -```yaml -colors: - labels: - static: [] - unique: [] -``` - -### Debug - -`debug` key allows enabling [gin](https://github.com/gin-gonic/gin) debug mode. -It will also configure to print out more debugging information on startup and -enable [https://golang.org/pkg/net/http/pprof/](pprof) debug paths. -Syntax: - -```yaml -debug: bool -``` - -Defaults: - -```yaml -debug: false -``` - ### Filters `filters` section allows configuring default set of filters used in the UI. @@ -219,21 +157,49 @@ filters: ### Labels -`labels` section allows configuring which alert labels will be rendered in the -UI. All labels will be parsed when collecting alerts from Alertmanager API and -used when deduplicating alerts, this section is only used to UI rendering and -should be used to remove those alerts that are not useful to users. +`labels` section allows configuring how alert labels will be rendered in the +UI. +All labels will be parsed when collecting alerts from Alertmanager API and +used when deduplicating alerts, but some labels aren't useful to users and so +can be removed from the UI, this is controlled by `keep` and `strip` options. +`colors` section allows configuring which labels should have colors applied +to label background in the UI. Colors can help visually identify alerts +with shared labels, for example coloring hostname label will allow to quickly +spot all alerts for the same host. Syntax: ```yaml labels: + color: + static: [] + unique: [] keep: list of strings strip: list of strings ``` +* `color:static` - list of label names that will all have the same color applied + (different than the default label color). This allows to quickly spot a + specific label that can have high range of values, but it's important when + reading the dashboard. For example coloring the instance label allows to + quickly learn which instance is affected by given alert. +* `color:unique` - list of label names that should have unique colors generated + in the UI. * `keep` - list of allowed labels, if empty all labels are allowed. * `strip` - list of ignored labels. +Example with static color for the `job` label (every `job` label will have the +same color regardless of the value) and unique color for the `@receiver` label +(every `@receiver` label will have color unique for each value). + +```yaml +colors: + labels: + static: + - job + unique: + - "@receiver" +``` + Example where `task_id` label is ignored by unsee: ```yaml @@ -257,6 +223,9 @@ Defaults: ```yaml labels: + color: + static: [] + unique: [] keep: [] strip: [] ``` diff --git a/docs/example.yaml b/docs/example.yaml index f83dc2d5b..964e29ad5 100644 --- a/docs/example.yaml +++ b/docs/example.yaml @@ -10,19 +10,18 @@ annotations: hidden: - help visible: [] -colors: - labels: +debug: false +filters: + default: + - "@receiver=by-cluster-service" +labels: + color: static: - job unique: - cluster - instance - "@receiver" -debug: false -filters: - default: - - "@receiver=by-cluster-service" -labels: keep: [] strip: [] listen: @@ -35,6 +34,7 @@ jira: - regex: DEVOPS-[0-9]+ uri: https://jira.example.com receivers: + keep: [] strip: [] sentry: private: secret diff --git a/internal/alertmanager/benchmark_test.go b/internal/alertmanager/benchmark_test.go index 8641ac501..499c68480 100644 --- a/internal/alertmanager/benchmark_test.go +++ b/internal/alertmanager/benchmark_test.go @@ -27,7 +27,7 @@ func BenchmarkDedupAutocomplete(b *testing.B) { } func BenchmarkDedupColors(b *testing.B) { - os.Setenv("COLORS_LABELS_UNIQUE", "cluster instance @receiver") + os.Setenv("LABELS_COLOR_UNIQUE", "cluster instance @receiver") os.Setenv("ALERTMANAGER_URI", "http://localhost") config.Config.Read() if err := pullAlerts(); err != nil { diff --git a/internal/alertmanager/dedup_test.go b/internal/alertmanager/dedup_test.go index 9eb9d4765..039f9ec9e 100644 --- a/internal/alertmanager/dedup_test.go +++ b/internal/alertmanager/dedup_test.go @@ -87,7 +87,7 @@ func TestDedupAutocomplete(t *testing.T) { } func TestDedupColors(t *testing.T) { - os.Setenv("COLORS_LABELS_UNIQUE", "cluster instance @receiver") + os.Setenv("LABELS_COLOR_UNIQUE", "cluster instance @receiver") os.Setenv("ALERTMANAGER_URI", "http://localhost") config.Config.Read() if err := pullAlerts(); err != nil { diff --git a/internal/config/config.go b/internal/config/config.go index 573065772..c96dd1f26 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -36,11 +36,6 @@ func init() { pflag.StringSlice("annotations.visible", []string{}, "List of annotations that are visible by default") - pflag.StringSlice("colors.labels.static", []string{}, - "List of label names that should have the same (but distinct) color") - pflag.StringSlice("colors.labels.unique", []string{}, - "List of label names that should have unique color") - pflag.StringVar(&configDir, "config.dir", ".", "Directory with configuration file to read") pflag.StringVar(&configFile, "config.file", "unsee", @@ -50,6 +45,10 @@ func init() { pflag.StringSlice("filters.default", []string{}, "List of default filters") + pflag.StringSlice("labels.color.static", []string{}, + "List of label names that should have the same (but distinct) color") + pflag.StringSlice("labels.color.unique", []string{}, + "List of label names that should have unique color") pflag.StringSlice("labels.keep", []string{}, "List of labels to keep, all other labels will be stripped") pflag.StringSlice("labels.strip", []string{}, "List of labels to ignore") @@ -112,10 +111,10 @@ 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.Colors.Labels.Static = v.GetStringSlice("colors.labels.static") - config.Colors.Labels.Unique = v.GetStringSlice("colors.labels.unique") config.Debug = v.GetBool("debug") config.Filters.Default = v.GetStringSlice("filters.default") + config.Labels.Color.Static = v.GetStringSlice("labels.color.static") + config.Labels.Color.Unique = v.GetStringSlice("labels.color.unique") config.Labels.Keep = v.GetStringSlice("labels.keep") config.Labels.Strip = v.GetStringSlice("labels.strip") config.Listen.Address = v.GetString("listen.address") diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 352d99418..c1923ac59 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -17,14 +17,14 @@ func testReadConfig(t *testing.T) { if Config.Debug != true { t.Errorf("Config.Debug is %v with env DEBUG=true set", Config.Debug) } - if !slices.StringInSlice(Config.Colors.Labels.Static, "a") { - t.Errorf("Config.Colors.Labels.Static is missing value 'a': %v", Config.Colors.Labels.Static) + if !slices.StringInSlice(Config.Labels.Color.Static, "a") { + t.Errorf("Config.Colors.Labels.Static is missing value 'a': %v", Config.Labels.Color.Static) } - if !slices.StringInSlice(Config.Colors.Labels.Static, "bb") { - t.Errorf("Config.Colors.Labels.Static is missing value 'bb': %v", Config.Colors.Labels.Static) + if !slices.StringInSlice(Config.Labels.Color.Static, "bb") { + t.Errorf("Config.Colors.Labels.Static is missing value 'bb': %v", Config.Labels.Color.Static) } - if !slices.StringInSlice(Config.Colors.Labels.Static, "ccc") { - t.Errorf("Config.Colors.Labels.Static is missing value 'ccc': %v", Config.Colors.Labels.Static) + if !slices.StringInSlice(Config.Labels.Color.Static, "ccc") { + t.Errorf("Config.Colors.Labels.Static is missing value 'ccc': %v", Config.Labels.Color.Static) } if Config.Listen.Port != 8080 { t.Errorf("Config.Listen.Port is invalid, expected 8080, got %v", Config.Listen.Port) @@ -50,7 +50,7 @@ func TestReadConfig(t *testing.T) { os.Setenv("ALERTMANAGER_INTERVAL", "1s") os.Setenv("ALERTMANAGER_URIS", "default:http://localhost") os.Setenv("DEBUG", "true") - os.Setenv("COLORS_LABELS_STATIC", "a bb ccc") + os.Setenv("LABELS_COLOR_STATIC", "a bb ccc") Config.Read() testReadConfig(t) } diff --git a/internal/config/legacy.go b/internal/config/legacy.go index 1bf606b8c..aae58cc62 100644 --- a/internal/config/legacy.go +++ b/internal/config/legacy.go @@ -15,8 +15,8 @@ func (config *configSchema) legacyEnvs(v *viper.Viper) { v.BindEnv("annotations.default.hidden", "ANNOTATIONS_DEFAULT_HIDDEN") v.BindEnv("annotations.hidden", "ANNOTATIONS_HIDE") v.BindEnv("annotations.visible", "ANNOTATIONS_SHOW") - v.BindEnv("colors.labels.static", "COLOR_LABELS_STATIC") - v.BindEnv("colors.labels.unique", "COLOR_LABELS_UNIQUE") + v.BindEnv("labels.color.static", "COLOR_LABELS_STATIC") + v.BindEnv("labels.color.unique", "COLOR_LABELS_UNIQUE") v.BindEnv("filters.default", "FILTER_DEFAULT") v.BindEnv("labels.keep", "KEEP_LABELS") v.BindEnv("labels.strip", "STRIP_LABELS") diff --git a/internal/config/models.go b/internal/config/models.go index d418ef9e7..aeaab158a 100644 --- a/internal/config/models.go +++ b/internal/config/models.go @@ -25,12 +25,6 @@ type configSchema struct { Hidden []string Visible []string } - Colors struct { - Labels struct { - Static []string - Unique []string - } - } Debug bool Filters struct { Default []string @@ -38,6 +32,10 @@ type configSchema struct { Labels struct { Keep []string Strip []string + Color struct { + Static []string + Unique []string + } } Listen struct { Address string diff --git a/internal/transform/color_test.go b/internal/transform/color_test.go index a72e30c3e..3ff895b09 100644 --- a/internal/transform/color_test.go +++ b/internal/transform/color_test.go @@ -58,7 +58,7 @@ var colorTests = []colorTest{ func TestColorLabel(t *testing.T) { for _, testCase := range colorTests { - config.Config.Colors.Labels.Unique = testCase.config + config.Config.Labels.Color.Unique = testCase.config colorStore := models.LabelsColorMap{} for key, value := range testCase.labels { transform.ColorLabel(colorStore, key, value) diff --git a/internal/transform/colors.go b/internal/transform/colors.go index 17e20e9f0..18e193585 100644 --- a/internal/transform/colors.go +++ b/internal/transform/colors.go @@ -27,7 +27,7 @@ func labelToSeed(key string, val string) int64 { // from label key and value passed here // It's used to generate unique colors for configured labels func ColorLabel(colorStore models.LabelsColorMap, key string, val string) { - if slices.StringInSlice(config.Config.Colors.Labels.Unique, key) == true { + if slices.StringInSlice(config.Config.Labels.Color.Unique, key) == true { if _, found := colorStore[key]; !found { colorStore[key] = make(map[string]models.LabelColors) } diff --git a/views.go b/views.go index f06bf70d2..c190c78f0 100644 --- a/views.go +++ b/views.go @@ -44,7 +44,7 @@ func index(c *gin.Context) { "QFilter": q, "DefaultUsed": defaultUsed, "DefaultFilter": strings.Join(config.Config.Filters.Default, ","), - "StaticColorLabels": strings.Join(config.Config.Colors.Labels.Static, " "), + "StaticColorLabels": strings.Join(config.Config.Labels.Color.Static, " "), "WebPrefix": config.Config.Listen.Prefix, }) diff --git a/views_test.go b/views_test.go index a3a2250d4..de832cb77 100644 --- a/views_test.go +++ b/views_test.go @@ -28,7 +28,7 @@ var upstreamSetup = false func mockConfig() { log.SetLevel(log.ErrorLevel) os.Setenv("ALERTMANAGER_URI", "http://localhost") - os.Setenv("COLORS_LABELS_UNIQUE", "alertname") + os.Setenv("LABELS_COLOR_UNIQUE", "alertname") config.Config.Read() if !upstreamSetup { upstreamSetup = true