From 774f7ca1c1c6b57c99adfc17765f1657d0617677 Mon Sep 17 00:00:00 2001 From: nicbaz Date: Tue, 23 Jun 2020 22:50:33 +0200 Subject: [PATCH] vmselect: fix label_replace when mismatch (#579) As per documentation on `label_replace` function: "If the regular expression doesn't match then the timeseries is returned unchanged". Currently this behavior is not enforced, if a regexp on an existing tag doesn't match then the tag value is copied as-is in the destination tag. This fix first checks that the regular expression matches the source tag before applying anything. Given the current implementation, this fix also changes the behavior of the **MetricsQL** `label_transform` function which does not document this behavior at the moment. --- app/vmselect/promql/exec_test.go | 17 ++++++++++++++++- app/vmselect/promql/transform.go | 3 +++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index f6f8dfb01d..a7c015d9b0 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -1480,7 +1480,7 @@ func TestExecSuccess(t *testing.T) { resultExpected := []netstorage.Result{r} f(q, resultExpected) }) - t.Run(`label_replace(mismatch)`, func(t *testing.T) { + t.Run(`label_replace(nonexisting_src)`, func(t *testing.T) { t.Parallel() q := `label_replace(time(), "__name__", "x${1}y", "foo", ".+")` r := netstorage.Result{ @@ -1491,6 +1491,21 @@ func TestExecSuccess(t *testing.T) { resultExpected := []netstorage.Result{r} f(q, resultExpected) }) + t.Run(`label_replace(mismatch)`, func(t *testing.T) { + t.Parallel() + q := `label_replace(label_set(time(), "foo", "foobar"), "__name__", "x${1}y", "foo", "bar(.+)")` + r := netstorage.Result{ + MetricName: metricNameExpected, + Values: []float64{1000, 1200, 1400, 1600, 1800, 2000}, + Timestamps: timestampsExpected, + } + r.MetricName.Tags = []storage.Tag{{ + Key: []byte("foo"), + Value: []byte("foobar"), + }} + resultExpected := []netstorage.Result{r} + f(q, resultExpected) + }) t.Run(`label_replace(match)`, func(t *testing.T) { t.Parallel() q := `label_replace(time(), "__name__", "x${1}y", "foo", ".*")` diff --git a/app/vmselect/promql/transform.go b/app/vmselect/promql/transform.go index b08f9e8a42..1f0f858127 100644 --- a/app/vmselect/promql/transform.go +++ b/app/vmselect/promql/transform.go @@ -1219,6 +1219,9 @@ func labelReplace(tss []*timeseries, srcLabel string, r *regexp.Regexp, dstLabel mn := &ts.MetricName dstValue := getDstValue(mn, dstLabel) srcValue := mn.GetTagValue(srcLabel) + if !r.Match(srcValue) { + continue + } b := r.ReplaceAll(srcValue, replacementBytes) *dstValue = append((*dstValue)[:0], b...) if len(b) == 0 {