mirror of
https://github.com/prymitive/karma
synced 2026-05-09 03:36:44 +00:00
committed by
Łukasz Mierzwa
parent
0f34e13c53
commit
d172c58a1a
@@ -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
|
||||
|
||||
|
||||
@@ -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:"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -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: []"
|
||||
|
||||
@@ -72,6 +72,9 @@ history:
|
||||
karma:
|
||||
name: karma-demo
|
||||
labels:
|
||||
order:
|
||||
- instance
|
||||
- job
|
||||
color:
|
||||
static:
|
||||
- job
|
||||
|
||||
@@ -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/)
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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:"-"`
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user