relabel: add keepequal/dropequal relabel action

Signed-off-by: Julien Pivotto <roidelapluie@o11y.eu>
This commit is contained in:
Julien Pivotto 2022-11-10 14:17:47 +01:00
parent b1566f761e
commit 005ede70de
9 changed files with 163 additions and 7 deletions

View file

@ -217,26 +217,45 @@ var expectedConf = &Config{
Regex: relabel.MustNewRegexp("(.*)some-[regex]"),
Replacement: "foo-${1}",
Action: relabel.Replace,
}, {
},
{
SourceLabels: model.LabelNames{"abc"},
TargetLabel: "cde",
Separator: ";",
Regex: relabel.DefaultRelabelConfig.Regex,
Replacement: relabel.DefaultRelabelConfig.Replacement,
Action: relabel.Replace,
}, {
},
{
TargetLabel: "abc",
Separator: ";",
Regex: relabel.DefaultRelabelConfig.Regex,
Replacement: "static",
Action: relabel.Replace,
}, {
},
{
TargetLabel: "abc",
Separator: ";",
Regex: relabel.MustNewRegexp(""),
Replacement: "static",
Action: relabel.Replace,
},
{
SourceLabels: model.LabelNames{"foo"},
TargetLabel: "abc",
Action: relabel.KeepEqual,
Regex: relabel.DefaultRelabelConfig.Regex,
Replacement: relabel.DefaultRelabelConfig.Replacement,
Separator: relabel.DefaultRelabelConfig.Separator,
},
{
SourceLabels: model.LabelNames{"foo"},
TargetLabel: "abc",
Action: relabel.DropEqual,
Regex: relabel.DefaultRelabelConfig.Regex,
Replacement: relabel.DefaultRelabelConfig.Replacement,
Separator: relabel.DefaultRelabelConfig.Separator,
},
},
},
{
@ -1316,6 +1335,22 @@ var expectedErrors = []struct {
filename: "labeldrop5.bad.yml",
errMsg: "labeldrop action requires only 'regex', and no other fields",
},
{
filename: "dropequal.bad.yml",
errMsg: "relabel configuration for dropequal action requires 'target_label' value",
},
{
filename: "dropequal1.bad.yml",
errMsg: "dropequal action requires only 'source_labels' and `target_label`, and no other fields",
},
{
filename: "keepequal.bad.yml",
errMsg: "relabel configuration for keepequal action requires 'target_label' value",
},
{
filename: "keepequal1.bad.yml",
errMsg: "keepequal action requires only 'source_labels' and `target_label`, and no other fields",
},
{
filename: "labelmap.bad.yml",
errMsg: "\"l-$1\" is invalid 'replacement' for labelmap action",

View file

@ -87,6 +87,12 @@ scrape_configs:
- regex:
replacement: static
target_label: abc
- source_labels: [foo]
target_label: abc
action: keepequal
- source_labels: [foo]
target_label: abc
action: dropequal
authorization:
credentials_file: valid_token_file

5
config/testdata/dropequal.bad.yml vendored Normal file
View file

@ -0,0 +1,5 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- source_labels: [abcdef]
action: dropequal

7
config/testdata/dropequal1.bad.yml vendored Normal file
View file

@ -0,0 +1,7 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- source_labels: [abcdef]
action: dropequal
regex: foo
target_label: bar

5
config/testdata/keepequal.bad.yml vendored Normal file
View file

@ -0,0 +1,5 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- source_labels: [abcdef]
action: keepequal

7
config/testdata/keepequal1.bad.yml vendored Normal file
View file

@ -0,0 +1,7 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- source_labels: [abcdef]
action: keepequal
regex: foo
target_label: bar

View file

@ -2857,6 +2857,8 @@ anchored on both ends. To un-anchor the regex, use `.*<regex>.*`.
* `uppercase`: Maps the concatenated `source_labels` to their upper case.
* `keep`: Drop targets for which `regex` does not match the concatenated `source_labels`.
* `drop`: Drop targets for which `regex` matches the concatenated `source_labels`.
* `keepequal`: Drop targets for which the concatenated `source_labels` do not match `target_label`.
* `dropequal`: Drop targets for which the concatenated `source_labels` do match `target_label`.
* `hashmod`: Set `target_label` to the `modulus` of a hash of the concatenated `source_labels`.
* `labelmap`: Match `regex` against all source label names, not just those specified in `source_labels`. Then
copy the values of the matching labels to label names given by `replacement` with match

View file

@ -45,6 +45,10 @@ const (
Keep Action = "keep"
// Drop drops targets for which the input does match the regex.
Drop Action = "drop"
// KeepEqual drops targets for which the input does not match the target.
KeepEqual Action = "keepequal"
// Drop drops targets for which the input does match the target.
DropEqual Action = "dropequal"
// HashMod sets a label to the modulus of a hash of labels.
HashMod Action = "hashmod"
// LabelMap copies labels to other labelnames based on a regex.
@ -66,7 +70,7 @@ func (a *Action) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err
}
switch act := Action(strings.ToLower(s)); act {
case Replace, Keep, Drop, HashMod, LabelMap, LabelDrop, LabelKeep, Lowercase, Uppercase:
case Replace, Keep, Drop, HashMod, LabelMap, LabelDrop, LabelKeep, Lowercase, Uppercase, KeepEqual, DropEqual:
*a = act
return nil
}
@ -109,13 +113,13 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
if c.Modulus == 0 && c.Action == HashMod {
return fmt.Errorf("relabel configuration for hashmod requires non-zero modulus")
}
if (c.Action == Replace || c.Action == HashMod || c.Action == Lowercase || c.Action == Uppercase) && c.TargetLabel == "" {
if (c.Action == Replace || c.Action == HashMod || c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.TargetLabel == "" {
return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action)
}
if (c.Action == Replace || c.Action == Lowercase || c.Action == Uppercase) && !relabelTarget.MatchString(c.TargetLabel) {
if (c.Action == Replace || c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && !relabelTarget.MatchString(c.TargetLabel) {
return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
}
if (c.Action == Lowercase || c.Action == Uppercase) && c.Replacement != DefaultRelabelConfig.Replacement {
if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.Replacement != DefaultRelabelConfig.Replacement {
return fmt.Errorf("'replacement' can not be set for %s action", c.Action)
}
if c.Action == LabelMap && !relabelTarget.MatchString(c.Replacement) {
@ -125,6 +129,15 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
}
if c.Action == DropEqual || c.Action == KeepEqual {
if c.Regex != DefaultRelabelConfig.Regex ||
c.Modulus != DefaultRelabelConfig.Modulus ||
c.Separator != DefaultRelabelConfig.Separator ||
c.Replacement != DefaultRelabelConfig.Replacement {
return fmt.Errorf("%s action requires only 'source_labels' and `target_label`, and no other fields", c.Action)
}
}
if c.Action == LabelDrop || c.Action == LabelKeep {
if c.SourceLabels != nil ||
c.TargetLabel != DefaultRelabelConfig.TargetLabel ||
@ -225,6 +238,14 @@ func relabel(lset labels.Labels, cfg *Config, lb *labels.Builder) labels.Labels
if !cfg.Regex.MatchString(val) {
return nil
}
case DropEqual:
if lset.Get(cfg.TargetLabel) == val {
return nil
}
case KeepEqual:
if lset.Get(cfg.TargetLabel) != val {
return nil
}
case Replace:
indexes := cfg.Regex.FindStringSubmatchIndex(val)
// If there is no match no replacement must take place.

View file

@ -451,6 +451,74 @@ func TestRelabel(t *testing.T) {
"foo_uppercase": "BAR123FOO",
}),
},
{
input: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
relabel: []*Config{
{
SourceLabels: model.LabelNames{"__tmp_port"},
Action: KeepEqual,
TargetLabel: "__port1",
},
},
output: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
},
{
input: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
relabel: []*Config{
{
SourceLabels: model.LabelNames{"__tmp_port"},
Action: DropEqual,
TargetLabel: "__port1",
},
},
output: nil,
},
{
input: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
relabel: []*Config{
{
SourceLabels: model.LabelNames{"__tmp_port"},
Action: DropEqual,
TargetLabel: "__port2",
},
},
output: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
},
{
input: labels.FromMap(map[string]string{
"__tmp_port": "1234",
"__port1": "1234",
"__port2": "5678",
}),
relabel: []*Config{
{
SourceLabels: model.LabelNames{"__tmp_port"},
Action: KeepEqual,
TargetLabel: "__port2",
},
},
output: nil,
},
}
for _, test := range tests {