app/vmselect/promql: keep all labels for time series from any() call

This commit is contained in:
Aliaksandr Valialkin 2020-07-17 15:14:58 +03:00
parent 21cf6a1ec4
commit c64914a7e4
3 changed files with 23 additions and 4 deletions

View file

@ -43,7 +43,7 @@ var aggrFuncs = map[string]aggrFunc{
"bottomk_max": newAggrFuncRangeTopK(maxValue, true), "bottomk_max": newAggrFuncRangeTopK(maxValue, true),
"bottomk_avg": newAggrFuncRangeTopK(avgValue, true), "bottomk_avg": newAggrFuncRangeTopK(avgValue, true),
"bottomk_median": newAggrFuncRangeTopK(medianValue, true), "bottomk_median": newAggrFuncRangeTopK(medianValue, true),
"any": newAggrFunc(aggrFuncAny), "any": aggrFuncAny,
"outliersk": aggrFuncOutliersK, "outliersk": aggrFuncOutliersK,
} }
@ -77,6 +77,8 @@ func removeGroupTags(metricName *storage.MetricName, modifier *metricsql.Modifie
metricName.RemoveTagsOn(modifier.Args) metricName.RemoveTagsOn(modifier.Args)
case "without": case "without":
metricName.RemoveTagsIgnoring(modifier.Args) metricName.RemoveTagsIgnoring(modifier.Args)
// Reset metric group as Prometheus does on `aggr(...) without (...)` call.
metricName.ResetMetricGroup()
default: default:
logger.Panicf("BUG: unknown group modifier: %q", groupOp) logger.Panicf("BUG: unknown group modifier: %q", groupOp)
} }
@ -120,8 +122,20 @@ func aggrFuncExt(afe func(tss []*timeseries) []*timeseries, argOrig []*timeserie
return rvs, nil return rvs, nil
} }
func aggrFuncAny(tss []*timeseries) []*timeseries { func aggrFuncAny(afa *aggrFuncArg) ([]*timeseries, error) {
args := afa.args
if err := expectTransformArgsNum(args, 1); err != nil {
return nil, err
}
afe := func(tss []*timeseries) []*timeseries {
return tss[:1] return tss[:1]
}
limit := afa.ae.Limit
if limit > 1 {
// Only a single time series per group must be returned
limit = 1
}
return aggrFuncExt(afe, args[0], &afa.ae.Modifier, limit, true)
} }
func aggrFuncSum(tss []*timeseries) []*timeseries { func aggrFuncSum(tss []*timeseries) []*timeseries {

View file

@ -3835,6 +3835,10 @@ func TestExecSuccess(t *testing.T) {
Values: []float64{10, 10, 10, 10, 10, 10}, Values: []float64{10, 10, 10, 10, 10, 10},
Timestamps: timestampsExpected, Timestamps: timestampsExpected,
} }
r.MetricName.Tags = []storage.Tag{{
Key: []byte("foo"),
Value: []byte("bar"),
}}
resultExpected := []netstorage.Result{r} resultExpected := []netstorage.Result{r}
f(q, resultExpected) f(q, resultExpected)
}) })
@ -5627,6 +5631,7 @@ func TestExecError(t *testing.T) {
f(`sum()`) f(`sum()`)
f(`count_values()`) f(`count_values()`)
f(`quantile()`) f(`quantile()`)
f(`any()`)
f(`topk()`) f(`topk()`)
f(`topk_min()`) f(`topk_min()`)
f(`topk_max()`) f(`topk_max()`)

View file

@ -76,7 +76,7 @@ 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`.
- `any(q) by (x)` - returns any time series from `q` for each group in `x`. Note that `any()` removes all the labels except of those listed in `by (x)`. - `any(q) by (x)` - returns any time series from `q` for each group in `x`.
Use `limitk(1, q)` if you need retaining all the labels from `q`. Use `limitk(1, q)` if you need retaining all the labels from `q`.
- `keep_last_value(q)` - fills missing data (gaps) in `q` with the previous non-empty 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. - `keep_next_value(q)` - fills missing data (gaps) in `q` with the next non-empty value.