mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
app/vmselect/promql: add keep_next_value(q)
for filling gaps with the next non-empty value
This commit is contained in:
parent
bdbb463756
commit
a462355b2f
4 changed files with 50 additions and 6 deletions
|
@ -3904,6 +3904,22 @@ func TestExecSuccess(t *testing.T) {
|
||||||
resultExpected := []netstorage.Result{r1}
|
resultExpected := []netstorage.Result{r1}
|
||||||
f(q, resultExpected)
|
f(q, resultExpected)
|
||||||
})
|
})
|
||||||
|
t.Run(`keep_next_value()`, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
q := `keep_next_value(label_set(time() < 1300 default time() > 1700, "__name__", "foobar", "x", "y"))`
|
||||||
|
r1 := netstorage.Result{
|
||||||
|
MetricName: metricNameExpected,
|
||||||
|
Values: []float64{1000, 1200, 1800, 1800, 1800, 2000},
|
||||||
|
Timestamps: timestampsExpected,
|
||||||
|
}
|
||||||
|
r1.MetricName.MetricGroup = []byte("foobar")
|
||||||
|
r1.MetricName.Tags = []storage.Tag{{
|
||||||
|
Key: []byte("x"),
|
||||||
|
Value: []byte("y"),
|
||||||
|
}}
|
||||||
|
resultExpected := []netstorage.Result{r1}
|
||||||
|
f(q, resultExpected)
|
||||||
|
})
|
||||||
t.Run(`distinct_over_time([500s])`, func(t *testing.T) {
|
t.Run(`distinct_over_time([500s])`, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
q := `distinct_over_time((time() < 1700)[500s])`
|
q := `distinct_over_time((time() < 1700)[500s])`
|
||||||
|
@ -5342,6 +5358,7 @@ func TestExecError(t *testing.T) {
|
||||||
f(`median()`)
|
f(`median()`)
|
||||||
f(`median("foo", "bar")`)
|
f(`median("foo", "bar")`)
|
||||||
f(`keep_last_value()`)
|
f(`keep_last_value()`)
|
||||||
|
f(`keep_next_value()`)
|
||||||
f(`distinct_over_time()`)
|
f(`distinct_over_time()`)
|
||||||
f(`distinct()`)
|
f(`distinct()`)
|
||||||
f(`alias()`)
|
f(`alias()`)
|
||||||
|
|
|
@ -70,6 +70,7 @@ var transformFuncs = map[string]transformFunc{
|
||||||
"union": transformUnion,
|
"union": transformUnion,
|
||||||
"": transformUnion, // empty func is a synonim to union
|
"": transformUnion, // empty func is a synonim to union
|
||||||
"keep_last_value": transformKeepLastValue,
|
"keep_last_value": transformKeepLastValue,
|
||||||
|
"keep_next_value": transformKeepNextValue,
|
||||||
"start": newTransformFuncZeroArgs(transformStart),
|
"start": newTransformFuncZeroArgs(transformStart),
|
||||||
"end": newTransformFuncZeroArgs(transformEnd),
|
"end": newTransformFuncZeroArgs(transformEnd),
|
||||||
"step": newTransformFuncZeroArgs(transformStep),
|
"step": newTransformFuncZeroArgs(transformStep),
|
||||||
|
@ -724,13 +725,37 @@ func transformKeepLastValue(tfa *transformFuncArg) ([]*timeseries, error) {
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
prevValue := values[0]
|
lastValue := values[0]
|
||||||
for i, v := range values {
|
for i, v := range values {
|
||||||
if math.IsNaN(v) {
|
if !math.IsNaN(v) {
|
||||||
v = prevValue
|
lastValue = v
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
values[i] = v
|
values[i] = lastValue
|
||||||
prevValue = v
|
}
|
||||||
|
}
|
||||||
|
return rvs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func transformKeepNextValue(tfa *transformFuncArg) ([]*timeseries, error) {
|
||||||
|
args := tfa.args
|
||||||
|
if err := expectTransformArgsNum(args, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rvs := args[0]
|
||||||
|
for _, ts := range rvs {
|
||||||
|
values := ts.Values
|
||||||
|
if len(values) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nextValue := values[len(values)-1]
|
||||||
|
for i := len(values) - 1; i >= 0; i-- {
|
||||||
|
v := values[i]
|
||||||
|
if !math.IsNaN(v) {
|
||||||
|
nextValue = v
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
values[i] = nextValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rvs, nil
|
return rvs, nil
|
||||||
|
|
|
@ -70,7 +70,8 @@ This functionality can be tried at [an editable Grafana dashboard](http://play-g
|
||||||
- `median_over_time(m[d])` - calculates median values for `m` over `d` time window. Shorthand to `quantile_over_time(0.5, m[d])`.
|
- `median_over_time(m[d])` - calculates median values for `m` over `d` time window. Shorthand to `quantile_over_time(0.5, m[d])`.
|
||||||
- `median(q)` - median aggregate. Shorthand to `quantile(0.5, q)`.
|
- `median(q)` - median aggregate. Shorthand to `quantile(0.5, q)`.
|
||||||
- `limitk(k, q)` - limits the number of time series returned from `q` to `k`.
|
- `limitk(k, q)` - limits the number of time series returned from `q` to `k`.
|
||||||
- `keep_last_value(q)` - fills missing data (gaps) in `q` with the previous value.
|
- `keep_last_value(q)` - fills missing data (gaps) in `q` with the previous non-empty value.
|
||||||
|
- `keep_next_value(q)` - fills missing data (gaps) in `q` with the next non-empty value.
|
||||||
- `distinct_over_time(m[d])` - returns distinct number of values for `m` data points over `d` duration.
|
- `distinct_over_time(m[d])` - returns distinct number of values for `m` data points over `d` duration.
|
||||||
- `distinct(q)` - returns a time series with the number of unique values for each timestamp in `q`.
|
- `distinct(q)` - returns a time series with the number of unique values for each timestamp in `q`.
|
||||||
- `sum2_over_time(m[d])` - returns sum of squares for all the `m` values over `d` duration.
|
- `sum2_over_time(m[d])` - returns sum of squares for all the `m` values over `d` duration.
|
||||||
|
|
|
@ -49,6 +49,7 @@ var transformFuncs = map[string]bool{
|
||||||
"union": true,
|
"union": true,
|
||||||
"": true, // empty func is a synonim to union
|
"": true, // empty func is a synonim to union
|
||||||
"keep_last_value": true,
|
"keep_last_value": true,
|
||||||
|
"keep_next_value": true,
|
||||||
"start": true,
|
"start": true,
|
||||||
"end": true,
|
"end": true,
|
||||||
"step": true,
|
"step": true,
|
||||||
|
|
Loading…
Reference in a new issue