feat(backend): add auto multi-grid config

This commit is contained in:
Łukasz Mierzwa
2021-04-21 10:51:18 +01:00
committed by Łukasz Mierzwa
parent d655faf393
commit e0f52dacbd
16 changed files with 151 additions and 2 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog
## [unreleased]
### Added
- Added `grid:auto` config section for fine tuning automatic label selection
for multi-grid, when multi-grid is configured to `Automatic selection`
in the UI or when `ui:multiGridLabel` config section is set to `@auto`.
## v0.83
### Added
+24 -2
View File
@@ -13,6 +13,7 @@ import (
"github.com/prymitive/karma/internal/config"
"github.com/prymitive/karma/internal/filters"
"github.com/prymitive/karma/internal/models"
"github.com/prymitive/karma/internal/slices"
"github.com/prymitive/karma/internal/uri"
)
@@ -265,6 +266,24 @@ func sortGrids(r *http.Request, gridLabel string, gridsMap map[string]models.API
return grids
}
func isPreferredLabel(label, other string) bool {
ai, aj := -1, -1
for index, name := range config.Config.Grid.Auto.Order {
if label == name {
ai = index
} else if other == name {
aj = index
}
if ai >= 0 && aj >= 0 {
return ai < aj
}
}
if ai != aj {
return aj < ai
}
return label < other
}
func autoGridLabel(dedupedAlerts []models.AlertGroup) string {
var alertsCount, alertGroupsCount int
labelNameToValueCount := map[string]map[string]int{}
@@ -287,6 +306,9 @@ func autoGridLabel(dedupedAlerts []models.AlertGroup) string {
candidates := map[string]int{}
for key, vals := range labelNameToValueCount {
if slices.StringInSlice(config.Config.Grid.Auto.Ignore, key) {
continue
}
var total int
uniqueValues := map[string]struct{}{}
for val, cnt := range vals {
@@ -303,11 +325,11 @@ func autoGridLabel(dedupedAlerts []models.AlertGroup) string {
var lastLabel string
var lastCnt int
for key, uniqueValues := range candidates {
log.Debug().Int("variants", uniqueValues).Str("label", key).Msg("Automatic grid label candidate")
if uniqueValues == 1 || uniqueValues == alertsCount || uniqueValues == alertGroupsCount {
continue
}
if lastCnt == 0 || uniqueValues < lastCnt || (uniqueValues == lastCnt && key > lastLabel) {
log.Debug().Int("variants", uniqueValues).Str("label", key).Msg("Automatic grid label candidate")
if lastCnt == 0 || uniqueValues < lastCnt || (uniqueValues == lastCnt && isPreferredLabel(key, lastLabel)) {
lastLabel = key
lastCnt = uniqueValues
}
@@ -32,6 +32,8 @@ env FILTERS_DEFAULT='@receiver=by-cluster-service @state=active'
env GRID_SORTING_ORDER=label
env GRID_SORTING_REVERSE=false
env GRID_SORTING_LABEL=severity
env GRID_AUTO_IGNORE="region instance"
env GRID_AUTO_ORDER="severity cluster"
env KARMA_NAME=karma-demo
@@ -146,6 +148,11 @@ level=info msg=" reverse: false"
level=info msg=" label: severity"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore:"
level=info msg=" - '\"region'"
level=info msg=" order:"
level=info msg=" - '\"severity'"
level=info msg="karma:"
level=info msg=" name: karma-demo"
level=info msg="labels:"
@@ -160,6 +160,13 @@ level=info msg=" severity:"
level=info msg=" critical: \"1\""
level=info msg=" info: \"3\""
level=info msg=" warning: \"2\""
level=info msg=" auto:"
level=info msg=" ignore:"
level=info msg=" - region"
level=info msg=" - instance"
level=info msg=" order:"
level=info msg=" - severity"
level=info msg=" - cluster"
level=info msg="karma:"
level=info msg=" name: karma-demo"
level=info msg="labels:"
@@ -346,6 +353,13 @@ grid:
critical: 1
warning: 2
info: 3
auto:
ignore:
- region
- instance
order:
- severity
- cluster
karma:
name: karma-demo
labels:
@@ -67,6 +67,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
+3
View File
@@ -67,6 +67,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
@@ -67,6 +67,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
@@ -69,6 +69,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
@@ -67,6 +67,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
@@ -67,6 +67,9 @@ level=info msg=" reverse: true"
level=info msg=" label: alertname"
level=info msg=" customValues:"
level=info msg=" labels: {}"
level=info msg=" auto:"
level=info msg=" ignore: []"
level=info msg=" order: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
+48
View File
@@ -2660,6 +2660,8 @@ func TestAutoGrid(t *testing.T) {
type testCaseT struct {
q string
gridLabel string
ignore []string
order []string
}
testCases := []testCaseT{
@@ -2671,6 +2673,42 @@ func TestAutoGrid(t *testing.T) {
q: "gridLabel=@auto",
gridLabel: "job",
},
{
q: "gridLabel=@auto&q=cluster!=prod",
gridLabel: "cluster",
ignore: []string{"job"},
order: []string{"cluster"},
},
{
q: "gridLabel=@auto&q=cluster!=prod",
gridLabel: "cluster",
ignore: []string{},
order: []string{"cluster"},
},
{
q: "gridLabel=@auto&q=cluster!=prod",
gridLabel: "job",
ignore: []string{},
order: []string{"job", "cluster"},
},
{
q: "gridLabel=@auto&q=job=node_exporter",
gridLabel: "cluster",
ignore: []string{},
order: []string{"job", "cluster"},
},
{
q: "gridLabel=@auto&q=cluster=dev",
gridLabel: "job",
ignore: []string{},
order: []string{"job", "cluster"},
},
{
q: "gridLabel=@auto&q=cluster=dev",
gridLabel: "alertname",
ignore: []string{},
order: []string{},
},
{
q: "gridLabel=job",
gridLabel: "job",
@@ -2678,19 +2716,29 @@ func TestAutoGrid(t *testing.T) {
{
q: "gridLabel=@auto&q=instance=server5",
gridLabel: "job",
ignore: []string{"alertname"},
},
{
q: "gridLabel=@auto&q=job=node_exporter",
gridLabel: "cluster",
ignore: []string{"alertname"},
},
{
q: "gridLabel=@auto&q=cluster=prod",
gridLabel: "job",
ignore: []string{"alertname", "instance"},
},
}
defer func() {
config.Config.Grid.Auto.Ignore = []string{}
config.Config.Grid.Auto.Order = []string{}
}()
mockConfig()
for _, tc := range testCases {
config.Config.Grid.Auto.Ignore = tc.ignore
config.Config.Grid.Auto.Order = tc.order
for _, version := range mock.ListAllMocks() {
t.Logf("Testing alerts using mock files from Alertmanager %s", version)
mockAlerts(version)
+6
View File
@@ -54,6 +54,12 @@ grid:
critical: 1
warning: 2
info: 3
auto:
order:
- severity
- cluster
ignore:
- region
karma:
name: karma-demo
labels:
+13
View File
@@ -645,6 +645,9 @@ grid:
label: string
customValues:
labels: dict
auto:
ignore: list of strings
order: list of strings
```
- `sorting:order` - default sort order for alert grid, valid values are:
@@ -668,6 +671,13 @@ grid:
instead of original string values.
Note: this option is not available via environment variables, you can only set
it via the config file.
- `auto:ignore` - list of label names that should never be selected as multi-grid
source label when multi-grid is configured to `Automatic selection` in the UI
or when `ui:multiGridLabel` is set to `@auto`.
- `auto:order` - preferred order for selecting labels to be used as multi-grid
source label when multi-grid is configured to `Automatic selection` in the UI
or when `ui:multiGridLabel` is set to `@auto`. If a label name is not present
in this list labels with equal weight will be picked in alphabetic order.
Defaults:
@@ -679,6 +689,9 @@ grid:
label: alertname
customValues:
labels: {}
auto:
ignore: []
order: []
```
Example with sorting using `severity` label and value mappings for it:
+3
View File
@@ -72,6 +72,7 @@ func SetupFlags(f *pflag.FlagSet) {
"List of annotations to keep, all other annotations will be stripped")
f.StringSlice("annotations.strip", []string{}, "List of annotations to ignore")
f.StringSlice("annotations.actions", []string{}, "List of annotations that will be moved to the alert menu")
f.StringSlice("annotations.order", []string{}, "Preferred order of annotation names")
f.Bool("annotations.enableInsecureHTML", false, "Enable HTML strings in annotations to be parsed as HTML, enable at your own risk")
f.String("config.file", "", "Full path to the configuration file, 'karma.yaml' will be used if found in the current working directory")
@@ -94,6 +95,8 @@ func SetupFlags(f *pflag.FlagSet) {
f.String("grid.sorting.order", "startsAt", "Default sort order for alert grid")
f.Bool("grid.sorting.reverse", true, "Reverse sort order")
f.String("grid.sorting.label", "alertname", "Label name to use when sorting alert grid by label")
f.StringSlice("grid.auto.ignore", []string{}, "List of label names not allowed for automatic multi-grid")
f.StringSlice("grid.auto.order", []string{}, "Order of preference for selecting label names for automatic multi-grid")
f.Bool("log.config", false, "Log used configuration to log on startup")
f.String("log.level", "info",
+6
View File
@@ -85,6 +85,9 @@ grid:
label: alertname
customValues:
labels: {}
auto:
ignore: []
order: []
karma:
name: another karma
labels:
@@ -330,10 +333,13 @@ func TestDefaultConfig(t *testing.T) {
expectedConfig.Annotations.Keep = []string{}
expectedConfig.Annotations.Strip = []string{}
expectedConfig.Annotations.Actions = []string{}
expectedConfig.Annotations.Order = []string{}
expectedConfig.Labels.Keep = []string{}
expectedConfig.Labels.Strip = []string{}
expectedConfig.Labels.Color.Static = []string{}
expectedConfig.Labels.Color.Unique = []string{}
expectedConfig.Grid.Auto.Ignore = []string{}
expectedConfig.Grid.Auto.Order = []string{}
expectedConfig.Receivers.Keep = []string{}
expectedConfig.Receivers.Strip = []string{}
expectedConfig.SilenceForm.Strip.Labels = []string{}
+4
View File
@@ -123,6 +123,10 @@ type configSchema struct {
Labels map[string]map[string]string
} `yaml:"customValues" koanf:"customValues"`
}
Auto struct {
Ignore []string
Order []string
}
} `yaml:"grid"`
Karma struct {
Name string