feat(backend): add labels:order config option

Fixes #3500
This commit is contained in:
Łukasz Mierzwa
2021-11-01 10:46:25 +00:00
committed by Łukasz Mierzwa
parent 0f34e13c53
commit d172c58a1a
17 changed files with 102 additions and 11 deletions

View File

@@ -13,6 +13,7 @@
- Loading user groups from HTTP headers, #3361 (@supertassu).
- Added `labels:keep_re`, `labels:strip_re` and `labels:valueOnly_re` config
options #3659 (@aalexk).
- `labels:order` config option to allow customising order of labels #3500.
### Changed

View File

@@ -38,6 +38,7 @@ env GRID_GROUPLIMIT=1
env KARMA_NAME=karma-demo
env LABELS_ORDER='job instance'
env LABELS_COLOR_STATIC=job
env LABELS_COLOR_UNIQUE='@receiver instance cluster'
env LABELS_KEEP='keep1 keep2'
@@ -45,6 +46,7 @@ env LABELS_KEEP_RE='keep_re1 keep_re2'
env LABELS_STRIP='strip1 strip2'
env LABELS_STRIP_RE='strip_re1 strip_re2'
env LABELS_VALUEONLY='value1 value2'
env LABELS_VALUEONLY_RE='foo.+'
env LISTEN_ADDRESS=127.0.0.1
env LISTEN_PORT=1234
@@ -169,6 +171,9 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma-demo"
level=info msg="labels:"
level=info msg=" order:"
level=info msg=" - job"
level=info msg=" - instance"
level=info msg=" keep:"
level=info msg=" - keep1"
level=info msg=" - keep2"
@@ -181,8 +186,11 @@ level=info msg=" - strip2"
level=info msg=" strip_re:"
level=info msg=" - strip_re1"
level=info msg=" - strip_re2"
level=info msg=" valueOnly: []"
level=info msg=" valueOnly_re: []"
level=info msg=" valueOnly:"
level=info msg=" - value1"
level=info msg=" - value2"
level=info msg=" valueOnly_re:"
level=info msg=" - foo.+"
level=info msg=" color:"
level=info msg=" custom: {}"
level=info msg=" static:"

View File

@@ -181,6 +181,9 @@ level=info msg=" uri: https://prod-$1.example.com"
level=info msg="karma:"
level=info msg=" name: karma-demo"
level=info msg="labels:"
level=info msg=" order:"
level=info msg=" - order1"
level=info msg=" - order2"
level=info msg=" keep:"
level=info msg=" - keep1"
level=info msg=" - keep2"
@@ -397,6 +400,9 @@ history:
karma:
name: karma-demo
labels:
order:
- order1
- order2
keep:
- keep1
- keep2

View File

@@ -82,6 +82,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -82,6 +82,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -82,6 +82,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -84,6 +84,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -82,6 +82,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -82,6 +82,7 @@ level=info msg=" rewrite: []"
level=info msg="karma:"
level=info msg=" name: karma"
level=info msg="labels:"
level=info msg=" order: []"
level=info msg=" keep: []"
level=info msg=" keep_re: []"
level=info msg=" strip: []"

View File

@@ -72,6 +72,9 @@ history:
karma:
name: karma-demo
labels:
order:
- instance
- job
color:
static:
- job

View File

