promrelabel: add support of lowercase and uppercase relabeling actions (#2665)

* promrelabel: add support of `lowercase` and `uppercase` relabeling actions

https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2664
Signed-off-by: hagen1778 <roman@victoriametrics.com>

* lib/storage: make golangci-lint happy

Signed-off-by: hagen1778 <roman@victoriametrics.com>

Co-authored-by: Nikolay <nik@victoriametrics.com>
This commit is contained in:
Roman Khavronenko 2022-06-01 10:02:37 +02:00 committed by GitHub
parent b97ad42b6e
commit 2177089f94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 3 deletions

View file

@ -15,6 +15,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
## tip
* FEATURE: add support of `lowercase` and `uppercase` relabeling actions for compatibility reasons. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2664).
* FEATURE: support query tracing, which allows determining bottlenecks during query processing. See [these docs](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#query-tracing) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1403).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): remove dependency on Internet access in `http://vmagent:8429/targets` page. Previously the page layout was broken without Internet access. See [shis issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2594).
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): remove dependency on Internet access in [web API pages](https://docs.victoriametrics.com/vmalert.html#web). Previously the functionality and the layout of these pages was broken without Internet access. See [shis issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2594).

View file

@ -260,6 +260,13 @@ func parseRelabelConfig(rc *RelabelConfig) (*parsedRelabelConfig, error) {
}
sourceLabels = []string{"__name__"}
action = "drop"
case "uppercase", "lowercase":
if len(sourceLabels) == 0 {
return nil, fmt.Errorf("missing `source_labels` for `action=%s`", action)
}
if targetLabel == "" {
return nil, fmt.Errorf("missing `target_label` for `action=%s`", action)
}
case "labelmap":
case "labelmap_all":
case "labeldrop":

View file

@ -53,8 +53,8 @@ func TestLoadRelabelConfigsSuccess(t *testing.T) {
if err != nil {
t.Fatalf("cannot load relabel configs from %q: %s", path, err)
}
if n := pcs.Len(); n != 12 {
t.Fatalf("unexpected number of relabel configs loaded from %q; got %d; want %d", path, n, 12)
if n := pcs.Len(); n != 14 {
t.Fatalf("unexpected number of relabel configs loaded from %q; got %d; want %d", path, n, 14)
}
}

View file

@ -184,7 +184,7 @@ func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset
relabelBufPool.Put(bb)
return setLabelValue(labels, labelsOffset, nameStr, valueStr)
case "replace_all":
// Replace all the occurences of `regex` at `source_labels` joined with `separator` with the `replacement`
// Replace all the occurrences of `regex` at `source_labels` joined with `separator` with the `replacement`
// and store the result at `target_label`
bb := relabelBufPool.Get()
bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
@ -300,6 +300,20 @@ func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset
}
}
return dst
case "uppercase":
bb := relabelBufPool.Get()
bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
value := strings.ToUpper(string(bb.B))
relabelBufPool.Put(bb)
labels = setLabelValue(labels, labelsOffset, prc.TargetLabel, value)
return labels
case "lowercase":
bb := relabelBufPool.Get()
bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
value := strings.ToLower(string(bb.B))
relabelBufPool.Put(bb)
labels = setLabelValue(labels, labelsOffset, prc.TargetLabel, value)
return labels
default:
logger.Panicf("BUG: unknown `action`: %q", prc.Action)
return labels

View file

@ -1580,6 +1580,63 @@ func TestApplyRelabelConfigs(t *testing.T) {
},
})
})
t.Run("upper-lower-case", func(t *testing.T) {
f(`
- action: uppercase
source_labels: ["foo"]
target_label: foo
`, []prompbmarshal.Label{
{
Name: "foo",
Value: "bar",
},
}, true, []prompbmarshal.Label{
{
Name: "foo",
Value: "BAR",
},
})
f(`
- action: lowercase
source_labels: ["foo", "bar"]
target_label: baz
- action: labeldrop
regex: foo|bar
`, []prompbmarshal.Label{
{
Name: "foo",
Value: "BaR",
},
{
Name: "bar",
Value: "fOO",
},
}, true, []prompbmarshal.Label{
{
Name: "baz",
Value: "bar;foo",
},
})
})
f(`
- action: lowercase
source_labels: ["foo"]
target_label: baz
- action: uppercase
source_labels: ["bar"]
target_label: baz
`, []prompbmarshal.Label{
{
Name: "qux",
Value: "quux",
},
}, true, []prompbmarshal.Label{
{
Name: "qux",
Value: "quux",
},
})
}
func TestFinalizeLabels(t *testing.T) {

View file

@ -32,3 +32,10 @@
regex: [foo bar baz]
- action: drop_metrics
regex: "foo|bar|baz"
- source_labels: [foo, bar]
separator: "-"
target_label: __tmp_uppercase
action: uppercase
- source_labels: [__tmp_uppercase]
target_label: lower_aaa
action: lowercase