From fda60b3d4d22e76ced2f3ba761c72552d3a5c6a9 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Fri, 30 Sep 2022 08:13:56 +0300 Subject: [PATCH] lib/promrelabel: properly parse regex with escaped $ at the end Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3131 Thanks to @dmitryk-dk for the initial fix at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3179 --- docs/CHANGELOG.md | 1 + lib/promrelabel/relabel_test.go | 9 +++++++++ lib/regexutil/regexutil.go | 2 +- lib/regexutil/regexutil_test.go | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8a11cdf62..c27f3d3fd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -36,6 +36,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup.html) and [vmrestore](https://docs.victoriametrics.com/vmrestore.html): retry GCS operations for up to 3 minutes on temporary failures. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3147). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly encode query params for aws signed requests, use `%20` instead of `+` as api requires. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3171). +* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly parse relabel config when regex ending with escaped `$`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3131). * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly calculate `rate_over_sum(m[d])` as `sum_over_time(m[d])/d`. Previously the `sum_over_time(m[d])` could be improperly divided by smaller than `d` time range. See [rate_over_sum() docs](https://docs.victoriametrics.com/MetricsQL.html#rate_over_sum) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3045). * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly calculate `increase(m[d])` over slow-changing counters with values smaller than 100. Previously [increase](https://docs.victoriametrics.com/MetricsQL.html#increase) could return unexpectedly big results in this case. See [the related issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/962) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3163). * BUGFIX: [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): properly calculate query results at `vmselect`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3067). The issue has been introduced in [v1.81.0](https://docs.victoriametrics.com/CHANGELOG.html#v1810). diff --git a/lib/promrelabel/relabel_test.go b/lib/promrelabel/relabel_test.go index bc4bb7c3f..f799e6777 100644 --- a/lib/promrelabel/relabel_test.go +++ b/lib/promrelabel/relabel_test.go @@ -682,6 +682,15 @@ func TestApplyRelabelConfigs(t *testing.T) { regex: "a(.+)" `, `qwe{foo="bar",baz="aaa"}`, true, `qwe{abc="qwe.bar.aa",baz="aaa",foo="bar"}`) }) + // Check $ at the end of regex - see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3131 + t.Run("replacement-with-$-at-the-end-of-regex", func(t *testing.T) { + f(` +- target_label: xyz + regex: "foo\\$$" + replacement: bar + source_labels: [xyz] +`, `metric{xyz="foo$",a="b"}`, true, `metric{a="b",xyz="bar"}`) + }) } func TestFinalizeLabels(t *testing.T) { diff --git a/lib/regexutil/regexutil.go b/lib/regexutil/regexutil.go index ca218098f..2a28be255 100644 --- a/lib/regexutil/regexutil.go +++ b/lib/regexutil/regexutil.go @@ -12,7 +12,7 @@ func RemoveStartEndAnchors(expr string) string { for strings.HasPrefix(expr, "^") { expr = expr[1:] } - for strings.HasSuffix(expr, "$") { + for strings.HasSuffix(expr, "$") && !strings.HasSuffix(expr, "\\$") { expr = expr[:len(expr)-1] } return expr diff --git a/lib/regexutil/regexutil_test.go b/lib/regexutil/regexutil_test.go index 8755ccc7f..e45781d25 100644 --- a/lib/regexutil/regexutil_test.go +++ b/lib/regexutil/regexutil_test.go @@ -110,3 +110,22 @@ func TestSimplify(t *testing.T) { // The transformed regexp mustn't match barx f("(foo|bar$)x*", "", "(?:foo|bar$)x*") } + +func TestRemoveStartEndAnchors(t *testing.T) { + f := func(s, resultExpected string) { + t.Helper() + result := RemoveStartEndAnchors(s) + if result != resultExpected { + t.Fatalf("unexpected result for RemoveStartEndAnchors(%q); got %q; want %q", s, result, resultExpected) + } + } + f("", "") + f("a", "a") + f("^^abc", "abc") + f("a^b$c", "a^b$c") + f("$$abc^", "$$abc^") + f("^abc|de$", "abc|de") + f("abc\\$", "abc\\$") + f("^abc\\$$$", "abc\\$") + f("^a\\$b\\$$", "a\\$b\\$") +}