@@ -859,6 +859,7 @@ labels:
- value: string
value_re: regex
color: string
order: list of strings
keep: list of strings
keep_re: list of regex
strip: list of strings
@@ -891,6 +892,9 @@ labels:
Note: this option is not available via environment variables, you can only set
it via the config file.
- `order` - custom order of label names. All labels listed here will
appear first in the order specified here. Remaining labels will be sorted
alphabetically and appended at the end.
- `keep` - list of allowed labels, if both `keep` and `keep_re` are empty all
labels are allowed.
- `keep_re` - list of Go compatible [regular expressions](https://golang.org/pkg/regexp/)

View File

@@ -85,6 +85,7 @@ func SetupFlags(f *pflag.FlagSet) {
f.StringSlice("filters.default", []string{}, "List of default filters")
f.StringSlice("labels.order", []string{}, "Preferred order of label names")
f.StringSlice("labels.color.static", []string{},
"List of label names that should have the same (but distinct) color")
f.StringSlice("labels.color.unique", []string{},
@@ -226,6 +227,8 @@ func readEnvVariables(k *koanf.Koanf) {
return "labels.keep_re"
case "LABELS_STRIP_RE":
return "labels.strip_re"
case "LABELS_VALUEONLY":
return "labels.valueOnly"
case "LABELS_VALUEONLY_RE":
return "labels.valueOnly_re"
case "SILENCEFORM_STRIP_LABELS":

View File

@@ -101,6 +101,7 @@ history:
karma:
name: another karma
labels:
order: []
keep:
- foo
- bar
@@ -376,6 +377,7 @@ func TestDefaultConfig(t *testing.T) {
expectedConfig.Annotations.Strip = []string{}
expectedConfig.Annotations.Actions = []string{}
expectedConfig.Annotations.Order = []string{}
expectedConfig.Labels.Order = []string{}
expectedConfig.Labels.Keep = []string{}
expectedConfig.Labels.KeepRegex = []string{}
expectedConfig.Labels.CompiledKeepRegex = []*regexp.Regexp{}

View File

@@ -148,6 +148,7 @@ type configSchema struct {
Name string
}
Labels struct {
Order []string
Keep []string
KeepRegex []string `yaml:"keep_re" koanf:"keep_re"`
CompiledKeepRegex []*regexp.Regexp `yaml:"-"`

View File

@@ -7,6 +7,7 @@ import (
"github.com/cnf/structhash"
"github.com/fvbommel/sortorder"
"github.com/prymitive/karma/internal/config"
)
// AlertStateUnprocessed means that Alertmanager notify didn't yet process it
@@ -62,6 +63,20 @@ func (ls Labels) Swap(i, j int) {
}
func (ls Labels) Less(i, j int) bool {
ai, aj := -1, -1
for index, name := range config.Config.Labels.Order {
if ls[i].Name == name {
ai = index
} else if ls[j].Name == name {
aj = index
}
if ai >= 0 && aj >= 0 {
return ai < aj
}
}
if ai != aj {
return aj < ai
}
if ls[i].Name == ls[j].Name {
return sortorder.NaturalLess(ls[i].Value, ls[j].Value)
}

View File

@@ -1,10 +1,12 @@
package models_test
import (
"fmt"
"sort"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/prymitive/karma/internal/config"
"github.com/prymitive/karma/internal/models"
)
@@ -41,13 +43,15 @@ func TestLabelsSet(t *testing.T) {
}
type sortLabelsTestCase struct {
in models.Labels
out models.Labels
order []string
in models.Labels
out models.Labels
}
func TestSortLabels(t *testing.T) {
testCases := []sortLabelsTestCase{
{
order: []string{},
in: models.Labels{
{Name: "foo", Value: "bar"},
},
@@ -56,6 +60,7 @@ func TestSortLabels(t *testing.T) {
},
},
{
order: []string{},
in: models.Labels{
{Name: "foo", Value: "bar"},
{Name: "bar", Value: "foo"},
@@ -66,6 +71,7 @@ func TestSortLabels(t *testing.T) {
},
},
{
order: []string{},
in: models.Labels{
{Name: "bar", Value: "foo"},
{Name: "foo", Value: "bar"},
@@ -76,6 +82,7 @@ func TestSortLabels(t *testing.T) {
},
},
{
order: []string{},
in: models.Labels{
{Name: "foo", Value: "foo"},
{Name: "bar", Value: "foo"},
@@ -88,6 +95,7 @@ func TestSortLabels(t *testing.T) {
},
},
{
order: []string{},
in: models.Labels{
{Name: "1", Value: "a12"},
{Name: "1", Value: "1"},
@@ -99,13 +107,46 @@ func TestSortLabels(t *testing.T) {
{Name: "1", Value: "a12"},
},
},
{
order: []string{"bar"},
in: models.Labels{
{Name: "baz", Value: "1"},
{Name: "bar", Value: "1"},
{Name: "foo", Value: "1"},
},
out: models.Labels{
{Name: "bar", Value: "1"},
{Name: "baz", Value: "1"},
{Name: "foo", Value: "1"},
},
},
{
order: []string{"foo", "bar"},
in: models.Labels{
{Name: "foo", Value: "a10"},
{Name: "bar", Value: "1"},
{Name: "foo", Value: "a3"},
},
out: models.Labels{
{Name: "foo", Value: "a3"},
{Name: "foo", Value: "a10"},
{Name: "bar", Value: "1"},
},
},
}
for _, testCase := range testCases {
sort.Sort(testCase.in)
if diff := cmp.Diff(testCase.in, testCase.out); diff != "" {
t.Errorf("Incorrectly sorted labels (-want +got):\n%s", diff)
break
}
defer func() {
config.Config.Labels.Order = []string{}
}()
for i, testCase := range testCases {
t.Run(fmt.Sprintf("[%d] order=%v", i, testCase.order), func(t *testing.T) {
config.Config.Labels.Order = testCase.order
sort.Sort(testCase.in)
if diff := cmp.Diff(testCase.in, testCase.out); diff != "" {
t.Errorf("Incorrectly sorted labels (-want +got):\n%s", diff)
t.FailNow()
}
})
}
}

View File

@@ -5,6 +5,7 @@ import (
"sort"
"strings"
"github.com/fvbommel/sortorder"
"github.com/prymitive/karma/internal/config"
"github.com/prymitive/karma/internal/slices"
)
@@ -50,7 +51,7 @@ func (a Annotations) Less(i, j int) bool {
return aj < ai
}
// If neither annotation was in c.C.A.Order, sort alphabetically.
return a[i].Name < a[j].Name
return sortorder.NaturalLess(a[i].Name, a[j].Name)
}
// AnnotationsFromMap will convert a map[string]string to a list of Annotation