diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 149741746..f85640d30 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -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). diff --git a/lib/promrelabel/config.go b/lib/promrelabel/config.go index 094904aa8..aefa94df4 100644 --- a/lib/promrelabel/config.go +++ b/lib/promrelabel/config.go @@ -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": diff --git a/lib/promrelabel/config_test.go b/lib/promrelabel/config_test.go index f460a2183..45dbf1e87 100644 --- a/lib/promrelabel/config_test.go +++ b/lib/promrelabel/config_test.go @@ -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) } } diff --git a/lib/promrelabel/relabel.go b/lib/promrelabel/relabel.go index 7950a6e6f..ccf2efc18 100644 --- a/lib/promrelabel/relabel.go +++ b/lib/promrelabel/relabel.go @@ -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 diff --git a/lib/promrelabel/relabel_test.go b/lib/promrelabel/relabel_test.go index bbc176681..abc4e12c8 100644 --- a/lib/promrelabel/relabel_test.go +++ b/lib/promrelabel/relabel_test.go @@ -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) { diff --git a/lib/promrelabel/testdata/relabel_configs_valid.yml b/lib/promrelabel/testdata/relabel_configs_valid.yml index 35bb6107f..5cd6b3102 100644 --- a/lib/promrelabel/testdata/relabel_configs_valid.yml +++ b/lib/promrelabel/testdata/relabel_configs_valid.yml @@ -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 \ No newline at end of file