diff --git a/Makefile b/Makefile index 5287947b..7ee68aa2 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,9 @@ check-docs: $(MDOX) format: $(GOIMPORTS) @echo ">> formatting go code" @gofmt -s -w $(FILES_TO_FMT) + @echo ">> formatting promql tests" + @go run scripts/testvet/main.go -json -fix ./... + @echo ">> formatting imports" @$(GOIMPORTS) -w $(FILES_TO_FMT) .PHONY:lint diff --git a/engine/bench_test.go b/engine/bench_test.go index 359532ea..1c725f5c 100644 --- a/engine/bench_test.go +++ b/engine/bench_test.go @@ -137,37 +137,37 @@ func BenchmarkRangeQuery(b *testing.B) { }{ { name: "vector selector", - query: "http_requests_total", + query: `http_requests_total`, storage: sixHourDataset, }, { name: "sum", - query: "sum(http_requests_total)", + query: `sum(http_requests_total)`, storage: sixHourDataset, }, { name: "sum by pod", - query: "sum by (pod) (http_requests_total)", + query: `sum by (pod) (http_requests_total)`, storage: sixHourDataset, }, { name: "topk", - query: "topk(2,http_requests_total)", + query: `topk(2, http_requests_total)`, storage: sixHourDataset, }, { name: "bottomk", - query: "bottomk(2,http_requests_total)", + query: `bottomk(2, http_requests_total)`, storage: sixHourDataset, }, { name: "rate", - query: "rate(http_requests_total[1m])", + query: `rate(http_requests_total[1m])`, storage: sixHourDataset, }, { name: "subquery", - query: "sum_over_time(rate(http_requests_total[1m])[10m:1m])", + query: `sum_over_time(rate(http_requests_total[1m])[10m:1m])`, storage: sixHourDataset, }, /* @@ -189,27 +189,27 @@ func BenchmarkRangeQuery(b *testing.B) { */ { name: "sum rate", - query: "sum(rate(http_requests_total[1m]))", + query: `sum(rate(http_requests_total[1m]))`, storage: sixHourDataset, }, { name: "sum by rate", - query: "sum by (pod) (rate(http_requests_total[1m]))", + query: `sum by (pod) (rate(http_requests_total[1m]))`, storage: sixHourDataset, }, { name: "quantile with variable parameter", - query: "quantile by (pod) (scalar(min(http_requests_total)), http_requests_total)", + query: `quantile by (pod) (scalar(min(http_requests_total)), http_requests_total)`, storage: sixHourDataset, }, { name: "binary operation with one to one", - query: `http_requests_total{container="c1"} / ignoring(container) http_responses_total`, + query: `http_requests_total{container="c1"} / ignoring (container) http_responses_total`, storage: sixHourDataset, }, { name: "binary operation with many to one", - query: `http_requests_total / on (pod) group_left http_responses_total`, + query: `http_requests_total / on (pod) group_left () http_responses_total`, storage: sixHourDataset, }, { @@ -229,17 +229,17 @@ func BenchmarkRangeQuery(b *testing.B) { }, { name: "positive offset vector", - query: "http_requests_total offset 5m", + query: `http_requests_total offset 5m`, storage: sixHourDataset, }, { name: "at modifier ", - query: "http_requests_total @ 600", + query: `http_requests_total @ 600.000`, storage: sixHourDataset, }, { name: "at modifier with positive offset vector", - query: "http_requests_total @ 600 offset 5m", + query: `http_requests_total @ 600.000 offset 5m`, storage: sixHourDataset, }, { @@ -354,43 +354,43 @@ func BenchmarkNativeHistograms(b *testing.B) { }{ { name: "selector", - query: "native_histogram_series", + query: `native_histogram_series`, }, { name: "sum", - query: "sum(native_histogram_series)", + query: `sum(native_histogram_series)`, }, { name: "rate", - query: "rate(native_histogram_series[1m])", + query: `rate(native_histogram_series[1m])`, }, { name: "sum rate", - query: "sum(rate(native_histogram_series[1m]))", + query: `sum(rate(native_histogram_series[1m]))`, }, { name: "histogram_sum", - query: "histogram_sum(native_histogram_series)", + query: `histogram_sum(native_histogram_series)`, }, { name: "histogram_count with rate", - query: "histogram_count(rate(native_histogram_series[1m]))", + query: `histogram_count(rate(native_histogram_series[1m]))`, }, { name: "histogram_count", - query: "histogram_count(native_histogram_series)", + query: `histogram_count(native_histogram_series)`, }, { name: "histogram_count with sum and rate", - query: "histogram_count(sum(rate(native_histogram_series[1m])))", + query: `histogram_count(sum(rate(native_histogram_series[1m])))`, }, { name: "histogram_quantile", - query: "histogram_quantile(0.9, sum(native_histogram_series))", + query: `histogram_quantile(0.9, sum(native_histogram_series))`, }, { name: "histogram scalar binop", - query: "sum(native_histogram_series * 60)", + query: `sum(native_histogram_series * 60)`, }, } @@ -449,51 +449,51 @@ func BenchmarkInstantQuery(b *testing.B) { }{ { name: "vector selector", - query: "http_requests_total", + query: `http_requests_total`, }, { name: "count", - query: "count(http_requests_total)", + query: `count(http_requests_total)`, }, { name: "count_values", - query: "count_values('val', http_requests_total)", + query: `count_values("val", http_requests_total)`, }, { name: "round", - query: "round(http_requests_total)", + query: `round(http_requests_total)`, }, { name: "round with argument", - query: "round(http_requests_total, 0.5)", + query: `round(http_requests_total, 0.5)`, }, { name: "avg", - query: "avg(http_requests_total)", + query: `avg(http_requests_total)`, }, { name: "sum", - query: "sum(http_requests_total)", + query: `sum(http_requests_total)`, }, { name: "sum by pod", - query: "sum by (pod) (http_requests_total)", + query: `sum by (pod) (http_requests_total)`, }, { name: "rate", - query: "rate(http_requests_total[1m])", + query: `rate(http_requests_total[1m])`, }, { name: "sum rate", - query: "sum(rate(http_requests_total[1m]))", + query: `sum(rate(http_requests_total[1m]))`, }, { name: "sum by rate", - query: "sum by (pod) (rate(http_requests_total[1m]))", + query: `sum by (pod) (rate(http_requests_total[1m]))`, }, { name: "binary operation with many to one", - query: `http_requests_total / on (pod) group_left http_responses_total`, + query: `http_requests_total / on (pod) group_left () http_responses_total`, }, { name: "unary negation", diff --git a/engine/distributed_test.go b/engine/distributed_test.go index 9b70dddb..19e2e244 100644 --- a/engine/distributed_test.go +++ b/engine/distributed_test.go @@ -238,9 +238,9 @@ func TestDistributedAggregations(t *testing.T) { rangeStart: time.Unix(7, 0), query: `max_over_time(min_over_time(sum(bar)[15s:15s])[15s:15s])`, }, - {name: "subquery over distributed binary expression", query: `max_over_time((bar/bar)[30s:15s])`}, + {name: "subquery over distributed binary expression", query: `max_over_time((bar / bar)[30s:15s])`}, {name: "timestamp", query: `timestamp(bar)`}, - {name: "timestamp - step invariant", query: `timestamp(bar @ 6000)`}, + {name: "timestamp - step invariant", query: `timestamp(bar @ 6000.000)`}, } lookbackDeltas := []time.Duration{0, 30 * time.Second, 5 * time.Minute} diff --git a/engine/engine_test.go b/engine/engine_test.go index f8a2a56e..9a368a81 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -129,131 +129,134 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "predict_linear fuzz", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 48.00+9.17x40 - http_requests_total{pod="nginx-2", route="/"} -108+173.00x40`, - query: `predict_linear( - http_requests_total{route="/"}[1h:1m] offset 1m, 60)`, + http_requests_total{pod="nginx-1", route="/"} 48.00+9.17x40 + http_requests_total{pod="nginx-2", route="/"} -108+173.00x40`, + query: `predict_linear(http_requests_total{route="/"}[1h:1m] offset 1m, 60)`, }, { name: "duplicate label fuzz", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 41.00+0.20x40 - http_requests_total{pod="nginx-2", route="/"} 51+21.71x40`, + http_requests_total{pod="nginx-1", route="/"} 41.00+0.20x40 + http_requests_total{pod="nginx-2", route="/"} 51+21.71x40`, query: ` -avg by (__name__) ( - (-group({__name__="http_requests_total"} @ 54.013) or {__name__="http_requests_total"} offset 1m32s) + (-group({__name__="http_requests_total"} @ 54.013) or {__name__="http_requests_total"} offset 1m32s) )`, }, { name: "timestamp fuzz 1", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 0.20+9.00x40 - http_requests_total{pod="nginx-2", route="/"} 6+60.00x40`, + http_requests_total{pod="nginx-1", route="/"} 0.20+9.00x40 + http_requests_total{pod="nginx-2", route="/"} 6+60.00x40`, query: `timestamp(last_over_time(http_requests_total{route="/"}[1h]))`, }, { name: "timestamp fuzz 2", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 8.00+9.17x40 - http_requests_total{pod="nginx-2", route="/"} -12+103.00x40`, - query: `timestamp( - http_requests_total{pod="nginx-1"} - >= bool - (http_requests_total < 2*http_requests_total) - )`, + http_requests_total{pod="nginx-1", route="/"} 8.00+9.17x40 + http_requests_total{pod="nginx-2", route="/"} -12+103.00x40`, + query: ` +timestamp( + http_requests_total{pod="nginx-1"} >= bool (http_requests_total < 2 * http_requests_total) +)`, }, { name: "timestamp with multiple parenthesis", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 8.00+9.17x40 - http_requests_total{pod="nginx-2", route="/"} -12+103.00x40`, + http_requests_total{pod="nginx-1", route="/"} 8.00+9.17x40 + http_requests_total{pod="nginx-2", route="/"} -12+103.00x40`, query: `timestamp((http_requests_total))`, }, { name: "subqueries in binary expression", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 1.00+0.20x40 - http_requests_total{pod="nginx-2", route="/"} -44+2.00x40`, + http_requests_total{pod="nginx-1", route="/"} 1.00+0.20x40 + http_requests_total{pod="nginx-2", route="/"} -44+2.00x40`, query: ` - absent_over_time(http_requests_total @end()[1h:1m]) - or - avg_over_time(http_requests_total @end()[1h:1m])`, + absent_over_time(http_requests_total @ end()[1h:1m]) +or + avg_over_time(http_requests_total @ end()[1h:1m])`, }, { name: "nested unary negation", - query: "1/(-(2*2))", + query: `1 / (-(2 * 2))`, }, { name: "stddev with large values", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 1e+181 - http_requests_total{pod="nginx-2", route="/"} 1e+80`, + http_requests_total{pod="nginx-1", route="/"} 1e+181 + http_requests_total{pod="nginx-2", route="/"} 1e+80`, query: `stddev(http_requests_total)`, }, { name: "stddev with NaN 1", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} NaN - http_requests_total{pod="nginx-2", route="/"} 1`, - query: "stddev by (route) (http_requests_total)", + http_requests_total{pod="nginx-1", route="/"} NaN + http_requests_total{pod="nginx-2", route="/"} 1`, + query: `stddev by (route) (http_requests_total)`, }, { name: "stddev with NaN 2", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} NaN - http_requests_total{pod="nginx-2", route="/"} 1`, - query: "stddev by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1", route="/"} NaN + http_requests_total{pod="nginx-2", route="/"} 1`, + query: `stddev by (pod) (http_requests_total)`, }, { name: "aggregate without", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1.1x1 - http_requests_total{pod="nginx-2"} 2+2.3x1`, + http_requests_total{pod="nginx-1"} 1+1.1x1 + http_requests_total{pod="nginx-2"} 2+2.3x1`, start: time.Unix(0, 0), end: time.Unix(60, 0), step: 30 * time.Second, - query: "avg without (pod) (http_requests_total)", + query: `avg without (pod) (http_requests_total)`, }, { name: "func with scalar arg that selects storage, checks whether same series handled correctly", load: `load 30s thanos_cache_redis_hits_total{name="caching-bucket",service="thanos-store"} 1+1x30`, - query: `clamp_min(thanos_cache_redis_hits_total, scalar(max(thanos_cache_redis_hits_total) by (service))) + clamp_min(thanos_cache_redis_hits_total, scalar(max(thanos_cache_redis_hits_total) by (service)))`, + query: ` + clamp_min(thanos_cache_redis_hits_total, scalar(max by (service) (thanos_cache_redis_hits_total))) ++ + clamp_min(thanos_cache_redis_hits_total, scalar(max by (service) (thanos_cache_redis_hits_total)))`, }, { name: "sum + rate divided by itself", load: `load 30s - thanos_cache_redis_hits_total{name="caching-bucket",service="thanos-store"} 1+1x30`, - query: `(sum(rate(thanos_cache_redis_hits_total{name="caching-bucket"}[2m])) by (service)) / - (sum(rate(thanos_cache_redis_hits_total{name="caching-bucket"}[2m])) by (service))`, + thanos_cache_redis_hits_total{name="caching-bucket",service="thanos-store"} 1+1x30`, + query: ` + (sum by (service) (rate(thanos_cache_redis_hits_total{name="caching-bucket"}[2m]))) +/ + (sum by (service) (rate(thanos_cache_redis_hits_total{name="caching-bucket"}[2m])))`, }, { name: "stddev_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "stddev_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `stddev_over_time(http_requests_total[30s])`, }, { name: "stdvar_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "stdvar_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `stdvar_over_time(http_requests_total[30s])`, }, { name: "quantile_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "quantile_over_time(0.9, http_requests_total[1m])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `quantile_over_time(0.9, http_requests_total[1m])`, }, { name: "quantile_over_time with subquery", load: `load 30s - http_requests_total{pod="nginx-1"} 41.00+0.20x40 - http_requests_total{pod="nginx-2"} 51+21.71x40`, + http_requests_total{pod="nginx-1"} 41.00+0.20x40 + http_requests_total{pod="nginx-2"} 51+21.71x40`, query: `quantile_over_time(0.5, http_requests_total{pod="nginx-1"}[5m:1m])`, start: start, end: end, @@ -261,9 +264,9 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "quantile_over_time with subquery and non-constant param", load: `load 30s - http_requests_total{pod="nginx-1"} 41.00+0.20x40 - http_requests_total{pod="nginx-2"} 51+21.71x40 - param_series 0+0.01x40`, + http_requests_total{pod="nginx-1"} 41.00+0.20x40 + http_requests_total{pod="nginx-2"} 51+21.71x40 + param_series 0+0.01x40`, query: `quantile_over_time(scalar(param_series), http_requests_total{pod="nginx-1"}[5m:1m])`, start: start, end: end, @@ -271,9 +274,9 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "predict_linear with subquery and non-constant param", load: `load 30s - http_requests_total{pod="nginx-1"} 41.00+0.20x40 - http_requests_total{pod="nginx-2"} 51+21.71x40 - param_series 1+1x40`, + http_requests_total{pod="nginx-1"} 41.00+0.20x40 + http_requests_total{pod="nginx-2"} 51+21.71x40 + param_series 1+1x40`, query: `predict_linear(http_requests_total{pod="nginx-1"}[5m:1m], scalar(param_series))`, start: start, end: end, @@ -281,8 +284,8 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "predict_linear with subquery and non-existing param series", load: `load 30s - http_requests_total{pod="nginx-1"} 41.00+0.20x40 - http_requests_total{pod="nginx-2"} 51+21.71x40`, + http_requests_total{pod="nginx-1"} 41.00+0.20x40 + http_requests_total{pod="nginx-2"} 51+21.71x40`, query: `predict_linear(http_requests_total{pod="nginx-1"}[5m:1m], scalar(non_existent))`, start: start, end: end, @@ -290,326 +293,325 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "changes", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "changes(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `changes(http_requests_total[30s])`, }, { name: "deriv", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "deriv(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `deriv(http_requests_total[30s])`, }, { name: "abs", load: `load 30s - http_requests_total{pod="nginx-1"} -5+1x15 - http_requests_total{pod="nginx-2"} -5+2x18`, - query: "abs(http_requests_total)", + http_requests_total{pod="nginx-1"} -5+1x15 + http_requests_total{pod="nginx-2"} -5+2x18`, + query: `abs(http_requests_total)`, }, { name: "ceil", load: `load 30s - http_requests_total{pod="nginx-1"} -5.5+1x15 - http_requests_total{pod="nginx-2"} -5.5+2x18`, - query: "ceil(http_requests_total)", + http_requests_total{pod="nginx-1"} -5.5+1x15 + http_requests_total{pod="nginx-2"} -5.5+2x18`, + query: `ceil(http_requests_total)`, }, { name: "exp", load: `load 30s - http_requests_total{pod="nginx-1"} -5.5+1x15 - http_requests_total{pod="nginx-2"} -5.5+2x18`, - query: "exp(http_requests_total)", + http_requests_total{pod="nginx-1"} -5.5+1x15 + http_requests_total{pod="nginx-2"} -5.5+2x18`, + query: `exp(http_requests_total)`, }, { name: "floor", load: `load 30s - http_requests_total{pod="nginx-1"} -5.5+1x15 - http_requests_total{pod="nginx-2"} -5.5+2x18`, - query: "floor(http_requests_total)", + http_requests_total{pod="nginx-1"} -5.5+1x15 + http_requests_total{pod="nginx-2"} -5.5+2x18`, + query: `floor(http_requests_total)`, }, { name: "floor with a filter", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 1 - http_requests_total{pod="nginx-2", route="/"} 2 -`, - query: `floor(http_requests_total{pod="nginx-2"})/http_requests_total`, + http_requests_total{pod="nginx-1", route="/"} 1 + http_requests_total{pod="nginx-2", route="/"} 2`, + query: `floor(http_requests_total{pod="nginx-2"}) / http_requests_total`, }, { name: "sqrt", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "sqrt(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `sqrt(http_requests_total)`, }, { name: "ln", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "ln(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `ln(http_requests_total)`, }, { name: "log2", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "log2(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `log2(http_requests_total)`, }, { name: "log10", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "log10(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `log10(http_requests_total)`, }, { name: "sin", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "sin(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `sin(http_requests_total)`, }, { name: "cos", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "cos(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `cos(http_requests_total)`, }, { name: "tan", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "tan(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `tan(http_requests_total)`, }, { name: "asin", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "asin(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `asin(http_requests_total)`, }, { name: "acos", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "acos(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `acos(http_requests_total)`, }, { name: "atan", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "atan(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `atan(http_requests_total)`, }, { name: "sinh", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "sinh(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `sinh(http_requests_total)`, }, { name: "cosh", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "cosh(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `cosh(http_requests_total)`, }, { name: "tanh", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "tanh(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `tanh(http_requests_total)`, }, { name: "asinh", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "asinh(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `asinh(http_requests_total)`, }, { name: "acosh", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "acosh(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `acosh(http_requests_total)`, }, { name: "atanh", load: `load 30s - http_requests_total{pod="nginx-1"} 0 - http_requests_total{pod="nginx-2"} 1`, - query: "atanh(http_requests_total)", + http_requests_total{pod="nginx-1"} 0 + http_requests_total{pod="nginx-2"} 1`, + query: `atanh(http_requests_total)`, }, { name: "rad", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "rad(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `rad(http_requests_total)`, }, { name: "deg", load: `load 30s - http_requests_total{pod="nginx-1"} 5.5+1x15 - http_requests_total{pod="nginx-2"} 5.5+2x18`, - query: "deg(http_requests_total)", + http_requests_total{pod="nginx-1"} 5.5+1x15 + http_requests_total{pod="nginx-2"} 5.5+2x18`, + query: `deg(http_requests_total)`, }, { name: "pi", load: ``, - query: "pi()", + query: `pi()`, }, { name: "sum", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum (http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum(http_requests_total)`, }, { name: "sum_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum_over_time(http_requests_total[30s])`, }, { name: "count", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count(http_requests_total)`, }, { name: "count_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count_over_time(http_requests_total[30s])`, }, { name: "average", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "avg(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `avg(http_requests_total)`, }, { name: "avg_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "avg_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `avg_over_time(http_requests_total[30s])`, }, { name: "abs", load: `load 30s - http_requests_total{pod="nginx-1"} -10+1x15 - http_requests_total{pod="nginx-2"} -10+2x18`, - query: "abs(http_requests_total)", + http_requests_total{pod="nginx-1"} -10+1x15 + http_requests_total{pod="nginx-2"} -10+2x18`, + query: `abs(http_requests_total)`, }, { name: "max", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "max(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `max(http_requests_total)`, }, { name: "max with only 1 sample", load: `load 30s - http_requests_total{pod="nginx-1"} -1 - http_requests_total{pod="nginx-2"} 1`, - query: "max(http_requests_total) by (pod)", + http_requests_total{pod="nginx-1"} -1 + http_requests_total{pod="nginx-2"} 1`, + query: `max by (pod) (http_requests_total)`, }, { name: "max_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "max_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `max_over_time(http_requests_total[30s])`, }, { name: "min", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "min(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `min(http_requests_total)`, }, { name: "min with only 1 sample", load: `load 30s - http_requests_total{pod="nginx-1"} -1 - http_requests_total{pod="nginx-2"} 1`, - query: "min(http_requests_total) by (pod)", + http_requests_total{pod="nginx-1"} -1 + http_requests_total{pod="nginx-2"} 1`, + query: `min by (pod) (http_requests_total)`, }, { name: "min_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "min_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `min_over_time(http_requests_total[30s])`, }, { name: "count_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count_over_time(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count_over_time(http_requests_total[30s])`, }, { name: "sum by pod", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-3"} 1+2x20 - http_requests_total{pod="nginx-4"} 1+2x50`, - query: "sum by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-3"} 1+2x20 + http_requests_total{pod="nginx-4"} 1+2x50`, + query: `sum by (pod) (http_requests_total)`, }, { name: "multi label grouping by", load: `load 30s - http_requests_total{pod="nginx-1", ns="a"} 1+1x15 - http_requests_total{pod="nginx-2", ns="a"} 1+1x15`, + http_requests_total{pod="nginx-1", ns="a"} 1+1x15 + http_requests_total{pod="nginx-2", ns="a"} 1+1x15`, query: `avg by (pod, ns) (avg_over_time(http_requests_total[2m]))`, }, { name: "multi label grouping without", load: `load 30s - http_requests_total{pod="nginx-1", ns="a"} 1+1x15 - http_requests_total{pod="nginx-2", ns="a"} 1+1x15`, + http_requests_total{pod="nginx-1", ns="a"} 1+1x15 + http_requests_total{pod="nginx-2", ns="a"} 1+1x15`, query: `avg without (pod, ns) (avg_over_time(http_requests_total[2m]))`, }, { name: "query in the future", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum by (pod) (http_requests_total)`, start: time.Unix(400, 0), end: time.Unix(3000, 0), }, { name: "count_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1 - http_requests_total{pod="nginx-1"} 1+1x30 - http_requests_total{pod="nginx-2"} 1+2x600`, + http_requests_total{pod="nginx-1"} 1 + http_requests_total{pod="nginx-1"} 1+1x30 + http_requests_total{pod="nginx-2"} 1+2x600`, query: `count_over_time(http_requests_total[10m])`, start: time.Unix(60, 0), end: time.Unix(600, 0), @@ -617,12 +619,12 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "rate", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "rate(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `rate(http_requests_total[1m])`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -630,19 +632,19 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "sum rate", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "sum(rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `sum(rate(http_requests_total[1m]))`, }, { name: "sum rate with stale series", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x40 - http_requests_total{pod="nginx-2"} 1+2x50 - http_requests_total{pod="nginx-4"} 1+2x50 - http_requests_total{pod="nginx-5"} 1+2x50 - http_requests_total{pod="nginx-6"} 1+2x50`, - query: "sum(rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x40 + http_requests_total{pod="nginx-2"} 1+2x50 + http_requests_total{pod="nginx-4"} 1+2x50 + http_requests_total{pod="nginx-5"} 1+2x50 + http_requests_total{pod="nginx-6"} 1+2x50`, + query: `sum(rate(http_requests_total[1m]))`, start: time.Unix(421, 0), end: time.Unix(3230, 0), step: 28 * time.Second, @@ -650,12 +652,12 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "delta", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "delta(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `delta(http_requests_total[1m])`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -663,12 +665,12 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "increase", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "increase(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `increase(http_requests_total[1m])`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -676,12 +678,12 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "irate", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "irate(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `irate(http_requests_total[1m])`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -689,12 +691,12 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "idelta", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "idelta(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `idelta(http_requests_total[1m])`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -702,40 +704,40 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "number literal", load: "", - query: "34", + query: `34`, }, { name: "vector", load: "", - query: "vector(24)", + query: `vector(24)`, }, { name: "binary operation atan2", load: `load 30s - foo{} 10 - bar{} 2`, - query: "foo atan2 bar", + foo{} 10 + bar{} 2`, + query: `foo atan2 bar`, }, { name: "binary operation atan2 with NaN", load: `load 30s - foo{} 10 - bar{} NaN`, - query: "foo atan2 bar", + foo{} 10 + bar{} NaN`, + query: `foo atan2 bar`, }, { name: "binary operation with one-to-one matching", load: `load 30s - foo{method="get", code="500"} 1+1x1 - foo{method="get", code="404"} 2+1x2 - foo{method="put", code="501"} 3+1x3 - foo{method="put", code="500"} 1+1x4 - foo{method="post", code="500"} 4+1x4 - foo{method="post", code="404"} 5+1x5 - bar{method="get"} 1+1x1 - bar{method="del"} 2+1x2 - bar{method="post"} 3+1x3`, - query: `foo{code="500"} + ignoring(code) bar`, + foo{method="get", code="500"} 1+1x1 + foo{method="get", code="404"} 2+1x2 + foo{method="put", code="501"} 3+1x3 + foo{method="put", code="500"} 1+1x4 + foo{method="post", code="500"} 4+1x4 + foo{method="post", code="404"} 5+1x5 + bar{method="get"} 1+1x1 + bar{method="del"} 2+1x2 + bar{method="post"} 3+1x3`, + query: `foo{code="500"} + ignoring (code) bar`, start: time.Unix(0, 0), end: time.Unix(600, 0), }, @@ -743,15 +745,15 @@ func TestQueriesAgainstOldEngine(t *testing.T) { // Example from https://prometheus.io/docs/prometheus/latest/querying/operators/#many-to-one-and-one-to-many-vector-matches name: "binary operation with group_left", load: `load 30s - foo{method="get", code="500", path="/"} 1+1.1x30 - foo{method="get", code="404", path="/"} 1+2.2x20 - foo{method="put", code="501", path="/"} 4+3.4x60 - foo{method="post", code="500", path="/"} 1+5.1x40 - foo{method="post", code="404", path="/"} 2+3.7x40 - bar{method="get", path="/a"} 3+7.4x10 - bar{method="del", path="/b"} 8+6.1x30 - bar{method="post", path="/c"} 1+2.1x40`, - query: `foo * ignoring(path, code) group_left bar`, + foo{method="get", code="500", path="/"} 1+1.1x30 + foo{method="get", code="404", path="/"} 1+2.2x20 + foo{method="put", code="501", path="/"} 4+3.4x60 + foo{method="post", code="500", path="/"} 1+5.1x40 + foo{method="post", code="404", path="/"} 2+3.7x40 + bar{method="get", path="/a"} 3+7.4x10 + bar{method="del", path="/b"} 8+6.1x30 + bar{method="post", path="/c"} 1+2.1x40`, + query: `foo * ignoring (path, code) group_left () bar`, start: time.Unix(0, 0), end: time.Unix(600, 0), }, @@ -759,15 +761,15 @@ func TestQueriesAgainstOldEngine(t *testing.T) { // Example from https://prometheus.io/docs/prometheus/latest/querying/operators/#many-to-one-and-one-to-many-vector-matches name: "binary operation with group_right", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20 - foo{method="put", code="501"} 4+3.4x60 - foo{method="post", code="500"} 1+5.1x40 - foo{method="post", code="404"} 2+3.7x40 - bar{method="get", path="/a"} 3+7.4x10 - bar{method="del", path="/b"} 8+6.1x30 - bar{method="post", path="/c"} 1+2.1x40`, - query: `bar * ignoring(code, path) group_right foo`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20 + foo{method="put", code="501"} 4+3.4x60 + foo{method="post", code="500"} 1+5.1x40 + foo{method="post", code="404"} 2+3.7x40 + bar{method="get", path="/a"} 3+7.4x10 + bar{method="del", path="/b"} 8+6.1x30 + bar{method="post", path="/c"} 1+2.1x40`, + query: `bar * ignoring (code, path) group_right () foo`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -775,208 +777,208 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "binary operation with group_left and included labels", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20 - foo{method="put", code="501"} 4+3.4x60 - foo{method="post", code="500"} 1+5.1x40 - foo{method="post", code="404"} 2+3.7x40 - bar{method="get", path="/a"} 3+7.4x10 - bar{method="del", path="/b"} 8+6.1x30 - bar{method="post", path="/c"} 1+2.1x40`, - query: `foo * ignoring(code, path) group_left(path) bar`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20 + foo{method="put", code="501"} 4+3.4x60 + foo{method="post", code="500"} 1+5.1x40 + foo{method="post", code="404"} 2+3.7x40 + bar{method="get", path="/a"} 3+7.4x10 + bar{method="del", path="/b"} 8+6.1x30 + bar{method="post", path="/c"} 1+2.1x40`, + query: `foo * ignoring (code, path) group_left (path) bar`, start: time.Unix(0, 0), end: time.Unix(600, 0), }, { name: "binary operation with group_right and included labels", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20 - foo{method="put", code="501"} 4+3.4x60 - foo{method="post", code="500"} 1+5.1x40 - foo{method="post", code="404"} 2+3.7x40 - bar{method="get", path="/a"} 3+7.4x10 - bar{method="del", path="/b"} 8+6.1x30 - bar{method="post", path="/c"} 1+2.1x40`, - query: `bar * ignoring(code, path) group_right(path) foo`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20 + foo{method="put", code="501"} 4+3.4x60 + foo{method="post", code="500"} 1+5.1x40 + foo{method="post", code="404"} 2+3.7x40 + bar{method="get", path="/a"} 3+7.4x10 + bar{method="del", path="/b"} 8+6.1x30 + bar{method="post", path="/c"} 1+2.1x40`, + query: `bar * ignoring (code, path) group_right (path) foo`, start: time.Unix(0, 0), end: time.Unix(600, 0), }, { name: "binary operation with vector and scalar on the right", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `sum(foo) * 2`, }, { name: "binary operation with vector and scalar on the left", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `2 * sum(foo)`, }, { name: "complex binary operation", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `1 - (100 * sum(foo{method="get"}) / sum(foo))`, }, { name: "binary operation with many-to-many matching", load: `load 30s - foo{code="200", method="get"} 1+1x20 - foo{code="200", method="post"} 1+1x20 - bar{code="200", method="get"} 1+1x20 - bar{code="200", method="post"} 1+1x20`, - query: `foo + on(code) bar`, + foo{code="200", method="get"} 1+1x20 + foo{code="200", method="post"} 1+1x20 + bar{code="200", method="get"} 1+1x20 + bar{code="200", method="post"} 1+1x20`, + query: `foo + on (code) bar`, }, { name: "binary operation with many-to-many matching lhs high card", load: `load 30s - foo{code="200", method="get"} 1+1x20 - foo{code="200", method="post"} 1+1x20 - bar{code="200", method="get"} 1+1x20 - bar{code="200", method="post"} 1+1x20`, - query: `foo + on(code) group_left bar`, + foo{code="200", method="get"} 1+1x20 + foo{code="200", method="post"} 1+1x20 + bar{code="200", method="get"} 1+1x20 + bar{code="200", method="post"} 1+1x20`, + query: `foo + on (code) group_left () bar`, }, { name: "binary operation with many-to-many matching rhs high card", load: `load 30s - foo{code="200", method="get"} 1+1x20 - foo{code="200", method="post"} 1+1x20 - bar{code="200", method="get"} 1+1x20 - bar{code="200", method="post"} 1+1x20`, - query: `foo + on(code) group_right bar`, + foo{code="200", method="get"} 1+1x20 + foo{code="200", method="post"} 1+1x20 + bar{code="200", method="get"} 1+1x20 + bar{code="200", method="post"} 1+1x20`, + query: `foo + on (code) group_right () bar`, }, { name: "vector binary op ==", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) == sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) == sum by (method) (bar)`, }, { name: "vector binary op !=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) != sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) != sum by (method) (bar)`, }, { name: "vector binary op >", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) > sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) > sum by (method) (bar)`, }, { name: "vector binary op with name <", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="500"} 1+1.1x30`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="500"} 1+1.1x30`, query: `foo < bar`, }, { name: "vector binary op with name < scalar", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="500"} 1+1.1x30`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="500"} 1+1.1x30`, query: `foo < 10`, }, { name: "vector binary op with name < scalar and bool modifier", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="500"} 1+1.1x30`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="500"} 1+1.1x30`, query: `foo < bool 10`, }, { name: "vector binary op > scalar", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) > 10`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) > 10`, }, { name: "vector binary op > scalar and bool modifier", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) > bool 10`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) > bool 10`, }, { name: "scalar < vector binary op", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `10 < sum(foo) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `10 < sum by (method) (foo)`, }, { name: "vector binary op <", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) < sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) < sum by (method) (bar)`, }, { name: "vector binary op >=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) >= sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) >= sum by (method) (bar)`, }, { name: "vector binary op <=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) <= sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) <= sum by (method) (bar)`, }, { name: "vector binary op ^", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) ^ sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) ^ sum by (method) (bar)`, }, { name: "vector binary op %", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) % sum(bar) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) % sum by (method) (bar)`, }, { name: "vector/vector binary op", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "(1 + rate(http_requests_total[30s])) > bool rate(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `(1 + rate(http_requests_total[30s])) > bool rate(http_requests_total[30s])`, }, { name: "vector/scalar binary op with a complicated expression on LHS", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "rate(http_requests_total[30s]) > bool 0", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `rate(http_requests_total[30s]) > bool 0`, }, { name: "vector/scalar binary op with a complicated expression on RHS", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "0 < bool rate(http_requests_total[30s])", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `0 < bool rate(http_requests_total[30s])`, }, { name: "scalar binary op == true", @@ -1031,92 +1033,90 @@ func TestQueriesAgainstOldEngine(t *testing.T) { { name: "empty series", load: "", - query: "http_requests_total", + query: `http_requests_total`, }, { name: "time function", load: "", - query: "time()", + query: `time()`, }, { name: "time function in binary expression", load: "", - query: "time() - 10", + query: `time() - 10`, }, { name: "empty series with func", load: "", - query: "sum(http_requests_total)", + query: `sum(http_requests_total)`, }, { name: "empty result", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total{pod="nginx-3"}`, }, { name: "last_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `last_over_time(http_requests_total[30s])`, }, { name: "group", load: `load 30s - http_requests_total{pod="nginx-1"} 2+1x15 - http_requests_total{pod="nginx-2"} 2+2x18`, + http_requests_total{pod="nginx-1"} 2+1x15 + http_requests_total{pod="nginx-2"} 2+2x18`, query: `group(http_requests_total)`, }, { name: "group by ", load: `load 30s - http_requests_total{pod="nginx-1"} 2+1x15 - http_requests_total{pod="nginx-2"} 2+2x18`, + http_requests_total{pod="nginx-1"} 2+1x15 + http_requests_total{pod="nginx-2"} 2+2x18`, query: `group by (pod) (http_requests_total)`, }, { // Issue https://github.com/thanos-io/promql-engine/issues/326. name: "group by with NaN values", - load: ` -load 30s - http_requests_total{pod="nginx-1", route="/"} 1.00+1.00x4 - http_requests_total{pod="nginx-2", route="/"} 1+2.00x4`, + load: `load 30s + http_requests_total{pod="nginx-1", route="/"} 1.00+1.00x4 + http_requests_total{pod="nginx-2", route="/"} 1+2.00x4`, query: `group by (pod, route) (atanh(-{__name__="http_requests_total"} offset -3m4s))`, }, { name: "resets", load: `load 30s - http_requests_total{pod="nginx-1"} 100-1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 100-1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `resets(http_requests_total[5m])`, }, { name: "present_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `present_over_time(http_requests_total[30s])`, }, { name: "complex binary with aggregation", load: `load 30s - grpc_server_handled_total{pod="nginx-1", grpc_method="Series", grpc_code="105"} 1+1x15 - grpc_server_handled_total{pod="nginx-2", grpc_method="Series", grpc_code="105"} 1+1x15 - grpc_server_handled_total{pod="nginx-3", grpc_method="Series", grpc_code="105"} 1+1x15 - prometheus_tsdb_head_samples_appended_total{pod="nginx-1", tenant="tenant-1"} 1+2x18 - prometheus_tsdb_head_samples_appended_total{pod="nginx-2", tenant="tenant-2"} 1+2x18 - prometheus_tsdb_head_samples_appended_total{pod="nginx-3", tenant="tenant-3"} 1+2x18`, + grpc_server_handled_total{pod="nginx-1", grpc_method="Series", grpc_code="105"} 1+1x15 + grpc_server_handled_total{pod="nginx-2", grpc_method="Series", grpc_code="105"} 1+1x15 + grpc_server_handled_total{pod="nginx-3", grpc_method="Series", grpc_code="105"} 1+1x15 + prometheus_tsdb_head_samples_appended_total{pod="nginx-1", tenant="tenant-1"} 1+2x18 + prometheus_tsdb_head_samples_appended_total{pod="nginx-2", tenant="tenant-2"} 1+2x18 + prometheus_tsdb_head_samples_appended_total{pod="nginx-3", tenant="tenant-3"} 1+2x18`, query: ` - sum by (grpc_method, grpc_code) ( - sum by (pod, grpc_method, grpc_code) ( - rate(grpc_server_handled_total{grpc_method="Series", pod=~".+"}[1m]) - ) - + on (pod) group_left() max by (pod) ( - prometheus_tsdb_head_samples_appended_total{pod=~".+"} - ) - )`, +sum by (grpc_method, grpc_code) ( + sum by (pod, grpc_method, grpc_code) ( + rate(grpc_server_handled_total{grpc_method="Series",pod=~".+"}[1m]) + ) + + on (pod) group_left () + max by (pod) (prometheus_tsdb_head_samples_appended_total{pod=~".+"}) +)`, }, { name: "unary sub operation for scalar", @@ -1126,22 +1126,22 @@ load 30s { name: "unary sub operation for vector", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `-http_requests_total`, }, { name: "unary add operation for vector", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `+http_requests_total`, }, { name: "vector positive offset", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total offset 30s`, start: time.Unix(600, 0), end: time.Unix(1200, 0), @@ -1149,8 +1149,8 @@ load 30s { name: "vector negative offset", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total offset -30s`, start: time.Unix(600, 0), end: time.Unix(1200, 0), @@ -1158,8 +1158,8 @@ load 30s { name: "matrix negative offset with sum_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x25 - http_requests_total{pod="nginx-2"} 1+2x28`, + http_requests_total{pod="nginx-1"} 1+1x25 + http_requests_total{pod="nginx-2"} 1+2x28`, query: `sum_over_time(http_requests_total[5m] offset 5m)`, start: time.Unix(600, 0), end: time.Unix(6000, 0), @@ -1167,8 +1167,8 @@ load 30s { name: "matrix negative offset with count_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `count_over_time(http_requests_total[5m] offset -2m)`, start: time.Unix(600, 0), end: time.Unix(6000, 0), @@ -1176,464 +1176,467 @@ load 30s { name: "@ vector time 10s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 10", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 10.000`, }, { name: "@ vector time 120s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 120", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 120.000`, }, { name: "@ vector time 360s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 360", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 360.000`, }, { name: "@ vector start", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ start()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ start()`, }, { name: "@ vector end", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ end()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ end()`, }, { name: "count_over_time @ start", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count_over_time(http_requests_total[5m] @ start())", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count_over_time(http_requests_total[5m] @ start())`, }, { name: "sum_over_time @ end", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum_over_time(http_requests_total[5m] @ start())", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum_over_time(http_requests_total[5m] @ start())`, }, { name: "avg_over_time @ 180s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "avg_over_time(http_requests_total[4m] @ 180)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `avg_over_time(http_requests_total[4m] @ 180.000)`, }, { name: "@ vector 240s offset 2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 240 offset 2m", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 240.000 offset 2m`, }, { name: "avg_over_time @ 120s offset -2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 120 offset -2m", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 120.000 offset -2m`, }, { name: "sum_over_time @ 180s offset 2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum_over_time(http_requests_total[5m] @ 180 offset 2m)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum_over_time(http_requests_total[5m] @ 180.000 offset 2m)`, }, { name: "binop with @ end() modifier inside query range", load: `load 30s - http_requests_total 2+3x100 - http_responses_total 2+4x100`, - query: "max(http_requests_total @ end()) / max(http_responses_total)", + http_requests_total 2+3x100 + http_responses_total 2+4x100`, + query: `max(http_requests_total @ end()) / max(http_responses_total)`, end: time.Unix(600, 0), }, { name: "binop with @ end() modifier outside of query range", load: `load 30s - http_requests_total 2+3x100 - http_responses_total 2+4x100`, - query: "max(http_requests_total @ end()) / max(http_responses_total)", + http_requests_total 2+3x100 + http_responses_total 2+4x100`, + query: `max(http_requests_total @ end()) / max(http_responses_total)`, end: time.Unix(60000, 0), }, { name: "days_in_month with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "days_in_month(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `days_in_month(http_requests_total)`, }, { name: "days_in_month without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "days_in_month()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `days_in_month()`, }, { name: "day_of_month with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "day_of_month(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `day_of_month(http_requests_total)`, }, { name: "day_of_month without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "day_of_month()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `day_of_month()`, }, { name: "day_of_week with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "days_in_month(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `days_in_month(http_requests_total)`, }, { name: "day_of_week without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "days_in_month()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `days_in_month()`, }, { name: "day_of_year with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "day_of_year(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `day_of_year(http_requests_total)`, }, { name: "day_of_year without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "day_of_year()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `day_of_year()`, }, { name: "hour with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "hour(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `hour(http_requests_total)`, }, { name: "hour without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "hour()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `hour()`, }, { name: "minute with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "minute(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `minute(http_requests_total)`, }, { name: "minute without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "minute()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `minute()`, }, { name: "month with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "month(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `month(http_requests_total)`, }, { name: "month without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "month()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `month()`, }, { name: "year with input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "year(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `year(http_requests_total)`, }, { name: "year without input", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "year()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `year()`, }, { name: "selector merge", load: `load 30s - http_requests_total{pod="nginx-1", ns="nginx"} 1+1x15 - http_requests_total{pod="nginx-2", ns="nginx"} 1+2x18 - http_requests_total{pod="nginx-3", ns="nginx"} 1+2x21`, - query: `http_requests_total{pod=~"nginx-1", ns="nginx"} / on() group_left() sum(http_requests_total{ns="nginx"})`, + http_requests_total{pod="nginx-1", ns="nginx"} 1+1x15 + http_requests_total{pod="nginx-2", ns="nginx"} 1+2x18 + http_requests_total{pod="nginx-3", ns="nginx"} 1+2x21`, + query: ` + http_requests_total{ns="nginx",pod=~"nginx-1"} +/ on () group_left () + sum(http_requests_total{ns="nginx"})`, }, { name: "selector merge with different ranges", load: `load 30s - http_requests_total{pod="nginx-1", ns="nginx"} 2+2x16 - http_requests_total{pod="nginx-2", ns="nginx"} 2+4x18 - http_requests_total{pod="nginx-3", ns="nginx"} 2+6x20`, + http_requests_total{pod="nginx-1", ns="nginx"} 2+2x16 + http_requests_total{pod="nginx-2", ns="nginx"} 2+4x18 + http_requests_total{pod="nginx-3", ns="nginx"} 2+6x20`, query: ` - rate(http_requests_total{pod=~"nginx-1", ns="nginx"}[2m]) - + on() group_left() - sum(http_requests_total{ns="nginx"})`, + rate(http_requests_total{ns="nginx",pod=~"nginx-1"}[2m]) ++ on () group_left () + sum(http_requests_total{ns="nginx"})`, }, { name: "binop with positive matcher using regex, only one side has data", load: `load 30s - metric{} 1+2x5 - metric{} 1+2x20`, - query: `sum(rate(metric{err=~".+"}[5m])) / sum(rate(metric{}[5m]))`, + metric{} 1+2x5 + metric{} 1+2x20`, + query: `sum(rate(metric{err=~".+"}[5m])) / sum(rate(metric[5m]))`, }, { name: "binop with positive matcher using regex, both sides have data", load: `load 30s - metric{} 1+2x5 - metric{err="FooBarKey"} 1+2x20`, - query: `sum(rate(metric{err=~".+"}[5m])) / sum(rate(metric{}[5m]))`, + metric{} 1+2x5 + metric{err="FooBarKey"} 1+2x20`, + query: `sum(rate(metric{err=~".+"}[5m])) / sum(rate(metric[5m]))`, }, { name: "binop with negative matcher using regex, only one side has data", load: `load 30s - metric{} 1+2x5 - metric{} 1+2x20`, - query: `sum(rate(metric{err!~".+"}[5m])) / sum(rate(metric{}[5m]))`, + metric{} 1+2x5 + metric{} 1+2x20`, + query: `sum(rate(metric{err!~".+"}[5m])) / sum(rate(metric[5m]))`, }, { name: "binop with negative matcher using regex, both sides have data", load: `load 30s - metric{} 1+2x5 - metric{err="FooBarKey"} 1+2x20`, - query: `sum(rate(metric{err!~".+"}[5m])) / sum(rate(metric{}[5m]))`, + metric{} 1+2x5 + metric{err="FooBarKey"} 1+2x20`, + query: `sum(rate(metric{err!~".+"}[5m])) / sum(rate(metric[5m]))`, }, { name: "scalar func with NaN", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} NaN`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} NaN`, query: `scalar(http_requests_total)`, }, { name: "scalar func with aggr", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `scalar(max(http_requests_total))`, }, { name: "scalar func with aggr and number on right", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `scalar(max(http_requests_total)) + 10`, }, { name: "scalar func with aggr and number on left", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `10 + scalar(max(http_requests_total))`, }, { name: "quantile with param series", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 - param_series 0+0.1x50`, - query: "quantile(scalar(param_series), rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 + param_series 0+0.1x50`, + query: `quantile(scalar(param_series), rate(http_requests_total[1m]))`, }, { name: "quantile with param series that evaluates to NaN", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 - param_series NaN+0x50`, - query: "quantile(scalar(param_series), rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 + param_series NaN+0x50`, + query: `quantile(scalar(param_series), rate(http_requests_total[1m]))`, }, { name: "quantile with non-existing param series", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 `, - query: "quantile(scalar(non_existent), rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `quantile(scalar(non_existent), rate(http_requests_total[1m]))`, }, { name: "clamp", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(http_requests_total, 5, 10)`, }, { name: "clamp_min", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, 10)`, }, { name: "complex func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(1 - http_requests_total, 10 - 5, 10)`, }, { name: "func within func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(irate(http_requests_total[30s]), 10 - 5, 10)`, }, { name: "aggr within func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(rate(http_requests_total[30s]), 10 - 5, 10)`, }, { name: "func with scalar arg that selects storage", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, scalar(max(http_requests_total)))`, }, { name: "func with scalar arg that selects storage + number", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, scalar(max(http_requests_total)) + 10)`, }, { name: "histogram quantile", load: `load 30s - http_requests_total{pod="nginx-1", le="1"} 1+3x10 - http_requests_total{pod="nginx-2", le="1"} 2+3x10 - http_requests_total{pod="nginx-1", le="2"} 1+2x10 - http_requests_total{pod="nginx-2", le="2"} 2+2x10 - http_requests_total{pod="nginx-2", le="5"} 3+2x10 - http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 - http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, + http_requests_total{pod="nginx-1", le="1"} 1+3x10 + http_requests_total{pod="nginx-2", le="1"} 2+3x10 + http_requests_total{pod="nginx-1", le="2"} 1+2x10 + http_requests_total{pod="nginx-2", le="2"} 2+2x10 + http_requests_total{pod="nginx-2", le="5"} 3+2x10 + http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 + http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on malformed data", load: `load 30s - http_requests_total{pod="nginx-1"} 1+3x10 - http_requests_total{pod="nginx-2"} 2+3x10`, + http_requests_total{pod="nginx-1"} 1+3x10 + http_requests_total{pod="nginx-2"} 2+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on partially malformed data", load: `load 30s - http_requests_total{pod="nginx-1", le="1"} 1+3x10 - http_requests_total{pod="nginx-2", le="2"} 2+3x10 - http_requests_total{pod="nginx-3"} 3+3x10 - http_requests_total{pod="nginx-4"} 4+3x10`, + http_requests_total{pod="nginx-1", le="1"} 1+3x10 + http_requests_total{pod="nginx-2", le="2"} 2+3x10 + http_requests_total{pod="nginx-3"} 3+3x10 + http_requests_total{pod="nginx-4"} 4+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on malformed, interleaved data", load: `load 30s - http_requests_total{pod="nginx-1"} 1+3x10 - http_requests_total{pod="nginx-2"} 2+3x10 - http_requests_total{pod="nginx-3", le="0.05"} 2+3x10 - http_requests_total{pod="nginx-4", le="0.1"} 2+3x10`, + http_requests_total{pod="nginx-1"} 1+3x10 + http_requests_total{pod="nginx-2"} 2+3x10 + http_requests_total{pod="nginx-3", le="0.05"} 2+3x10 + http_requests_total{pod="nginx-4", le="0.1"} 2+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on malformed, interleaved data 2", load: `load 30s - http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 - http_requests_total{pod="nginx-2", le="0.02"} 2+3x10 - http_requests_total{pod="nginx-3"} 2+3x10 - http_requests_total{pod="nginx-4"} 2+3x10`, + http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 + http_requests_total{pod="nginx-2", le="0.02"} 2+3x10 + http_requests_total{pod="nginx-3"} 2+3x10 + http_requests_total{pod="nginx-4"} 2+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on malformed, interleaved data 3", load: `load 30s - http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 - http_requests_total{pod="nginx-2"} 2+3x10 - http_requests_total{pod="nginx-3"} 2+3x10 - http_requests_total{pod="nginx-4", le="0.03"} 2+3x10`, + http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 + http_requests_total{pod="nginx-2"} 2+3x10 + http_requests_total{pod="nginx-3"} 2+3x10 + http_requests_total{pod="nginx-4", le="0.03"} 2+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile on malformed, interleaved data 4", load: `load 30s - http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 - http_requests_total{pod="nginx-2"} 2+3x10 - http_requests_total{pod="nginx-2", le="0.05"} 2+3x10 - http_requests_total{pod="nginx-2", le="0.2"} 2+3x10 - http_requests_total{pod="nginx-3"} 2+3x10 - http_requests_total{pod="nginx-4", le="0.03"} 2+3x10`, + http_requests_total{pod="nginx-1", le="0.01"} 1+3x10 + http_requests_total{pod="nginx-2"} 2+3x10 + http_requests_total{pod="nginx-2", le="0.05"} 2+3x10 + http_requests_total{pod="nginx-2", le="0.2"} 2+3x10 + http_requests_total{pod="nginx-3"} 2+3x10 + http_requests_total{pod="nginx-4", le="0.03"} 2+3x10`, query: `histogram_quantile(0.9, http_requests_total)`, }, { name: "histogram quantile with sum", load: `load 30s - http_requests_total{pod="nginx-1", le="1"} 1+3x10 - http_requests_total{pod="nginx-2", le="1"} 2+3x10 - http_requests_total{pod="nginx-1", le="2"} 1+2x10 - http_requests_total{pod="nginx-2", le="2"} 2+2x10 - http_requests_total{pod="nginx-2", le="5"} 3+2x10 - http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 - http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, + http_requests_total{pod="nginx-1", le="1"} 1+3x10 + http_requests_total{pod="nginx-2", le="1"} 2+3x10 + http_requests_total{pod="nginx-1", le="2"} 1+2x10 + http_requests_total{pod="nginx-2", le="2"} 2+2x10 + http_requests_total{pod="nginx-2", le="5"} 3+2x10 + http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 + http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, query: `histogram_quantile(0.9, sum by (pod, le) (rate(http_requests_total[2m])))`, }, { name: "histogram quantile with scalar operator", load: `load 30s - quantile{pod="nginx-1", le="1"} 1+1x2 - http_requests_total{pod="nginx-1", le="1"} 1+3x10 - http_requests_total{pod="nginx-2", le="1"} 2+3x10 - http_requests_total{pod="nginx-1", le="2"} 1+2x10 - http_requests_total{pod="nginx-2", le="2"} 2+2x10 - http_requests_total{pod="nginx-2", le="5"} 3+2x10 - http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 - http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, + quantile{pod="nginx-1", le="1"} 1+1x2 + http_requests_total{pod="nginx-1", le="1"} 1+3x10 + http_requests_total{pod="nginx-2", le="1"} 2+3x10 + http_requests_total{pod="nginx-1", le="2"} 1+2x10 + http_requests_total{pod="nginx-2", le="2"} 2+2x10 + http_requests_total{pod="nginx-2", le="5"} 3+2x10 + http_requests_total{pod="nginx-1", le="+Inf"} 1+1x10 + http_requests_total{pod="nginx-2", le="+Inf"} 4+1x10`, query: `histogram_quantile(scalar(max(quantile)), http_requests_total)`, }, { name: "topk", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(2, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk(2, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1641,12 +1644,12 @@ load 30s { name: "topk with float64 parameter", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(3.5, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk(3.5, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1654,12 +1657,12 @@ load 30s { name: "topk with float64 parameter that gets truncated to 0", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(0.5, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk(0.5, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1667,12 +1670,12 @@ load 30s { name: "topk with float64 parameter that does not fit int64", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(1e120, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk(1e+120, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1680,19 +1683,19 @@ load 30s { name: "topk with NaN", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(NaN, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk(NaN, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, }, { name: "topk with NaN and no matching series", - query: "topk(NaN, not_there)", + query: `topk(NaN, not_there)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1700,15 +1703,15 @@ load 30s { name: "topk with NaN comparison", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} NaN - http_requests_total{pod="nginx-2", route="/"} NaN`, - query: "topk by (route) (1, http_requests_total)", + http_requests_total{pod="nginx-1", route="/"} NaN + http_requests_total{pod="nginx-2", route="/"} NaN`, + query: `topk by (route) (1, http_requests_total)`, }, { name: "nested topk error that should not be skipped", load: `load 30s - X 1+1x50`, - query: "topk (0, topk (NaN, X))", + X 1+1x50`, + query: `topk(0, topk(NaN, X))`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1716,29 +1719,29 @@ load 30s { name: "topk wrapped by another aggregate", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "max(topk by (series) (2, http_requests_total))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `max(topk by (series) (2, http_requests_total))`, end: time.Unix(3000, 0), }, { name: "topk on empty result", load: `load 30s - metric_a 1+1x2`, - query: "topk(2, histogram_quantile(0.1, metric_b))", + metric_a 1+1x2`, + query: `topk(2, histogram_quantile(0.1, metric_b))`, }, { name: "topk by", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(2, http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk by (series) (2, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1746,12 +1749,12 @@ load 30s { name: "topk with simple expression", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(2 - 1, http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk by (series) (2 - 1, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1759,12 +1762,12 @@ load 30s { name: "topk with expression", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(scalar(min(http_requests_total)), http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk by (series) (scalar(min(http_requests_total)), http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(500, 0), step: 2 * time.Second, @@ -1772,12 +1775,12 @@ load 30s { name: "topk with expression as argument not returning any value", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "topk(scalar(min(non_existent_metric)), http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `topk by (series) (scalar(min(non_existent_metric)), http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(500, 0), step: 2 * time.Second, @@ -1785,12 +1788,12 @@ load 30s { name: "bottomK", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "bottomk(2, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `bottomk(2, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1798,12 +1801,12 @@ load 30s { name: "bottomK by", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "bottomk(2, http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `bottomk by (series) (2, http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1811,9 +1814,9 @@ load 30s { name: "sgn", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} -10+1x50`, - query: "sgn(http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} -10+1x50`, + query: `sgn(http_requests_total)`, start: time.Unix(0, 0), end: time.Unix(3000, 0), step: 2 * time.Second, @@ -1821,53 +1824,58 @@ load 30s { name: "sort_desc", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "sort_desc(http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="2"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="2"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `sort_desc(http_requests_total)`, }, { name: "count by __name__ label", load: `load 30s - foo 1+1x5 - bar 2+2x5`, + foo 1+1x5 + bar 2+2x5`, query: `count by (__name__) ({__name__=~".+"})`, }, { name: "scalar with bool", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-3", series="3"} 6+0.8x60 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-3", series="3"} 6+0.8x60 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, query: `scalar(avg_over_time({__name__="http_requests_total"}[3m])) > bool 0.9464749352949011`, }, { name: "repro https://github.com/thanos-io/promql-engine/issues/239", load: `load 30s - storage_used{storage_index="1010"} 65x20 - storage_used{storage_index="1011"} 125x20 - storage_used{storage_index="1012"} 0x20 - storage_used{storage_index="20"} 2290380x20 - storage_used{storage_index="30"} 397304x20 - storage_used{storage_index="40"} 5590832x20 - storage_used{storage_index="41"} 65559832x20 - storage_used{storage_index="42"} 3516400x20 - storage_info{storage_info="Config", storage_index="40"} 1x20 - storage_info{storage_info="Log", storage_index="41"} 1x20 - storage_info{storage_info="Mem", storage_index="20"} 1x20 - storage_info{storage_info="Root", storage_index="42"} 1x20 - storage_info{storage_info="Swap", storage_index="30"} 1x20`, - query: `avg by (storage_info) (storage_used * on (instance, storage_index) group_left(storage_info) (sum by (instance, storage_index, storage_info) (storage_info)))`, + storage_used{storage_index="1010"} 65x20 + storage_used{storage_index="1011"} 125x20 + storage_used{storage_index="1012"} 0x20 + storage_used{storage_index="20"} 2290380x20 + storage_used{storage_index="30"} 397304x20 + storage_used{storage_index="40"} 5590832x20 + storage_used{storage_index="41"} 65559832x20 + storage_used{storage_index="42"} 3516400x20 + storage_info{storage_info="Config", storage_index="40"} 1x20 + storage_info{storage_info="Log", storage_index="41"} 1x20 + storage_info{storage_info="Mem", storage_index="20"} 1x20 + storage_info{storage_info="Root", storage_index="42"} 1x20 + storage_info{storage_info="Swap", storage_index="30"} 1x20`, + query: ` +avg by (storage_info) ( + storage_used + * on (instance, storage_index) group_left (storage_info) + (sum by (instance, storage_index, storage_info) (storage_info)) +)`, }, { name: "absent with partial data in range", load: `load 30s - existent{job="myjob"} 1 1 1`, + existent{job="myjob"} 1 1 1`, query: `absent(existent{job="myjob"})`, }, { @@ -1877,70 +1885,70 @@ load 30s }, { name: "absent_over_time with no data in range", - query: "absent_over_time(non_existent[10m])", + query: `absent_over_time(non_existent[10m])`, }, { name: "absent_over_time with data in range", load: `load 30s - X{a="b"} 1x10`, + X{a="b"} 1x10`, query: `absent_over_time(X{a="b"}[10m])`, }, { name: "absent_over_time - present but out of range", load: `load 30s - X{a="b"} 1x10`, + X{a="b"} 1x10`, query: `absent_over_time(X{a="b"}[1m])`, start: time.Unix(600, 0), }, { name: "absent_over_time - absent because of label", load: `load 30s - X{a="b"} 1x10`, + X{a="b"} 1x10`, query: `absent_over_time(X{a!="b"}[1m])`, }, { name: "subquery in binary expression", load: `load 60s - http_requests_total{pod="nginx-1", series="1"} 1+1x40`, - query: "http_requests_total * (sum_over_time(http_requests_total[5m:1m]) > 0)", + http_requests_total{pod="nginx-1", series="1"} 1+1x40`, + query: `http_requests_total * (sum_over_time(http_requests_total[5m:1m]) > 0)`, }, { name: "sum_over_time subquery with outer step larger than inner step", load: `load 60s - http_requests_total{pod="nginx-1", series="1"} 1+1x40`, - query: "sum_over_time(sum_over_time(http_requests_total[2m])[5m:1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1x40`, + query: `sum_over_time(sum_over_time(http_requests_total[2m])[5m:1m])`, }, { name: "sum_over_time subquery with outer step equal to inner step", load: `load 60s - http_requests_total{pod="nginx-1", series="1"} 1+1x40`, - query: "sum_over_time(sum_over_time(http_requests_total[2m])[5m:30s])", + http_requests_total{pod="nginx-1", series="1"} 1+1x40`, + query: `sum_over_time(sum_over_time(http_requests_total[2m])[5m:30s])`, }, { name: "sum_over_time subquery with outer step smaller than inner step", load: `load 60s - http_requests_total{pod="nginx-1", series="1"} 1+1x40`, - query: "sum_over_time(sum_over_time(http_requests_total[2m])[5m:15s])", + http_requests_total{pod="nginx-1", series="1"} 1+1x40`, + query: `sum_over_time(sum_over_time(http_requests_total[2m])[5m:15s])`, }, { name: "sum_over_time subquery with aggregation", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50`, - query: "sum_over_time(sum by (pod) (http_requests_total)[5m:1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50`, + query: `sum_over_time(sum by (pod) (http_requests_total)[5m:1m])`, }, { name: "rate subquery with outer @ modifier", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50`, - query: "rate(http_requests_total[20s:10s] @ 100)", + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50`, + query: `rate(http_requests_total[20s:10s] @ 100.000)`, }, { name: "rate subquery with offset", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+2x40`, - query: "rate(http_requests_total[20s:10s] offset 20s)", + http_requests_total{pod="nginx-1", series="1"} 1+2x40`, + query: `rate(http_requests_total[20s:10s] offset 20s)`, }, } @@ -2065,7 +2073,7 @@ func TestWarnings(t *testing.T) { }{ { name: "single select call", - query: "http_requests_total", + query: `http_requests_total`, expectedWarns: annotations.New().Add( errors.New("test warning"), ), @@ -2165,7 +2173,7 @@ func TestEdgeCases(t *testing.T) { []float64{3, 4}, ), }, - query: `foo * on () group_left bar`, + query: `foo * on () group_left () bar`, start: time.Unix(0, 0), end: time.Unix(30000, 0), }, @@ -2412,7 +2420,7 @@ func TestXFunctions(t *testing.T) { { name: "eval instant xincrease with only one point", load: `load 5m - http_requests{path="/foo"} stale stale stale 5`, + http_requests{path="/foo"} stale stale stale 5`, query: "xincrease(http_requests[1h15m])", queryTime: time.Unix(1*60*60+15*60, 0), expected: []promql.Sample{ @@ -2444,8 +2452,8 @@ func TestXFunctions(t *testing.T) { { name: "eval instant at 30m increase(http_requests[30m])", load: `load 5m - http_requests{path="/foo"} 0 1 2 3 2 3 4`, - query: "increase(http_requests[30m])", + http_requests{path="/foo"} 0 1 2 3 2 3 4`, + query: `increase(http_requests[30m])`, queryTime: time.Unix(1800, 0), expected: []promql.Sample{ createSample(1800000, 7, labels.FromStrings("path", "/foo")), @@ -2454,7 +2462,7 @@ func TestXFunctions(t *testing.T) { { name: "eval instant at 30m xincrease(http_requests[30m])", load: `load 5m - http_requests{path="/foo"} 0 1 2 3 2 3 4`, + http_requests{path="/foo"} 0 1 2 3 2 3 4`, query: "xincrease(http_requests[30m])", queryTime: time.Unix(1800, 0), expected: []promql.Sample{ @@ -2495,7 +2503,7 @@ func TestXFunctions(t *testing.T) { { name: "eval instant at 4m xincrease(http_requests[2m]), with 1m lookback", load: `load 30s - http_requests 0 0 0 0 1 1 1 1`, + http_requests 0 0 0 0 1 1 1 1`, query: "xincrease(http_requests[2m])", queryTime: time.Unix(240, 0), expected: []promql.Sample{ @@ -2565,7 +2573,7 @@ func TestRateVsXRate(t *testing.T) { // 1. Reference eval { name: "eval instant at 25s rate, with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(25, 0), expected: []promql.Sample{ createSample(defaultQueryTime.UnixMilli(), 0.022, labels.FromStrings("path", "/foo")), @@ -2587,7 +2595,7 @@ func TestRateVsXRate(t *testing.T) { // XXX Seeing ~20% jump for path="/foo" { name: "eval instant at 24s rate(http_requests[50s]), with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(24, 0), expected: []promql.Sample{ createSample(24000, 0.0265, labels.FromStrings("path", "/foo")), @@ -2609,7 +2617,7 @@ func TestRateVsXRate(t *testing.T) { // XXX Higher instead of lower for both. { name: "eval instant at 26s rate(http_requests[50s]), with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(26, 0), expected: []promql.Sample{ createSample(26000, 0.022799999999999997, labels.FromStrings("path", "/foo")), @@ -2629,7 +2637,7 @@ func TestRateVsXRate(t *testing.T) { // 4. Reference eval { name: "eval instant at 75s rate(http_requests[50s]), with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(75, 0), expected: []promql.Sample{ createSample(75000, 0.022, labels.FromStrings("path", "/foo")), @@ -2651,7 +2659,7 @@ func TestRateVsXRate(t *testing.T) { // # XXX Higher instead of lower for both. { name: "eval instant at 74s rate(http_requests[50s]), with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(74, 0), expected: []promql.Sample{ createSample(74000, 0.02279999999, labels.FromStrings("path", "/foo")), @@ -2673,7 +2681,7 @@ func TestRateVsXRate(t *testing.T) { // XXX Seeing ~20% jump for path="/foo", decrease instead of increase for path="/bar". { name: "eval instant at 76s rate(http_requests[50s]), with 50s lookback", - query: "rate(http_requests[50s])", + query: `rate(http_requests[50s])`, queryTime: time.Unix(76, 0), expected: []promql.Sample{ createSample(76000, 0.0265, labels.FromStrings("path", "/foo")), @@ -2692,7 +2700,7 @@ func TestRateVsXRate(t *testing.T) { // Evaluation of 10 second rate every 10 seconds { name: "eval instant at 9s rate(http_requests[10s]), with 10s lookback", - query: "rate(http_requests[10s])", + query: `rate(http_requests[10s])`, queryTime: time.Unix(9, 0), expected: []promql.Sample{ createSample(9000, 0, labels.FromStrings("path", "/foo")), @@ -2701,7 +2709,7 @@ func TestRateVsXRate(t *testing.T) { }, { name: "eval instant at 19s rate(http_requests[10s]), with 10s lookback", - query: "rate(http_requests[10s])", + query: `rate(http_requests[10s])`, queryTime: time.Unix(19, 0), expected: []promql.Sample{ createSample(19000, 0.2, labels.FromStrings("path", "/foo")), @@ -2710,7 +2718,7 @@ func TestRateVsXRate(t *testing.T) { }, { name: "eval instant at 29s rate(http_requests[10s]), with 10s lookback", - query: "rate(http_requests[10s])", + query: `rate(http_requests[10s])`, queryTime: time.Unix(29, 0), expected: []promql.Sample{ createSample(29000, 0, labels.FromStrings("path", "/foo")), @@ -2719,7 +2727,7 @@ func TestRateVsXRate(t *testing.T) { }, { name: "eval instant at 39s rate(http_requests[10s]), with 10s lookback", - query: "rate(http_requests[10s])", + query: `rate(http_requests[10s])`, queryTime: time.Unix(39, 0), expected: []promql.Sample{ createSample(39000, 0, labels.FromStrings("path", "/foo")), @@ -2729,7 +2737,7 @@ func TestRateVsXRate(t *testing.T) { // XXX Missed an increase in path="/foo" between timestamps 35 and 40 (both in this eval and the one before). { name: "eval instant at 49s rate(http_requests[10s]), with 10s lookback", - query: "rate(http_requests[10s])", + query: `rate(http_requests[10s])`, queryTime: time.Unix(49, 0), expected: []promql.Sample{ createSample(49000, 0, labels.FromStrings("path", "/foo")), @@ -2880,78 +2888,68 @@ func TestInstantQuery(t *testing.T) { { name: "count_values fuzz", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 51.00+1.00x40 - http_requests_total{pod="nginx-2", route="/"} -74+14.00x40`, - query: `count_values without () ( - "value", - ( - atanh(http_requests_total{pod="nginx-1"}) - > - tanh(http_requests_total{route="/"}) - ) - or - avg by (pod, __name__) ( - http_requests_total{route="/"} - ) - )`, + http_requests_total{pod="nginx-1", route="/"} 51.00+1.00x40 + http_requests_total{pod="nginx-2", route="/"} -74+14.00x40`, + query: ` +count_values without () ( + "value", + (atanh(http_requests_total{pod="nginx-1"}) > tanh(http_requests_total{route="/"})) + or + avg by (pod, __name__) (http_requests_total{route="/"}) +)`, }, { name: "sum evaluates to -0 fuzz", load: `load 30s - http_requests_total{pod="nginx-2", route="/"} 0`, + http_requests_total{pod="nginx-2", route="/"} 0`, query: `sum by (pod) (-http_requests_total) atan2 -0`, queryTime: time.Unix(0, 0), }, { name: "count_values", load: `load 30s - version{foo="bar"} 1 - version{foo="baz"} 1 - version{foo="quz"} 2 - `, + version{foo="bar"} 1 + version{foo="baz"} 1 + version{foo="quz"} 2`, query: `count_values("val", version)`, queryTime: time.Unix(0, 0), }, { name: "binary pairing early exit fuzz", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 33.00+1.00x40 - http_requests_total{pod="nginx-2", route="/"} 1+2.00x40`, + http_requests_total{pod="nginx-1", route="/"} 33.00+1.00x40 + http_requests_total{pod="nginx-2", route="/"} 1+2.00x40`, query: ` - avg without (route) ( - avg(http_requests_total) / http_requests_total - ) - <= - sum by (__name__) ( - http_requests_total or avg(http_requests_total) - )`, + avg without (route) (avg(http_requests_total) / http_requests_total) +<= + sum by (__name__) (http_requests_total or avg(http_requests_total))`, queryTime: time.Unix(0, 0), }, { name: "offset and @ modifiers", load: `load 30s - http_requests_total{pod="nginx-0", route="/"} 1+1x30`, - query: `http_requests_total @end() offset 2m`, + http_requests_total{pod="nginx-0", route="/"} 1+1x30`, + query: `http_requests_total @ end() offset 2m`, queryTime: time.Unix(300, 0), }, { name: "timestamp - offset modifier", load: `load 30s - http_requests_total{pod="nginx-0", route="/"} 0x30`, + http_requests_total{pod="nginx-0", route="/"} 0x30`, query: `timestamp(http_requests_total offset 2m)`, queryTime: time.Unix(300, 0), }, { name: "timestamp - @ modifier", load: `load 30s - http_requests_total{pod="nginx-0", route="/"} 0x30`, - query: `timestamp(http_requests_total @ 60)`, + http_requests_total{pod="nginx-0", route="/"} 0x30`, + query: `timestamp(http_requests_total @ 60.000)`, queryTime: time.Unix(300, 0), }, { name: "timestamp - nested functions with offset", load: `load 30s - http_requests_total{pod="nginx-0", route="/"} 0x30`, + http_requests_total{pod="nginx-0", route="/"} 0x30`, query: `timestamp(timestamp(http_requests_total offset 2m))`, queryTime: time.Unix(300, 0), }, @@ -2963,54 +2961,54 @@ func TestInstantQuery(t *testing.T) { { name: "timestamp - aggregation", load: `load 30s - http_requests_total{pod="nginx-0", route="/"} 0x30`, + http_requests_total{pod="nginx-0", route="/"} 0x30`, query: `timestamp(sum(http_requests_total))`, queryTime: time.Unix(300, 0), }, { name: "timestamp - fuzzing failure", load: `load 30s - http_requests_total{pod="nginx-1"} 1.00+1.00x15 - http_requests_total{pod="nginx-2"} 1+2.00x21`, + http_requests_total{pod="nginx-1"} 1.00+1.00x15 + http_requests_total{pod="nginx-2"} 1+2.00x21`, query: `timestamp(http_requests_total @ end() offset -2m23s)`, queryTime: time.Unix(300, 0), }, { name: "fuzz - min with NaN", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 0 - http_requests_total{pod="nginx-2", route="/"} NaN`, + http_requests_total{pod="nginx-1", route="/"} 0 + http_requests_total{pod="nginx-2", route="/"} NaN`, query: `min without (__name__, pod) (http_requests_total)`, queryTime: time.Unix(0, 0), }, { name: "fuzz - max with NaN", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 0 - http_requests_total{pod="nginx-2", route="/"} NaN`, + http_requests_total{pod="nginx-1", route="/"} 0 + http_requests_total{pod="nginx-2", route="/"} NaN`, query: `max without (__name__, pod) (http_requests_total)`, queryTime: time.Unix(0, 0), }, { name: "fuzz - min with NaN", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 124.00+1.00x40 - http_requests_total{pod="nginx-2", route="/"} 0+0.29x40`, - query: "min by (route, pod) (sqrt(-http_requests_total))", + http_requests_total{pod="nginx-1", route="/"} 124.00+1.00x40 + http_requests_total{pod="nginx-2", route="/"} 0+0.29x40`, + query: `min by (route, pod) (sqrt(-http_requests_total))`, }, { name: "fuzz - min with Inf", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 483.00+6035.00x40 - http_requests_total{pod="nginx-2", route="/"} 2+47.14x40`, + http_requests_total{pod="nginx-1", route="/"} 483.00+6035.00x40 + http_requests_total{pod="nginx-2", route="/"} 2+47.14x40`, query: ` min without () ( - ( - {__name__="http_requests_total"} @ start() offset -2m40s - ^ - {__name__="http_requests_total"} @ start() offset -2m49s - ) - )`, + ( + {__name__="http_requests_total"} @ start() offset -2m40s + ^ + {__name__="http_requests_total"} @ start() offset -2m49s + ) +)`, }, /* This is a known issue, we lose the signed 0 in the sum because we add to a @@ -3024,624 +3022,624 @@ min without () ( { name: "sum_over_time with subquery", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total)[5m:1m])", + query: `sum_over_time(sum by (series) (http_requests_total)[5m:1m])`, }, { name: "sum_over_time with subquery with default step", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total)[5m:])", + query: `sum_over_time(sum by (series) (http_requests_total)[5m:])`, }, { name: "sum_over_time with subquery with resolution that doesnt divide step length", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total)[5m:22s])", + query: `sum_over_time(sum by (series) (http_requests_total)[5m:22s])`, }, { name: "sum_over_time with subquery with offset", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total)[5m:1m] offset 1m)", + query: `sum_over_time(sum by (series) (http_requests_total)[5m:1m] offset 1m)`, }, { name: "sum_over_time with subquery with inner offset", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total offset 1m)[5m:1m])", + query: `sum_over_time(sum by (series) (http_requests_total offset 1m)[5m:1m])`, }, { name: "sum_over_time with subquery with inner @ modifier", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(sum by (series) (http_requests_total @ 10)[5m:1m])", + query: `sum_over_time(sum by (series) (http_requests_total @ 10.000)[5m:1m])`, }, { name: "sum_over_time with nested subqueries with inner @ modifier", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2x50 - http_requests_total{pod="nginx-4", series="3"} 5+2x50 - http_requests_total{pod="nginx-5", series="1"} 8+4x50 - http_requests_total{pod="nginx-6", series="2"} 2+3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2x50 + http_requests_total{pod="nginx-4", series="3"} 5+2x50 + http_requests_total{pod="nginx-5", series="1"} 8+4x50 + http_requests_total{pod="nginx-6", series="2"} 2+3x50`, queryTime: time.Unix(600, 0), - query: "sum_over_time(rate(sum by (series) (http_requests_total @ 10)[5m:1m] @0)[10m:1m])", + query: `sum_over_time(rate(sum by (series) (http_requests_total @ 10.000)[5m:1m] @ 0.000)[10m:1m])`, }, { name: "sum_over_time with subquery should drop name label", load: `load 10s - http_requests_total{pod="nginx-1", series="1"} 1+1x40 - http_requests_total{pod="nginx-2", series="1"} 2+2x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1x40 + http_requests_total{pod="nginx-2", series="1"} 2+2x50`, queryTime: time.Unix(0, 0), query: `sum_over_time(http_requests_total{series="1"} offset 7s[1h:1m] @ 119.800)`, }, { name: "duplicate label set", load: `load 5m - testmetric1{src="a",dst="b"} 0 - testmetric2{src="a",dst="b"} 1`, - query: "changes({__name__=~'testmetric1|testmetric2'}[5m])", + testmetric1{src="a",dst="b"} 0 + testmetric2{src="a",dst="b"} 1`, + query: `changes({__name__=~"testmetric1|testmetric2"}[5m])`, }, { name: "scalar", load: ``, queryTime: time.Unix(160, 0), - query: "12 + 1", + query: `12 + 1`, }, { name: "string literal", load: ``, queryTime: time.Unix(160, 0), - query: "test-string-literal", + query: `test - string - literal`, }, { name: "increase plus offset", load: `load 1s - http_requests_total{pod="nginx-1"} 1+1x180`, + http_requests_total{pod="nginx-1"} 1+1x180`, queryTime: time.Unix(160, 0), - query: "increase(http_requests_total[1m] offset 1m)", + query: `increase(http_requests_total[1m] offset 1m)`, }, { name: "round", load: `load 1s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, queryTime: time.Unix(0, 0), - query: "round(http_requests_total)", + query: `round(http_requests_total)`, }, { name: "round with argument", load: `load 1s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, queryTime: time.Unix(0, 0), - query: "round(http_requests_total, 0.5)", + query: `round(http_requests_total, 0.5)`, }, { name: "sort", load: `load 1s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, queryTime: time.Unix(0, 0), - query: "sort(http_requests_total)", + query: `sort(http_requests_total)`, }, { name: "sort_desc", load: `load 1s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, queryTime: time.Unix(0, 0), - query: "sort_desc(http_requests_total)", + query: `sort_desc(http_requests_total)`, }, { name: "histogram_quantile with mock duplicate labels", load: `load 30s - http_requests_total{pod="nginx-2", route="/"} 0+0.14x40`, + http_requests_total{pod="nginx-2", route="/"} 0+0.14x40`, queryTime: time.Unix(600, 0), query: `histogram_quantile(10, -http_requests_total or http_requests_total)`, }, { name: "quantile by pod", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "quantile by (pod) (0.9, rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `quantile by (pod) (0.9, rate(http_requests_total[1m]))`, }, { name: "quantile by pod with binary", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "quantile by (pod) (1 - 0.1, rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `quantile by (pod) (1 - 0.1, rate(http_requests_total[1m]))`, }, { name: "quantile by pod with expression", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "quantile by (pod) (scalar(min(http_requests_total)), rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `quantile by (pod) (scalar(min(http_requests_total)), rate(http_requests_total[1m]))`, }, { name: "quantile", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50 `, - query: "quantile(0.9, rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `quantile(0.9, rate(http_requests_total[1m]))`, }, { name: "stdvar", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "stdvar(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `stdvar(http_requests_total)`, }, { name: "stdvar by pod", load: `load 30s - http_requests_total{pod="nginx-1"} 1 - http_requests_total{pod="nginx-2"} 2 - http_requests_total{pod="nginx-3"} 8 - http_requests_total{pod="nginx-4"} 6`, - query: "stdvar by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1"} 1 + http_requests_total{pod="nginx-2"} 2 + http_requests_total{pod="nginx-3"} 8 + http_requests_total{pod="nginx-4"} 6`, + query: `stdvar by (pod) (http_requests_total)`, }, { name: "stddev", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "stddev(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `stddev(http_requests_total)`, }, { name: "stddev by pod", load: `load 30s - http_requests_total{pod="nginx-1"} 1 - http_requests_total{pod="nginx-2"} 2 - http_requests_total{pod="nginx-3"} 8 - http_requests_total{pod="nginx-4"} 6`, - query: "stddev by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1"} 1 + http_requests_total{pod="nginx-2"} 2 + http_requests_total{pod="nginx-3"} 8 + http_requests_total{pod="nginx-4"} 6`, + query: `stddev by (pod) (http_requests_total)`, }, { name: "sum by pod", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "sum by (pod) (http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `sum by (pod) (http_requests_total)`, }, { name: "count", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count(http_requests_total)`, }, { name: "average", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "avg(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `avg(http_requests_total)`, }, { name: "label_join", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), - query: `label_join(http_requests_total{}, "label", "-", "pod", "series")`, + query: `label_join(http_requests_total, "label", "-", "pod", "series")`, }, { name: "label_join with non-existing src labels", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), - query: `label_join(http_requests_total{}, "label", "-", "test", "fake")`, + query: `label_join(http_requests_total, "label", "-", "test", "fake")`, }, { name: "label_join with overwrite dst label if exists", load: `load 30s - http_requests_total{pod="nginx-1", series="1", label="test-1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2", label="test-2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3", label="test-3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1", label="test-1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2", label="test-2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3", label="test-3"} 5+2.4x50`, queryTime: time.Unix(160, 0), - query: `label_join(http_requests_total{}, "label", "-", "pod", "series")`, + query: `label_join(http_requests_total, "label", "-", "pod", "series")`, }, { name: "label_join with no src labels provided", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), - query: `label_join(http_requests_total{}, "label", "-")`, + query: `label_join(http_requests_total, "label", "-")`, }, { name: "label_replace", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), query: `label_replace(http_requests_total, "foo", "$1", "series", ".*")`, }, { name: "label_replace with bad regular expression", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), query: `label_replace(http_requests_total, "foo", "$1", "series", "]]")`, }, { name: "label_replace non-existing src label", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50`, queryTime: time.Unix(160, 0), query: `label_replace(http_requests_total, "foo", "$1", "bar", ".*")`, }, { name: "topk", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1 - http_requests_total{pod="nginx-2", series="1"} 2 - http_requests_total{pod="nginx-3", series="1"} 8 - http_requests_total{pod="nginx-4", series="2"} 6 - http_requests_total{pod="nginx-5", series="2"} 8 - http_requests_total{pod="nginx-6", series="3"} 15 - http_requests_total{pod="nginx-7", series="3"} 11 - http_requests_total{pod="nginx-8", series="4"} 22 - http_requests_total{pod="nginx-9", series="4"} 89`, - query: "topk(2, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1 + http_requests_total{pod="nginx-2", series="1"} 2 + http_requests_total{pod="nginx-3", series="1"} 8 + http_requests_total{pod="nginx-4", series="2"} 6 + http_requests_total{pod="nginx-5", series="2"} 8 + http_requests_total{pod="nginx-6", series="3"} 15 + http_requests_total{pod="nginx-7", series="3"} 11 + http_requests_total{pod="nginx-8", series="4"} 22 + http_requests_total{pod="nginx-9", series="4"} 89`, + query: `topk(2, http_requests_total)`, }, { name: "topk by series", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1 - http_requests_total{pod="nginx-2", series="1"} 2 - http_requests_total{pod="nginx-3", series="1"} 8 - http_requests_total{pod="nginx-4", series="2"} 6 - http_requests_total{pod="nginx-5", series="2"} 8 - http_requests_total{pod="nginx-6", series="3"} 15 - http_requests_total{pod="nginx-7", series="3"} 11 - http_requests_total{pod="nginx-8", series="4"} 22 - http_requests_total{pod="nginx-9", series="4"} 89`, - query: "topk(2, http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1 + http_requests_total{pod="nginx-2", series="1"} 2 + http_requests_total{pod="nginx-3", series="1"} 8 + http_requests_total{pod="nginx-4", series="2"} 6 + http_requests_total{pod="nginx-5", series="2"} 8 + http_requests_total{pod="nginx-6", series="3"} 15 + http_requests_total{pod="nginx-7", series="3"} 11 + http_requests_total{pod="nginx-8", series="4"} 22 + http_requests_total{pod="nginx-9", series="4"} 89`, + query: `topk by (series) (2, http_requests_total)`, }, { name: "bottomK", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1 - http_requests_total{pod="nginx-2", series="1"} 2 - http_requests_total{pod="nginx-3", series="1"} 8 - http_requests_total{pod="nginx-4", series="2"} 6 - http_requests_total{pod="nginx-5", series="2"} 8 - http_requests_total{pod="nginx-6", series="3"} 15 - http_requests_total{pod="nginx-7", series="3"} 11 - http_requests_total{pod="nginx-8", series="4"} 22 - http_requests_total{pod="nginx-9", series="4"} 89`, - query: "bottomk(2, http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1 + http_requests_total{pod="nginx-2", series="1"} 2 + http_requests_total{pod="nginx-3", series="1"} 8 + http_requests_total{pod="nginx-4", series="2"} 6 + http_requests_total{pod="nginx-5", series="2"} 8 + http_requests_total{pod="nginx-6", series="3"} 15 + http_requests_total{pod="nginx-7", series="3"} 11 + http_requests_total{pod="nginx-8", series="4"} 22 + http_requests_total{pod="nginx-9", series="4"} 89`, + query: `bottomk(2, http_requests_total)`, }, { name: "bottomk by series", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1 - http_requests_total{pod="nginx-2", series="1"} 2 - http_requests_total{pod="nginx-3", series="1"} 8 - http_requests_total{pod="nginx-4", series="2"} 6 - http_requests_total{pod="nginx-5", series="2"} 8 - http_requests_total{pod="nginx-6", series="3"} 15 - http_requests_total{pod="nginx-7", series="3"} 11 - http_requests_total{pod="nginx-8", series="4"} 22 - http_requests_total{pod="nginx-9", series="4"} 89`, - query: "bottomk(2, http_requests_total) by (series)", + http_requests_total{pod="nginx-1", series="1"} 1 + http_requests_total{pod="nginx-2", series="1"} 2 + http_requests_total{pod="nginx-3", series="1"} 8 + http_requests_total{pod="nginx-4", series="2"} 6 + http_requests_total{pod="nginx-5", series="2"} 8 + http_requests_total{pod="nginx-6", series="3"} 15 + http_requests_total{pod="nginx-7", series="3"} 11 + http_requests_total{pod="nginx-8", series="4"} 22 + http_requests_total{pod="nginx-9", series="4"} 89`, + query: `bottomk by (series) (2, http_requests_total)`, }, { name: "max", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "max(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `max(http_requests_total)`, }, { name: "max with only 1 sample", load: `load 30s - http_requests_total{pod="nginx-1"} -1 - http_requests_total{pod="nginx-2"} 1`, - query: "max(http_requests_total) by (pod)", + http_requests_total{pod="nginx-1"} -1 + http_requests_total{pod="nginx-2"} 1`, + query: `max by (pod) (http_requests_total)`, }, { name: "min", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "min(http_requests_total)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `min(http_requests_total)`, }, { name: "min with only 1 sample", load: `load 30s - http_requests_total{pod="nginx-1"} -1 - http_requests_total{pod="nginx-2"} 1`, - query: "min(http_requests_total) by (pod)", + http_requests_total{pod="nginx-1"} -1 + http_requests_total{pod="nginx-2"} 1`, + query: `min by (pod) (http_requests_total)`, }, { name: "rate", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 - http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 - http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 - http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, - query: "rate(http_requests_total[1m])", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="2"} 2+2.3x50 + http_requests_total{pod="nginx-4", series="3"} 5+2.4x50 + http_requests_total{pod="nginx-5", series="1"} 8.4+2.3x50 + http_requests_total{pod="nginx-6", series="2"} 2.3+2.3x50`, + query: `rate(http_requests_total[1m])`, }, { name: "sum rate", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "sum(rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `sum(rate(http_requests_total[1m]))`, }, { name: "sum rate with single sample series", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4 - http_requests_total{pod="nginx-3"} 0`, - query: "sum by (pod) (rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4 + http_requests_total{pod="nginx-3"} 0`, + query: `sum by (pod) (rate(http_requests_total[1m]))`, }, { name: "sum rate with stale series", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x20`, - query: "sum(rate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x20`, + query: `sum(rate(http_requests_total[1m]))`, }, { name: "delta", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "delta(http_requests_total[1m])", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `delta(http_requests_total[1m])`, }, { name: "increase", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "increase(http_requests_total[1m])", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `increase(http_requests_total[1m])`, }, { name: "sum irate", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x4`, - query: "sum(irate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x4`, + query: `sum(irate(http_requests_total[1m]))`, }, { name: "sum irate with stale series", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x4 - http_requests_total{pod="nginx-2"} 1+2x20`, - query: "sum(irate(http_requests_total[1m]))", + http_requests_total{pod="nginx-1"} 1+1x4 + http_requests_total{pod="nginx-2"} 1+2x20`, + query: `sum(irate(http_requests_total[1m]))`, }, { name: "number literal", load: "", - query: "34", + query: `34`, }, { name: "vector", load: "", - query: "vector(24)", + query: `vector(24)`, }, { name: "binary operation with vector and scalar on the right", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `foo * 2`, }, { name: "binary operation with vector and scalar on the left", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `2 * foo`, }, { name: "complex binary operation", load: `load 30s - foo{method="get", code="500"} 1+1.1x30 - foo{method="get", code="404"} 1+2.2x20`, + foo{method="get", code="500"} 1+1.1x30 + foo{method="get", code="404"} 1+2.2x20`, query: `1 - (100 * sum(foo{method="get"}) / sum(foo))`, }, { name: "vector binary op ==", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) == sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) == sum by (method) (bar)`, }, { name: "vector binary op !=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) != sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) != sum by (method) (bar)`, }, { name: "vector binary op >", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) > sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) > sum by (method) (bar)`, }, { name: "vector binary op <", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) < sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) < sum by (method) (bar)`, }, { name: "vector binary op >=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) >= sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) >= sum by (method) (bar)`, }, { name: "vector binary op <=", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) <= sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) <= sum by (method) (bar)`, }, { name: "vector binary op ^", load: `load 30s - foo{method="get", code="500"} 1+1x40 - bar{method="get", code="404"} 1+1.1x30`, - query: `sum(foo) by (method) ^ sum(bar) by (method)`, + foo{method="get", code="500"} 1+1x40 + bar{method="get", code="404"} 1+1.1x30`, + query: `sum by (method) (foo) ^ sum by (method) (bar)`, }, { name: "vector binary op %", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) % sum(bar) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) % sum by (method) (bar)`, }, { name: "vector binary op and 1", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) and sum(bar) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) and sum by (method) (bar)`, }, { name: "vector binary op and 2", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (code) and sum(bar) by (code)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (code) (foo) and sum by (code) (bar)`, }, { name: "vector binary op unless 1", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) unless sum(bar) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) unless sum by (method) (bar)`, }, { name: "vector binary op unless 2", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (code) unless sum(bar) by (code)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (code) (foo) unless sum by (code) (bar)`, }, { name: "vector binary op unless 3", load: `load 30s - foo{method="get", code="500"} 1+2x40`, - query: `sum(foo) by (code) unless nonexistent`, + foo{method="get", code="500"} 1+2x40`, + query: `sum by (code) (foo) unless nonexistent`, }, { name: "vector binary op or 1", load: `load 30s - foo{A="1"} 1+1x40 - foo{A="2"} 2+2x40`, + foo{A="1"} 1+1x40 + foo{A="2"} 2+2x40`, query: `sinh(foo or exp(foo))`, }, { name: "vector binary op one-to-one left multiple matches", load: `load 30s - foo{method="get", code="500"} 1 - foo{method="get", code="200"} 1 - bar{method="get", code="200"} 1`, + foo{method="get", code="500"} 1 + foo{method="get", code="200"} 1 + bar{method="get", code="200"} 1`, query: `foo / ignoring (code) bar`, }, { name: "vector binary operation with many-to-many matching rhs high card", load: `load 30s - foo{code="200", method="get"} 1+1x20 - foo{code="200", method="post"} 1+1x20 - bar{code="200", method="get"} 1+1x20 - bar{code="200", method="post"} 1+1x20`, - query: `foo + on(code) group_right bar`, + foo{code="200", method="get"} 1+1x20 + foo{code="200", method="post"} 1+1x20 + bar{code="200", method="get"} 1+1x20 + bar{code="200", method="post"} 1+1x20`, + query: `foo + on (code) group_right () bar`, }, { name: "vector binary op > scalar", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `sum(foo) by (method) > 10`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `sum by (method) (foo) > 10`, }, { name: "scalar < vector binary op", load: `load 30s - foo{method="get", code="500"} 1+2x40 - bar{method="get", code="404"} 1+1x30`, - query: `10 < sum(foo) by (method)`, + foo{method="get", code="500"} 1+2x40 + bar{method="get", code="404"} 1+1x30`, + query: `10 < sum by (method) (foo)`, }, { name: "scalar binary op == true", @@ -3696,46 +3694,46 @@ min without () ( { name: "empty series", load: "", - query: "http_requests_total", + query: `http_requests_total`, }, { name: "empty series with func", load: "", - query: "sum(http_requests_total)", + query: `sum(http_requests_total)`, }, { name: "empty result", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total{pod="nginx-3"}`, }, { name: "last_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `last_over_time(http_requests_total[30s])`, }, { name: "group", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `group(http_requests_total)`, }, { name: "reset", load: `load 30s - http_requests_total{pod="nginx-1"} 100-1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 100-1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `resets(http_requests_total[5m])`, }, { name: "present_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `present_over_time(http_requests_total[30s])`, }, { @@ -3746,129 +3744,128 @@ min without () ( { name: "unary sub operation for vector", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `-http_requests_total`, }, { name: "unary add operation for vector", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `+http_requests_total`, }, { name: "vector positive offset", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total offset 30s`, }, { name: "vector negative offset", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `http_requests_total offset -30s`, }, { name: "matrix negative offset with sum_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x25 - http_requests_total{pod="nginx-2"} 1+2x28`, + http_requests_total{pod="nginx-1"} 1+1x25 + http_requests_total{pod="nginx-2"} 1+2x28`, query: `sum_over_time(http_requests_total[5m] offset 5m)`, }, { name: "matrix negative offset with count_over_time", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `count_over_time(http_requests_total[5m] offset -2m)`, }, { name: "@ vector time 10s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 10", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 10.000`, }, { name: "@ vector time 120s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 120", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 120.000`, }, { name: "@ vector time 360s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 360", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 360.000`, }, { name: "@ vector start", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ start()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ start()`, }, { name: "@ vector end", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ end()", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ end()`, }, { name: "count_over_time @ start", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "count_over_time(http_requests_total[5m] @ start())", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `count_over_time(http_requests_total[5m] @ start())`, }, { name: "sum_over_time @ end", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum_over_time(http_requests_total[5m] @ start())", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum_over_time(http_requests_total[5m] @ start())`, }, { name: "avg_over_time @ 180s", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "avg_over_time(http_requests_total[4m] @ 180)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `avg_over_time(http_requests_total[4m] @ 180.000)`, }, { name: "@ vector 240s offset 2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 240 offset 2m", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 240.000 offset 2m`, }, { name: "avg_over_time @ 120s offset -2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "http_requests_total @ 120 offset -2m", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `http_requests_total @ 120.000 offset -2m`, }, { name: "sum_over_time @ 180s offset 2m", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, - query: "sum_over_time(http_requests_total[5m] @ 180 offset 2m)", + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, + query: `sum_over_time(http_requests_total[5m] @ 180.000 offset 2m)`, }, { name: "scalar with nested binary operator with step invariant", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 53.33+56.00x40 - http_requests_total{pod="nginx-2", route="/"} -26+2.00x40`, - query: `vector(scalar((http_requests_total @ end() offset 5m > http_requests_total))) - `, + http_requests_total{pod="nginx-1", route="/"} 53.33+56.00x40 + http_requests_total{pod="nginx-2", route="/"} -26+2.00x40`, + query: `vector(scalar((http_requests_total @ end() offset 5m > http_requests_total)))`, }, { name: "scalar func with non existent metric in scalar comparison", @@ -3877,87 +3874,87 @@ min without () ( { name: "scalar func with NaN", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `scalar(http_requests_total)`, }, { name: "scalar func with aggr", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `scalar(max(http_requests_total))`, }, { name: "scalar func with aggr and number on right", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `scalar(max(http_requests_total)) + 10`, }, { name: "scalar func with aggr and number on left", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `10 + scalar(max(http_requests_total))`, }, { name: "clamp", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(http_requests_total, 5, 10)`, }, { name: "clamp_min", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, 10)`, }, { name: "complex func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(1 - http_requests_total, 10 - 5, 10)`, }, { name: "func within func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(irate(http_requests_total[30s]), 10 - 5, 10)`, }, { name: "aggr within func query", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp(rate(http_requests_total[30s]), 10 - 5, 10)`, }, { name: "func with scalar arg that selects storage", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, scalar(max(http_requests_total)))`, }, { name: "func with scalar arg that selects storage + number", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x15 - http_requests_total{pod="nginx-2"} 1+2x18`, + http_requests_total{pod="nginx-1"} 1+1x15 + http_requests_total{pod="nginx-2"} 1+2x18`, query: `clamp_min(http_requests_total, scalar(max(http_requests_total)) + 10)`, }, { name: "sgn", load: `load 30s - http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 - http_requests_total{pod="nginx-2", series="1"} -10+1x50 - http_requests_total{pod="nginx-3", series="1"} NaN`, - query: "sgn(http_requests_total)", + http_requests_total{pod="nginx-1", series="1"} 1+1.1x40 + http_requests_total{pod="nginx-2", series="1"} -10+1x50 + http_requests_total{pod="nginx-3", series="1"} NaN`, + query: `sgn(http_requests_total)`, }, { name: "absent and series does not exist", @@ -3967,18 +3964,18 @@ min without () ( { name: "absent and series exists", load: `load 30s - existent{job="myjob"} 1`, + existent{job="myjob"} 1`, query: `absent(existent{job="myjob"})`, }, { name: "absent and regex matcher", load: `load 30s`, - query: `absent(nonexistent{job="myjob", instance=~".*"})`, + query: `absent(nonexistent{instance=~".*",job="myjob"})`, }, { name: "absent and duplicate matchers", load: `load 30s`, - query: `absent(nonexistent{job="myjob", job="yourjob", foo="bar"})`, + query: `absent(nonexistent{foo="bar",job="myjob",job="yourjob"})`, }, { name: "absent and nested function", @@ -3988,37 +3985,37 @@ min without () ( { name: "absent and nested absent with existing series", load: `load 30s - existent{job="myjob"} 1`, + existent{job="myjob"} 1`, query: `absent(absent(existent{job="myjob"}))`, }, { name: "absent_over_time with subquery - present data", load: `load 30s - X{a="b"} 1x10`, + X{a="b"} 1x10`, query: `absent_over_time(sum_over_time(X{a="b"}[1m])[1m:30s])`, }, { name: "absent_over_time with subquery - missing data", load: `load 30s - X{a="b"} 1x10`, + X{a="b"} 1x10`, query: `absent_over_time(sum_over_time(X{a!="b"}[1m])[1m:30s])`, }, { name: "absent_over_time with subquery and fixed offset", load: `load 30s - http_requests_total{pod="nginx-1"} 1+1x10 - http_requests_total{pod="nginx-2"} 1+2x10`, + http_requests_total{pod="nginx-1"} 1+1x10 + http_requests_total{pod="nginx-2"} 1+2x10`, query: `absent_over_time(http_requests_total @ start()[1h:1m])`, }, { name: "absent_over_time fuzzer findings", load: `load 30s - http_requests_total{pod="nginx-1", route="/"} 0.02+1.00x40 - http_requests_total{pod="nginx-2", route="/"} -24+0.67x40`, + http_requests_total{pod="nginx-1", route="/"} 0.02+1.00x40 + http_requests_total{pod="nginx-2", route="/"} -24+0.67x40`, query: ` -count without (route, pod) ({__name__="http_requests_total"} @ 153.689) + count without (route, pod) ({__name__="http_requests_total"} @ 153.689) > -absent_over_time({__name__="http_requests_total",route="/"}[3m] offset 1m45s)`, + absent_over_time({__name__="http_requests_total",route="/"}[3m] offset 1m45s)`, }, } @@ -4234,220 +4231,220 @@ func TestSelectHintsSetCorrectly(t *testing.T) { expected []*storage.SelectHints }{ { - query: "foo", start: 10000, + query: `foo`, start: 10000, expected: []*storage.SelectHints{ {Start: 5000, End: 10000}, }, }, { - query: "foo @ 15", start: 10000, + query: `foo @ 15.000`, start: 10000, expected: []*storage.SelectHints{ {Start: 10000, End: 15000}, }, }, { - query: "foo @ 1", start: 10000, + query: `foo @ 1.000`, start: 10000, expected: []*storage.SelectHints{ {Start: -4000, End: 1000}, }, }, { - query: "foo[2m]", start: 200000, + query: `foo[2m]`, start: 200000, expected: []*storage.SelectHints{ {Start: 80000, End: 200000, Range: 120000}, }, }, { - query: "foo[2m] @ 180", start: 200000, + query: `foo[2m] @ 180.000`, start: 200000, expected: []*storage.SelectHints{ {Start: 60000, End: 180000, Range: 120000}, }, }, { - query: "foo[2m] @ 300", start: 200000, + query: `foo[2m] @ 300.000`, start: 200000, expected: []*storage.SelectHints{ {Start: 180000, End: 300000, Range: 120000}, }, }, { - query: "foo[2m] @ 60", start: 200000, + query: `foo[2m] @ 60.000`, start: 200000, expected: []*storage.SelectHints{ {Start: -60000, End: 60000, Range: 120000}, }, }, { - query: "foo[2m] offset 2m", start: 300000, + query: `foo[2m] offset 2m`, start: 300000, expected: []*storage.SelectHints{ {Start: 60000, End: 180000, Range: 120000}, }, }, { - query: "foo[2m] @ 200 offset 2m", start: 300000, + query: `foo[2m] @ 200.000 offset 2m`, start: 300000, expected: []*storage.SelectHints{ {Start: -40000, End: 80000, Range: 120000}, }, }, { - query: "foo[2m:1s]", start: 300000, + query: `foo[2m:1s]`, start: 300000, expected: []*storage.SelectHints{ {Start: 175000, End: 300000, Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s])", start: 300000, + query: `count_over_time(foo[2m:1s])`, start: 300000, expected: []*storage.SelectHints{ {Start: 175000, End: 300000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 300)", start: 200000, + query: `count_over_time(foo[2m:1s] @ 300.000)`, start: 200000, expected: []*storage.SelectHints{ {Start: 175000, End: 300000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 200)", start: 200000, + query: `count_over_time(foo[2m:1s] @ 200.000)`, start: 200000, expected: []*storage.SelectHints{ {Start: 75000, End: 200000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 100)", start: 200000, + query: `count_over_time(foo[2m:1s] @ 100.000)`, start: 200000, expected: []*storage.SelectHints{ {Start: -25000, End: 100000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] offset 10s)", start: 300000, + query: `count_over_time(foo[2m:1s] offset 10s)`, start: 300000, expected: []*storage.SelectHints{ {Start: 165000, End: 290000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time((foo offset 10s)[2m:1s] offset 10s)", start: 300000, + query: `count_over_time((foo offset 10s)[2m:1s] offset 10s)`, start: 300000, expected: []*storage.SelectHints{ {Start: 155000, End: 280000, Func: "count_over_time", Step: 1000}, }, }, { // When the @ is on the vector selector, the enclosing subquery parameters // don't affect the hint ranges. - query: "count_over_time((foo @ 200 offset 10s)[2m:1s] offset 10s)", start: 300000, + query: `count_over_time((foo @ 200.000 offset 10s)[2m:1s] offset 10s)`, start: 300000, expected: []*storage.SelectHints{ {Start: 185000, End: 190000, Func: "count_over_time", Step: 1000}, }, }, { // When the @ is on the vector selector, the enclosing subquery parameters // don't affect the hint ranges. - query: "count_over_time((foo @ 200 offset 10s)[2m:1s] @ 100 offset 10s)", start: 300000, + query: `count_over_time((foo @ 200.000 offset 10s)[2m:1s] @ 100.000 offset 10s)`, start: 300000, expected: []*storage.SelectHints{ {Start: 185000, End: 190000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time((foo offset 10s)[2m:1s] @ 100 offset 10s)", start: 300000, + query: `count_over_time((foo offset 10s)[2m:1s] @ 100.000 offset 10s)`, start: 300000, expected: []*storage.SelectHints{ {Start: -45000, End: 80000, Func: "count_over_time", Step: 1000}, }, }, { - query: "foo", start: 10000, end: 20000, + query: `foo`, start: 10000, end: 20000, expected: []*storage.SelectHints{ {Start: 5000, End: 20000, Step: 1000}, }, }, { - query: "foo @ 15", start: 10000, end: 20000, + query: `foo @ 15.000`, start: 10000, end: 20000, expected: []*storage.SelectHints{ {Start: 10000, End: 15000, Step: 1000}, }, }, { - query: "foo @ 1", start: 10000, end: 20000, + query: `foo @ 1.000`, start: 10000, end: 20000, expected: []*storage.SelectHints{ {Start: -4000, End: 1000, Step: 1000}, }, }, { - query: "rate(foo[2m] @ 180)", start: 200000, end: 500000, + query: `rate(foo[2m] @ 180.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: 60000, End: 180000, Range: 120000, Func: "rate", Step: 1000}, }, }, { - query: "rate(foo[2m] @ 300)", start: 200000, end: 500000, + query: `rate(foo[2m] @ 300.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: 180000, End: 300000, Range: 120000, Func: "rate", Step: 1000}, }, }, { - query: "rate(foo[2m] @ 60)", start: 200000, end: 500000, + query: `rate(foo[2m] @ 60.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: -60000, End: 60000, Range: 120000, Func: "rate", Step: 1000}, }, }, { - query: "rate(foo[2m])", start: 200000, end: 500000, + query: `rate(foo[2m])`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: 80000, End: 500000, Range: 120000, Func: "rate", Step: 1000}, }, }, { - query: "rate(foo[2m] offset 2m)", start: 300000, end: 500000, + query: `rate(foo[2m] offset 2m)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 60000, End: 380000, Range: 120000, Func: "rate", Step: 1000}, }, }, { - query: "rate(foo[2m:1s])", start: 300000, end: 500000, + query: `rate(foo[2m:1s])`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 175000, End: 500000, Func: "rate", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s])", start: 300000, end: 500000, + query: `count_over_time(foo[2m:1s])`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 175000, End: 500000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] offset 10s)", start: 300000, end: 500000, + query: `count_over_time(foo[2m:1s] offset 10s)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 165000, End: 490000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 300)", start: 200000, end: 500000, + query: `count_over_time(foo[2m:1s] @ 300.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: 175000, End: 300000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 200)", start: 200000, end: 500000, + query: `count_over_time(foo[2m:1s] @ 200.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: 75000, End: 200000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time(foo[2m:1s] @ 100)", start: 200000, end: 500000, + query: `count_over_time(foo[2m:1s] @ 100.000)`, start: 200000, end: 500000, expected: []*storage.SelectHints{ {Start: -25000, End: 100000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time((foo offset 10s)[2m:1s] offset 10s)", start: 300000, end: 500000, + query: `count_over_time((foo offset 10s)[2m:1s] offset 10s)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 155000, End: 480000, Func: "count_over_time", Step: 1000}, }, }, { // When the @ is on the vector selector, the enclosing subquery parameters // don't affect the hint ranges. - query: "count_over_time((foo @ 200 offset 10s)[2m:1s] offset 10s)", start: 300000, end: 500000, + query: `count_over_time((foo @ 200.000 offset 10s)[2m:1s] offset 10s)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 185000, End: 190000, Func: "count_over_time", Step: 1000}, }, }, { // When the @ is on the vector selector, the enclosing subquery parameters // don't affect the hint ranges. - query: "count_over_time((foo @ 200 offset 10s)[2m:1s] @ 100 offset 10s)", start: 300000, end: 500000, + query: `count_over_time((foo @ 200.000 offset 10s)[2m:1s] @ 100.000 offset 10s)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: 185000, End: 190000, Func: "count_over_time", Step: 1000}, }, }, { - query: "count_over_time((foo offset 10s)[2m:1s] @ 100 offset 10s)", start: 300000, end: 500000, + query: `count_over_time((foo offset 10s)[2m:1s] @ 100.000 offset 10s)`, start: 300000, end: 500000, expected: []*storage.SelectHints{ {Start: -45000, End: 80000, Func: "count_over_time", Step: 1000}, }, }, { - query: "sum by (dim1) (foo)", start: 10000, + query: `sum by (dim1) (foo)`, start: 10000, expected: []*storage.SelectHints{ {Start: 5000, End: 10000, Func: "sum", By: true, Grouping: []string{"dim1"}}, }, }, { - query: "sum without (dim1) (foo)", start: 10000, + query: `sum without (dim1) (foo)`, start: 10000, expected: []*storage.SelectHints{ {Start: 5000, End: 10000, Func: "sum", Grouping: []string{"dim1"}}, }, }, { - query: "sum by (dim1) (avg_over_time(foo[1s]))", start: 10000, + query: `sum by (dim1) (avg_over_time(foo[1s]))`, start: 10000, expected: []*storage.SelectHints{ {Start: 9000, End: 10000, Func: "avg_over_time", Range: 1000}, }, }, { - query: "sum by (dim1) (max by (dim2) (foo))", start: 10000, + query: `sum by (dim1) (max by (dim2) (foo))`, start: 10000, expected: []*storage.SelectHints{ {Start: 5000, End: 10000, Func: "max", By: true, Grouping: []string{"dim2"}}, }, }, { - query: "(max by (dim1) (foo))[5s:1s]", start: 10000, + query: `(max by (dim1) (foo))[5s:1s]`, start: 10000, expected: []*storage.SelectHints{ {Start: 0, End: 10000, Func: "max", By: true, Grouping: []string{"dim1"}, Step: 1000}, }, @@ -4458,47 +4455,47 @@ func TestSelectHintsSetCorrectly(t *testing.T) { {Start: 95000, End: 120000, Func: "max", By: true, Step: 5000}, }, }, { - query: "foo @ 50 + bar @ 250 + baz @ 900", start: 100000, end: 500000, + query: `foo @ 50.000 + bar @ 250.000 + baz @ 900.000`, start: 100000, end: 500000, expected: []*storage.SelectHints{ {Start: 45000, End: 50000, Step: 1000}, {Start: 245000, End: 250000, Step: 1000}, {Start: 895000, End: 900000, Step: 1000}, }, }, { - query: "foo @ 50 + bar + baz @ 900", start: 100000, end: 500000, + query: `foo @ 50.000 + bar + baz @ 900.000`, start: 100000, end: 500000, expected: []*storage.SelectHints{ {Start: 45000, End: 50000, Step: 1000}, {Start: 95000, End: 500000, Step: 1000}, {Start: 895000, End: 900000, Step: 1000}, }, }, { - query: "rate(foo[2s] @ 50) + bar @ 250 + baz @ 900", start: 100000, end: 500000, + query: `rate(foo[2s] @ 50.000) + bar @ 250.000 + baz @ 900.000`, start: 100000, end: 500000, expected: []*storage.SelectHints{ {Start: 48000, End: 50000, Step: 1000, Func: "rate", Range: 2000}, {Start: 245000, End: 250000, Step: 1000}, {Start: 895000, End: 900000, Step: 1000}, }, }, { - query: "rate(foo[2s:1s] @ 50) + bar + baz", start: 100000, end: 500000, + query: `rate(foo[2s:1s] @ 50.000) + bar + baz`, start: 100000, end: 500000, expected: []*storage.SelectHints{ {Start: 43000, End: 50000, Step: 1000, Func: "rate"}, {Start: 95000, End: 500000, Step: 1000}, {Start: 95000, End: 500000, Step: 1000}, }, }, { - query: "rate(foo[2s:1s] @ 50) + bar + rate(baz[2m:1s] @ 900 offset 2m) ", start: 100000, end: 500000, + query: `rate(foo[2s:1s] @ 50.000) + bar + rate(baz[2m:1s] @ 900.000 offset 2m)`, start: 100000, end: 500000, expected: []*storage.SelectHints{ {Start: 43000, End: 50000, Step: 1000, Func: "rate"}, {Start: 95000, End: 500000, Step: 1000}, {Start: 655000, End: 780000, Step: 1000, Func: "rate"}, }, }, { // Hints are based on the inner most subquery timestamp. - query: `sum_over_time(sum_over_time(metric{job="1"}[100s])[100s:25s] @ 50)[3s:1s] @ 3000`, start: 100000, + query: `sum_over_time(sum_over_time(metric{job="1"}[1m40s])[1m40s:25s] @ 50.000)[3s:1s] @ 3000.000`, start: 100000, expected: []*storage.SelectHints{ {Start: -150000, End: 50000, Range: 100000, Func: "sum_over_time", Step: 25000}, }, }, { // Hints are based on the inner most subquery timestamp. - query: `sum_over_time(sum_over_time(metric{job="1"}[100s])[100s:25s] @ 3000)[3s:1s] @ 50`, + query: `sum_over_time(sum_over_time(metric{job="1"}[1m40s])[1m40s:25s] @ 3000.000)[3s:1s] @ 50.000`, expected: []*storage.SelectHints{ {Start: 2800000, End: 3000000, Range: 100000, Func: "sum_over_time", Step: 25000}, }, @@ -4898,43 +4895,43 @@ func TestNativeHistograms(t *testing.T) { cases := []histogramTestCase{ { name: "count_over_time() with different start time", - query: "count_over_time(native_histogram_series[1m15s])", + query: `count_over_time(native_histogram_series[1m15s])`, start: time.Unix(400, 0), }, { name: "irate()", - query: "irate(native_histogram_series[1m])", + query: `irate(native_histogram_series[1m])`, }, { name: "rate()", - query: "rate(native_histogram_series[1m])", + query: `rate(native_histogram_series[1m])`, }, { name: "increase()", - query: "increase(native_histogram_series[1m])", + query: `increase(native_histogram_series[1m])`, }, { name: "delta()", - query: "delta(native_histogram_series[1m])", + query: `delta(native_histogram_series[1m])`, }, { name: "sum()", - query: "sum(native_histogram_series)", + query: `sum(native_histogram_series)`, wantEmptyForMixedTypes: true, }, { name: "sum by (foo)", - query: "sum by (foo) (native_histogram_series)", + query: `sum by (foo) (native_histogram_series)`, wantEmptyForMixedTypes: true, }, { name: "count", - query: "count (native_histogram_series)", + query: `count(native_histogram_series)`, }, { name: "count by (foo)", - query: "count by (foo) (native_histogram_series)", + query: `count by (foo) (native_histogram_series)`, }, // TODO(fpetkovski): The Prometheus engine returns an incorrect result for this case. // Uncomment once it gets fixed: https://github.com/prometheus/prometheus/issues/11973. @@ -4944,7 +4941,7 @@ func TestNativeHistograms(t *testing.T) { // }, { name: "max by (foo)", - query: "max by (foo) (native_histogram_series)", + query: `max by (foo) (native_histogram_series)`, }, // TODO(fpetkovski): The Prometheus engine returns an incorrect result for this case. // Uncomment once it gets fixed: https://github.com/prometheus/prometheus/issues/11973. @@ -4954,68 +4951,71 @@ func TestNativeHistograms(t *testing.T) { // }, { name: "min by (foo)", - query: "min by (foo) (native_histogram_series)", + query: `min by (foo) (native_histogram_series)`, }, { name: "absent", - query: "absent(native_histogram_series)", + query: `absent(native_histogram_series)`, }, { name: "histogram_sum", - query: "histogram_sum(native_histogram_series)", + query: `histogram_sum(native_histogram_series)`, }, { name: "histogram_count", - query: "histogram_count(native_histogram_series)", + query: `histogram_count(native_histogram_series)`, }, { name: "histogram_count of histogram product", - query: "histogram_count(native_histogram_series * native_histogram_series)", + query: `histogram_count(native_histogram_series * native_histogram_series)`, }, { name: "histogram_sum / histogram_count", - query: "histogram_sum(native_histogram_series) / histogram_count(native_histogram_series)", + query: `histogram_sum(native_histogram_series) / histogram_count(native_histogram_series)`, }, { name: "histogram_sum over histogram_fraction", - query: "histogram_sum(scalar(histogram_quantile(1, sum(native_histogram_series))) * native_histogram_series)", + query: `histogram_sum(scalar(histogram_quantile(1, sum(native_histogram_series))) * native_histogram_series)`, }, { - name: "histogram_sum over histogram_fraction", - query: "histogram_sum(scalar(histogram_fraction(-Inf, +Inf, sum(native_histogram_series))) * native_histogram_series)", + name: "histogram_sum over histogram_fraction", + query: ` +histogram_sum( + scalar(histogram_fraction(-Inf, +Inf, sum(native_histogram_series))) * native_histogram_series +)`, }, { name: "histogram_quantile", - query: "histogram_quantile(0.7, native_histogram_series)", + query: `histogram_quantile(0.7, native_histogram_series)`, }, { // Test strange query with a mix of histogram functions. name: "histogram_quantile(histogram_sum)", - query: "histogram_quantile(0.7, histogram_sum(native_histogram_series))", + query: `histogram_quantile(0.7, histogram_sum(native_histogram_series))`, }, { name: "histogram_count * histogram aggregation", - query: "scalar(histogram_count(sum(native_histogram_series))) * sum(native_histogram_series)", + query: `scalar(histogram_count(sum(native_histogram_series))) * sum(native_histogram_series)`, }, { name: "histogram_fraction", - query: "histogram_fraction(0, 0.2, native_histogram_series)", + query: `histogram_fraction(0, 0.2, native_histogram_series)`, }, { name: "lhs multiplication", - query: "native_histogram_series * 3", + query: `native_histogram_series * 3`, }, { name: "rhs multiplication", - query: "3 * native_histogram_series", + query: `3 * native_histogram_series`, }, { name: "lhs division", - query: "native_histogram_series / 2", + query: `native_histogram_series / 2`, }, { name: "subqueries", - query: "increase(rate(native_histogram_series[2m])[2m:15s])", + query: `increase(rate(native_histogram_series[2m])[2m:15s])`, }, } diff --git a/engine/existing_test.go b/engine/existing_test.go index e1a6d9c8..c0a30409 100644 --- a/engine/existing_test.go +++ b/engine/existing_test.go @@ -29,8 +29,8 @@ func TestRangeQuery(t *testing.T) { { Name: "sum_over_time with all values", Load: `load 30s - bar 0 1 10 100 1000`, - Query: "sum_over_time(bar[30s])", + bar 0 1 10 100 1000`, + Query: `sum_over_time(bar[30s])`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 0, T: 0}, {F: 11, T: 60000}, {F: 1100, T: 120000}}, @@ -44,8 +44,8 @@ func TestRangeQuery(t *testing.T) { { Name: "sum_over_time with trailing values", Load: `load 30s - bar 0 1 10 100 1000 0 0 0 0`, - Query: "sum_over_time(bar[30s])", + bar 0 1 10 100 1000 0 0 0 0`, + Query: `sum_over_time(bar[30s])`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 0, T: 0}, {F: 11, T: 60000}, {F: 1100, T: 120000}}, @@ -59,8 +59,8 @@ func TestRangeQuery(t *testing.T) { { Name: "sum_over_time with all values long", Load: `load 30s - bar 0 1 10 100 1000 10000 100000 1000000 10000000`, - Query: "sum_over_time(bar[30s])", + bar 0 1 10 100 1000 10000 100000 1000000 10000000`, + Query: `sum_over_time(bar[30s])`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 0, T: 0}, {F: 11, T: 60000}, {F: 1100, T: 120000}, {F: 110000, T: 180000}, {F: 11000000, T: 240000}}, @@ -74,8 +74,8 @@ func TestRangeQuery(t *testing.T) { { Name: "sum_over_time with all values random", Load: `load 30s - bar 5 17 42 2 7 905 51`, - Query: "sum_over_time(bar[30s])", + bar 5 17 42 2 7 905 51`, + Query: `sum_over_time(bar[30s])`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 5, T: 0}, {F: 59, T: 60000}, {F: 9, T: 120000}, {F: 956, T: 180000}}, @@ -89,8 +89,8 @@ func TestRangeQuery(t *testing.T) { { Name: "metric query", Load: `load 30s - metric 1+1x4`, - Query: "metric", + metric 1+1x4`, + Query: `metric`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 1, T: 0}, {F: 3, T: 60000}, {F: 5, T: 120000}}, @@ -104,8 +104,8 @@ func TestRangeQuery(t *testing.T) { { Name: "metric query with trailing values", Load: `load 30s - metric 1+1x8`, - Query: "metric", + metric 1+1x8`, + Query: `metric`, Result: promql.Matrix{ promql.Series{ Floats: []promql.FPoint{{F: 1, T: 0}, {F: 3, T: 60000}, {F: 5, T: 120000}}, diff --git a/engine/explain_test.go b/engine/explain_test.go index 191ee6b8..ba6b49ae 100644 --- a/engine/explain_test.go +++ b/engine/explain_test.go @@ -48,7 +48,7 @@ func TestQueryExplain(t *testing.T) { expected *engine.ExplainOutputNode }{ { - query: "time()", + query: `time()`, expected: &engine.ExplainOutputNode{OperatorName: "[duplicateLabelCheck]", Children: []engine.ExplainOutputNode{ { OperatorName: "[noArgFunction]", @@ -57,11 +57,11 @@ func TestQueryExplain(t *testing.T) { }}, }, { - query: "foo", + query: `foo`, expected: &engine.ExplainOutputNode{OperatorName: "[coalesce]", Children: concurrencyOperators}, }, { - query: "sum(foo) by (job)", + query: `sum by (job) (foo)`, expected: &engine.ExplainOutputNode{ OperatorName: "[duplicateLabelCheck]", Children: []engine.ExplainOutputNode{ @@ -134,16 +134,16 @@ func TestQueryAnalyze(t *testing.T) { query string }{ { - query: "foo", + query: `foo`, }, { - query: "time()", + query: `time()`, }, { - query: "sum(foo) by (job)", + query: `sum by (job) (foo)`, }, { - query: "rate(http_requests_total[30s]) > bool 0", + query: `rate(http_requests_total[30s]) > bool 0`, }, } { tc := tc diff --git a/go.mod b/go.mod index 2d7e3bfe..ea48a05c 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/zhangyunhao116/umap v0.0.0-20221211160557-cb7705fafa39 go.uber.org/goleak v1.3.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a + golang.org/x/tools v0.20.0 gonum.org/v1/gonum v0.12.0 ) @@ -57,6 +58,7 @@ require ( go.opentelemetry.io/otel/trace v1.25.0 // indirect go.uber.org/atomic v1.11.0 // indirect golang.org/x/crypto v0.22.0 // indirect + golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.24.0 // indirect golang.org/x/oauth2 v0.19.0 // indirect golang.org/x/sync v0.7.0 // indirect diff --git a/scripts/testvet/main.go b/scripts/testvet/main.go new file mode 100644 index 00000000..975e9e9e --- /dev/null +++ b/scripts/testvet/main.go @@ -0,0 +1,188 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package main + +import ( + "bufio" + "bytes" + "fmt" + "go/ast" + "go/token" + "io" + "os" + "strings" + "unicode" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/singlechecker" + + "github.com/prometheus/prometheus/promql/parser" +) + +func main() { + singlechecker.Main(loadAnalyzer) +} + +var loadAnalyzer = &analysis.Analyzer{ + Name: "loadvet", + Doc: "reports ill-formatted prometheus load directives or PromQL expressions", + Run: run, +} + +func run(pass *analysis.Pass) (interface{}, error) { + for _, file := range pass.Files { + if !strings.HasSuffix(file.Name.String(), "_test") { + continue + } + var stack []ast.Node + ast.Inspect(file, func(n ast.Node) bool { + defer func() { + if n == nil { + stack = stack[:len(stack)-1] + } else { + stack = append(stack, n) + } + }() + if n == nil || len(stack) == 0 { + return true + } + // only format expressions that are behind "query" or "load" keys + parent, ok := stack[len(stack)-1].(*ast.KeyValueExpr) + if !ok { + return true + } + p, ok := parent.Key.(*ast.Ident) + if !ok { + return true + } + switch strings.ToLower(p.Name) { + case "query", "load": + default: + return true + } + + s, ok := n.(*ast.BasicLit) + if !ok { + return true + } + if s.Kind != token.STRING { + return true + } + position := pass.Fset.Position(s.Pos()) + lineAtPosition, err := readLine(position.Filename, position.Line) + if err != nil { + return true + } + whiteSpace := leadingWhitespace(lineAtPosition) + cont := s.Value[1 : len(s.Value)-1] + // for consistency and ease of replacement, we replace the quotes with ` here + quote := s.Value[0] + switch { + case looksLikeLoadStmt(cont): + if formatted := formatLoadDirective(cont, whiteSpace); cont != formatted || quote != '`' { + pass.Report(analysis.Diagnostic{ + Pos: s.Pos(), + Message: "ill-formatted load directive found", + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: fmt.Sprintf("Should replace '%s' with '%s'", cont, formatted), + TextEdits: []analysis.TextEdit{ + { + Pos: s.Pos(), + End: s.End(), + NewText: []byte(fmt.Sprintf("%c%s%c", '`', formatted, '`')), + }, + }, + }, + }, + }) + return false + } + case looksLikePromQL(cont): + if formatted := formatPromQL(cont); cont != formatted || quote != '`' { + pass.Report(analysis.Diagnostic{ + Pos: s.Pos(), + Message: "ill-formatted promql found", + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: fmt.Sprintf("Should replace '%s' with '%s'", cont, formatted), + TextEdits: []analysis.TextEdit{ + { + Pos: s.Pos(), + End: s.End(), + NewText: []byte(fmt.Sprintf("%c%s%c", '`', formatted, '`')), + }, + }, + }, + }, + }) + return false + } + } + return true + }) + } + return nil, nil +} + +func looksLikeLoadStmt(cont string) bool { + return strings.HasPrefix(strings.TrimSpace(cont), "load") +} +func looksLikePromQL(cont string) bool { + _, err := parser.ParseExpr(cont) + return err == nil +} + +func formatLoadDirective(load, whiteSpace string) string { + var res strings.Builder + + sc := bufio.NewScanner(strings.NewReader(strings.TrimSpace(load))) + for i := 0; sc.Scan(); i++ { + if i == 0 { + res.WriteString(sc.Text()) + } else { + res.WriteString(whiteSpace) + res.WriteString(strings.Repeat(" ", 4)) + res.WriteString(strings.TrimSpace(sc.Text())) + } + res.WriteByte('\n') + } + + return strings.TrimSpace(res.String()) +} + +func formatPromQL(exprStr string) string { + expr, _ := parser.ParseExpr(exprStr) + pretty := expr.Pretty(0) + if strings.Count(pretty, "\n") > 0 { + return "\n" + pretty + } + return pretty +} + +func readLine(filename string, line int) (string, error) { + content, err := os.ReadFile(filename) + if err != nil { + return "", err + } + sc := bufio.NewScanner(bytes.NewReader(content)) + for i := 0; sc.Scan(); i++ { + if i == line-1 { + return sc.Text(), sc.Err() + } + } + return "", io.EOF +} + +func leadingWhitespace(line string) string { + var res strings.Builder + for _, r := range line { + if unicode.IsSpace(r) { + res.WriteRune(r) + } else { + break + } + } + return res.String() +}