mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-20 07:19:17 +01:00
app/vmselect/promql: properly handle (a op b) default N
if (a op b)
returns NaN series
The result should be a series with `N` values and `a op b` labels. Previously such series has been removed from the result.
This commit is contained in:
parent
ed10141ff8
commit
05672ffc32
@ -100,9 +100,8 @@ func newBinaryOpFunc(bf func(left, right float64, isBool bool) float64) binaryOp
|
|||||||
dstValues[j] = bf(a, b, isBool)
|
dstValues[j] = bf(a, b, isBool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Optimization: remove time series containing only NaNs.
|
// Do not remove time series containing only NaNs, since then the `(foo op bar) default N`
|
||||||
// This is quite common after applying filters like `q > 0`.
|
// won't work as expected if `(foo op bar)` results to NaN series.
|
||||||
dst = removeNaNs(dst)
|
|
||||||
return dst, nil
|
return dst, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1044,6 +1044,21 @@ func TestExecSuccess(t *testing.T) {
|
|||||||
resultExpected := []netstorage.Result{r}
|
resultExpected := []netstorage.Result{r}
|
||||||
f(q, resultExpected)
|
f(q, resultExpected)
|
||||||
})
|
})
|
||||||
|
t.Run("default_for_nan_series", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
q := `label_set(0, "foo", "bar")/0 default 7`
|
||||||
|
r := netstorage.Result{
|
||||||
|
MetricName: metricNameExpected,
|
||||||
|
Values: []float64{7, 7, 7, 7, 7, 7},
|
||||||
|
Timestamps: timestampsExpected,
|
||||||
|
}
|
||||||
|
r.MetricName.Tags = []storage.Tag{{
|
||||||
|
Key: []byte("foo"),
|
||||||
|
Value: []byte("bar"),
|
||||||
|
}}
|
||||||
|
resultExpected := []netstorage.Result{r}
|
||||||
|
f(q, resultExpected)
|
||||||
|
})
|
||||||
t.Run(`alias()`, func(t *testing.T) {
|
t.Run(`alias()`, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
q := `alias(time(), "foobar")`
|
q := `alias(time(), "foobar")`
|
||||||
@ -1691,10 +1706,12 @@ func TestExecSuccess(t *testing.T) {
|
|||||||
Values: []float64{1123.456, 1323.456, 1523.456, 1723.456, 1923.456, 2123.456},
|
Values: []float64{1123.456, 1323.456, 1523.456, 1723.456, 1923.456, 2123.456},
|
||||||
Timestamps: timestampsExpected,
|
Timestamps: timestampsExpected,
|
||||||
}
|
}
|
||||||
r2.MetricName.Tags = []storage.Tag{{
|
r2.MetricName.Tags = []storage.Tag{
|
||||||
Key: []byte("foo"),
|
{
|
||||||
Value: []byte("123.456"),
|
Key: []byte("foo"),
|
||||||
}}
|
Value: []byte("123.456"),
|
||||||
|
},
|
||||||
|
}
|
||||||
resultExpected := []netstorage.Result{r1, r2}
|
resultExpected := []netstorage.Result{r1, r2}
|
||||||
f(q, resultExpected)
|
f(q, resultExpected)
|
||||||
})
|
})
|
||||||
@ -6941,19 +6958,21 @@ func testResultsEqual(t *testing.T, result, resultExpected []netstorage.Result)
|
|||||||
func testMetricNamesEqual(t *testing.T, mn, mnExpected *storage.MetricName, pos int) {
|
func testMetricNamesEqual(t *testing.T, mn, mnExpected *storage.MetricName, pos int) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if string(mn.MetricGroup) != string(mnExpected.MetricGroup) {
|
if string(mn.MetricGroup) != string(mnExpected.MetricGroup) {
|
||||||
t.Fatalf(`unexpected MetricGroup at #%d; got %q; want %q`, pos, mn.MetricGroup, mnExpected.MetricGroup)
|
t.Fatalf(`unexpected MetricGroup at #%d; got %q; want %q; metricGot=%s, metricExpected=%s`,
|
||||||
|
pos, mn.MetricGroup, mnExpected.MetricGroup, mn.String(), mnExpected.String())
|
||||||
}
|
}
|
||||||
if len(mn.Tags) != len(mnExpected.Tags) {
|
if len(mn.Tags) != len(mnExpected.Tags) {
|
||||||
t.Fatalf(`unexpected tags count at #%d; got %d; want %d`, pos, len(mn.Tags), len(mnExpected.Tags))
|
t.Fatalf(`unexpected tags count at #%d; got %d; want %d; metricGot=%s, metricExpected=%s`, pos, len(mn.Tags), len(mnExpected.Tags), mn.String(), mnExpected.String())
|
||||||
}
|
}
|
||||||
for i := range mn.Tags {
|
for i := range mn.Tags {
|
||||||
tag := &mn.Tags[i]
|
tag := &mn.Tags[i]
|
||||||
tagExpected := &mnExpected.Tags[i]
|
tagExpected := &mnExpected.Tags[i]
|
||||||
if string(tag.Key) != string(tagExpected.Key) {
|
if string(tag.Key) != string(tagExpected.Key) {
|
||||||
t.Fatalf(`unexpected tag key at #%d,%d; got %q; want %q`, pos, i, tag.Key, tagExpected.Key)
|
t.Fatalf(`unexpected tag key at #%d,%d; got %q; want %q; metricGot=%s, metricExpected=%s`, pos, i, tag.Key, tagExpected.Key, mn.String(), mnExpected.String())
|
||||||
}
|
}
|
||||||
if string(tag.Value) != string(tagExpected.Value) {
|
if string(tag.Value) != string(tagExpected.Value) {
|
||||||
t.Fatalf(`unexpected tag value for key %q at #%d,%d; got %q; want %q`, tag.Key, pos, i, tag.Value, tagExpected.Value)
|
t.Fatalf(`unexpected tag value for key %q at #%d,%d; got %q; want %q; metricGot=%s, metricExpected=%s`,
|
||||||
|
tag.Key, pos, i, tag.Value, tagExpected.Value, mn.String(), mnExpected.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1823,8 +1823,15 @@ func newTransformFuncSort(isDesc bool) transformFunc {
|
|||||||
b := rvs[j].Values
|
b := rvs[j].Values
|
||||||
n := len(a) - 1
|
n := len(a) - 1
|
||||||
for n >= 0 {
|
for n >= 0 {
|
||||||
if !math.IsNaN(a[n]) && !math.IsNaN(b[n]) && a[n] != b[n] {
|
if !math.IsNaN(a[n]) {
|
||||||
break
|
if math.IsNaN(b[n]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a[n] != b[n] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if !math.IsNaN(b[n]) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ sort: 15
|
|||||||
|
|
||||||
* FEATURE: add `-search.maxSamplesPerSeries` command-line flag for limiting the number of raw samples a single query could process per each time series. This option can prevent from out of memory errors when a query processes tens of millions of raw samples per series. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1067).
|
* FEATURE: add `-search.maxSamplesPerSeries` command-line flag for limiting the number of raw samples a single query could process per each time series. This option can prevent from out of memory errors when a query processes tens of millions of raw samples per series. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1067).
|
||||||
|
|
||||||
|
* BUGFIX: return series with `a op b` labels and `N` values for `(a op b) default N` if `(a op b)` returns series with all NaN values. Previously such series were removed.
|
||||||
|
|
||||||
|
|
||||||
## [v1.63.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.63.0)
|
## [v1.63.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.63.0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user