cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.71.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/parser/utils/source_test.go

3859lines · modecode

1package utils_test
2
3import (
4 "strings"
5 "testing"
6
7 "github.com/google/go-cmp/cmp"
8 "github.com/google/go-cmp/cmp/cmpopts"
9 "github.com/stretchr/testify/require"
10
11 "github.com/cloudflare/pint/internal/parser"
12 "github.com/cloudflare/pint/internal/parser/utils"
13
14 "github.com/prometheus/prometheus/model/labels"
15 promParser "github.com/prometheus/prometheus/promql/parser"
16 "github.com/prometheus/prometheus/promql/parser/posrange"
17)
18
19func mustParse[T any](t *testing.T, s string, offset int) T {
20 m, err := promParser.ParseExpr(strings.Repeat(" ", offset) + s)
21 require.NoErrorf(t, err, "failed to parse vector selector: %s", s)
22 n, ok := m.(T)
23 require.True(t, ok, "failed to convert %q to %t\n", s, n)
24 return n
25}
26
27func TestLabelsSource(t *testing.T) {
28 type testCaseT struct {
29 expr string
30 output []utils.Source
31 }
32
33 testCases := []testCaseT{
34 {
35 expr: "1",
36 output: []utils.Source{
37 {
38 Type: utils.NumberSource,
39 Returns: promParser.ValueTypeScalar,
40 FixedLabels: true,
41 AlwaysReturns: true,
42 KnownReturn: true,
43 ReturnedNumber: 1,
44 ExcludeReason: map[string]utils.ExcludedLabel{
45 "": {
46 Reason: "This query returns a number value with no labels.",
47 },
48 },
49 },
50 },
51 },
52 {
53 expr: "1 / 5",
54 output: []utils.Source{
55 {
56 Type: utils.NumberSource,
57 Returns: promParser.ValueTypeScalar,
58 FixedLabels: true,
59 AlwaysReturns: true,
60 KnownReturn: true,
61 ReturnedNumber: 0.2,
62 ExcludeReason: map[string]utils.ExcludedLabel{
63 "": {
64 Reason: "This query returns a number value with no labels.",
65 },
66 },
67 },
68 },
69 },
70 {
71 expr: "(2 ^ 5) == bool 5",
72 output: []utils.Source{
73 {
74 Type: utils.NumberSource,
75 Returns: promParser.ValueTypeScalar,
76 FixedLabels: true,
77 AlwaysReturns: true,
78 KnownReturn: true,
79 IsDead: true,
80 IsDeadReason: "this query always evaluates to `32 == 5` which is not possible, so it will never return anything",
81 ReturnedNumber: 32,
82 ExcludeReason: map[string]utils.ExcludedLabel{
83 "": {
84 Reason: "This query returns a number value with no labels.",
85 },
86 },
87 IsConditional: true,
88 },
89 },
90 },
91 {
92 expr: "(2 ^ 5 + 11) % 5 <= bool 2",
93 output: []utils.Source{
94 {
95 Type: utils.NumberSource,
96 Returns: promParser.ValueTypeScalar,
97 FixedLabels: true,
98 AlwaysReturns: true,
99 KnownReturn: true,
100 IsDead: true,
101 IsDeadReason: "this query always evaluates to `3 <= 2` which is not possible, so it will never return anything",
102 ReturnedNumber: 3,
103 ExcludeReason: map[string]utils.ExcludedLabel{
104 "": {
105 Reason: "This query returns a number value with no labels.",
106 },
107 },
108 IsConditional: true,
109 },
110 },
111 },
112 {
113 expr: "(2 ^ 5 + 11) % 5 >= bool 20",
114 output: []utils.Source{
115 {
116 Type: utils.NumberSource,
117 Returns: promParser.ValueTypeScalar,
118 FixedLabels: true,
119 AlwaysReturns: true,
120 KnownReturn: true,
121 IsDead: true,
122 IsDeadReason: "this query always evaluates to `3 >= 20` which is not possible, so it will never return anything",
123 ReturnedNumber: 3,
124 ExcludeReason: map[string]utils.ExcludedLabel{
125 "": {
126 Reason: "This query returns a number value with no labels.",
127 },
128 },
129 IsConditional: true,
130 },
131 },
132 },
133 {
134 expr: "(2 ^ 5 + 11) % 5 <= bool 3",
135 output: []utils.Source{
136 {
137 Type: utils.NumberSource,
138 Returns: promParser.ValueTypeScalar,
139 FixedLabels: true,
140 AlwaysReturns: true,
141 KnownReturn: true,
142 ReturnedNumber: 3,
143 ExcludeReason: map[string]utils.ExcludedLabel{
144 "": {
145 Reason: "This query returns a number value with no labels.",
146 },
147 },
148 IsConditional: true,
149 },
150 },
151 },
152 {
153 expr: "(2 ^ 5 + 11) % 5 < bool 1",
154 output: []utils.Source{
155 {
156 Type: utils.NumberSource,
157 Returns: promParser.ValueTypeScalar,
158 FixedLabels: true,
159 AlwaysReturns: true,
160 KnownReturn: true,
161 IsDead: true,
162 IsDeadReason: "this query always evaluates to `3 < 1` which is not possible, so it will never return anything",
163 ReturnedNumber: 3,
164 ExcludeReason: map[string]utils.ExcludedLabel{
165 "": {
166 Reason: "This query returns a number value with no labels.",
167 },
168 },
169 IsConditional: true,
170 },
171 },
172 },
173 {
174 expr: "20 - 15 < bool 1",
175 output: []utils.Source{
176 {
177 Type: utils.NumberSource,
178 Returns: promParser.ValueTypeScalar,
179 FixedLabels: true,
180 AlwaysReturns: true,
181 KnownReturn: true,
182 IsDead: true,
183 IsDeadReason: "this query always evaluates to `5 < 1` which is not possible, so it will never return anything",
184 ReturnedNumber: 5,
185 ExcludeReason: map[string]utils.ExcludedLabel{
186 "": {
187 Reason: "This query returns a number value with no labels.",
188 },
189 },
190 IsConditional: true,
191 },
192 },
193 },
194 {
195 expr: "2 * 5",
196 output: []utils.Source{
197 {
198 Type: utils.NumberSource,
199 Returns: promParser.ValueTypeScalar,
200 FixedLabels: true,
201 AlwaysReturns: true,
202 KnownReturn: true,
203 ReturnedNumber: 10,
204 ExcludeReason: map[string]utils.ExcludedLabel{
205 "": {
206 Reason: "This query returns a number value with no labels.",
207 },
208 },
209 },
210 },
211 },
212 {
213 expr: "(foo or bar) * 5",
214 output: []utils.Source{
215 {
216 Type: utils.SelectorSource,
217 Returns: promParser.ValueTypeVector,
218 Operation: promParser.CardManyToMany.String(),
219 Selector: mustParse[*promParser.VectorSelector](t, "foo", 1),
220 },
221 {
222 Type: utils.SelectorSource,
223 Returns: promParser.ValueTypeVector,
224 Operation: promParser.CardManyToMany.String(),
225 Selector: mustParse[*promParser.VectorSelector](t, "bar", 8),
226 },
227 },
228 },
229 {
230 expr: "(foo or vector(2)) * 5",
231 output: []utils.Source{
232 {
233 Type: utils.SelectorSource,
234 Returns: promParser.ValueTypeVector,
235 Operation: promParser.CardManyToMany.String(),
236 Selector: mustParse[*promParser.VectorSelector](t, "foo", 1),
237 },
238 {
239 Type: utils.FuncSource,
240 Returns: promParser.ValueTypeVector,
241 Operation: "vector",
242 FixedLabels: true,
243 AlwaysReturns: true,
244 KnownReturn: true,
245 ReturnedNumber: 10,
246 ExcludeReason: map[string]utils.ExcludedLabel{
247 "": {
248 Reason: "Calling `vector()` will return a vector value with no labels.",
249 },
250 },
251 Call: mustParse[*promParser.Call](t, "vector(2)", 8),
252 },
253 },
254 },
255 {
256 expr: "(foo or vector(5)) * (vector(2) or bar)",
257 output: []utils.Source{
258 {
259 Type: utils.SelectorSource,
260 Returns: promParser.ValueTypeVector,
261 Operation: promParser.CardManyToMany.String(),
262 Selector: mustParse[*promParser.VectorSelector](t, "foo", 1),
263 Joins: []utils.Join{
264 {
265 Src: utils.Source{
266 Type: utils.FuncSource,
267 Returns: promParser.ValueTypeVector,
268 Operation: "vector",
269 FixedLabels: true,
270 AlwaysReturns: true,
271 KnownReturn: true,
272 ReturnedNumber: 2,
273 Call: mustParse[*promParser.Call](t, "vector(2)", 22),
274 ExcludeReason: map[string]utils.ExcludedLabel{
275 "": {
276 Reason: "Calling `vector()` will return a vector value with no labels.",
277 },
278 },
279 },
280 },
281 {
282 Src: utils.Source{
283 Type: utils.SelectorSource,
284 Returns: promParser.ValueTypeVector,
285 Operation: promParser.CardManyToMany.String(),
286 Selector: mustParse[*promParser.VectorSelector](t, "bar", 35),
287 IsDead: true,
288 IsDeadReason: "the left hand side always returs something and so the right hand side is never used",
289 },
290 },
291 },
292 },
293 {
294 Type: utils.FuncSource,
295 Returns: promParser.ValueTypeVector,
296 Operation: "vector",
297 FixedLabels: true,
298 AlwaysReturns: true,
299 KnownReturn: true,
300 ReturnedNumber: 10,
301 ExcludeReason: map[string]utils.ExcludedLabel{
302 "": {
303 Reason: "Calling `vector()` will return a vector value with no labels.",
304 },
305 },
306 Call: mustParse[*promParser.Call](t, "vector(5)", 8),
307 Joins: []utils.Join{
308 {
309 Src: utils.Source{
310 Type: utils.FuncSource,
311 Returns: promParser.ValueTypeVector,
312 Operation: "vector",
313 FixedLabels: true,
314 AlwaysReturns: true,
315 KnownReturn: true,
316 ReturnedNumber: 2,
317 Call: mustParse[*promParser.Call](t, "vector(2)", 22),
318 ExcludeReason: map[string]utils.ExcludedLabel{
319 "": {
320 Reason: "Calling `vector()` will return a vector value with no labels.",
321 },
322 },
323 },
324 },
325 {
326 Src: utils.Source{
327 Type: utils.SelectorSource,
328 Returns: promParser.ValueTypeVector,
329 Operation: promParser.CardManyToMany.String(),
330 Selector: mustParse[*promParser.VectorSelector](t, "bar", 35),
331 IsDead: true,
332 IsDeadReason: "the left hand side always returs something and so the right hand side is never used",
333 },
334 },
335 },
336 },
337 },
338 },
339 {
340 expr: `1 > bool 0`,
341 output: []utils.Source{
342 {
343 Type: utils.NumberSource,
344 Returns: promParser.ValueTypeScalar,
345 FixedLabels: true,
346 AlwaysReturns: true,
347 KnownReturn: true,
348 ReturnedNumber: 1,
349 ExcludeReason: map[string]utils.ExcludedLabel{
350 "": {
351 Reason: "This query returns a number value with no labels.",
352 },
353 },
354 IsConditional: true,
355 },
356 },
357 },
358 {
359 expr: `20 > bool 10`,
360 output: []utils.Source{
361 {
362 Type: utils.NumberSource,
363 Returns: promParser.ValueTypeScalar,
364 FixedLabels: true,
365 AlwaysReturns: true,
366 KnownReturn: true,
367 ReturnedNumber: 20,
368 ExcludeReason: map[string]utils.ExcludedLabel{
369 "": {
370 Reason: "This query returns a number value with no labels.",
371 },
372 },
373 IsConditional: true,
374 },
375 },
376 },
377 {
378 expr: `"test"`,
379 output: []utils.Source{
380 {
381 Type: utils.StringSource,
382 Returns: promParser.ValueTypeString,
383 FixedLabels: true,
384 AlwaysReturns: true,
385 ExcludeReason: map[string]utils.ExcludedLabel{
386 "": {
387 Reason: "This query returns a string value with no labels.",
388 },
389 },
390 },
391 },
392 },
393 {
394 expr: "foo",
395 output: []utils.Source{
396 {
397 Type: utils.SelectorSource,
398 Returns: promParser.ValueTypeVector,
399 Selector: mustParse[*promParser.VectorSelector](t, "foo", 0),
400 },
401 },
402 },
403 {
404 expr: "foo offset 5m",
405 output: []utils.Source{
406 {
407 Type: utils.SelectorSource,
408 Returns: promParser.ValueTypeVector,
409 Selector: mustParse[*promParser.VectorSelector](t, "foo offset 5m", 0),
410 },
411 },
412 },
413 {
414 expr: `foo{job="bar"}`,
415 output: []utils.Source{
416 {
417 Type: utils.SelectorSource,
418 Returns: promParser.ValueTypeVector,
419 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="bar"}`, 0),
420 GuaranteedLabels: []string{"job"},
421 },
422 },
423 },
424 {
425 expr: `foo{job=""}`,
426 output: []utils.Source{
427 {
428 Type: utils.SelectorSource,
429 Returns: promParser.ValueTypeVector,
430 Selector: mustParse[*promParser.VectorSelector](t, `foo{job=""}`, 0),
431 ExcludedLabels: []string{"job"},
432 ExcludeReason: map[string]utils.ExcludedLabel{
433 "job": {
434 Reason: "Query uses `{job=\"\"}` selector which will filter out any time series with the `job` label set.",
435 },
436 },
437 },
438 },
439 },
440 {
441 expr: `foo{job="bar"} or bar{job="foo"}`,
442 output: []utils.Source{
443 {
444 Type: utils.SelectorSource,
445 Returns: promParser.ValueTypeVector,
446 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="bar"}`, 0),
447 Operation: promParser.CardManyToMany.String(),
448 GuaranteedLabels: []string{"job"},
449 },
450 {
451 Type: utils.SelectorSource,
452 Returns: promParser.ValueTypeVector,
453 Selector: mustParse[*promParser.VectorSelector](t, `bar{job="foo"}`, 18),
454 Operation: promParser.CardManyToMany.String(),
455 GuaranteedLabels: []string{"job"},
456 },
457 },
458 },
459 {
460 expr: `foo{a="bar"} or bar{b="foo"}`,
461 output: []utils.Source{
462 {
463 Type: utils.SelectorSource,
464 Returns: promParser.ValueTypeVector,
465 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="bar"}`, 0),
466 Operation: promParser.CardManyToMany.String(),
467 GuaranteedLabels: []string{"a"},
468 },
469 {
470 Type: utils.SelectorSource,
471 Returns: promParser.ValueTypeVector,
472 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="foo"}`, 16),
473 Operation: promParser.CardManyToMany.String(),
474 GuaranteedLabels: []string{"b"},
475 },
476 },
477 },
478 {
479 expr: "foo[5m]",
480 output: []utils.Source{
481 {
482 Type: utils.SelectorSource,
483 Returns: promParser.ValueTypeVector, // FIXME Matrix ??
484 Selector: mustParse[*promParser.VectorSelector](t, "foo", 0),
485 },
486 },
487 },
488 {
489 expr: "prometheus_build_info[2m:1m]",
490 output: []utils.Source{
491 {
492 Type: utils.SelectorSource,
493 Returns: promParser.ValueTypeVector,
494 Selector: mustParse[*promParser.VectorSelector](t, "prometheus_build_info", 0),
495 },
496 },
497 },
498 {
499 expr: "deriv(rate(distance_covered_meters_total[1m])[5m:1m])",
500 output: []utils.Source{
501 {
502 Type: utils.FuncSource,
503 Returns: promParser.ValueTypeVector,
504 Operation: "deriv",
505 Selector: mustParse[*promParser.VectorSelector](t, "distance_covered_meters_total", 11),
506 Call: mustParse[*promParser.Call](t, "deriv(rate(distance_covered_meters_total[1m])[5m:1m])", 0),
507 },
508 },
509 },
510 {
511 expr: "foo - 1",
512 output: []utils.Source{
513 {
514 Type: utils.SelectorSource,
515 Returns: promParser.ValueTypeVector,
516 Selector: mustParse[*promParser.VectorSelector](t, "foo", 0),
517 },
518 },
519 },
520 {
521 expr: "foo / 5",
522 output: []utils.Source{
523 {
524 Type: utils.SelectorSource,
525 Returns: promParser.ValueTypeVector,
526 Selector: mustParse[*promParser.VectorSelector](t, "foo", 0),
527 },
528 },
529 },
530 {
531 expr: "-foo",
532 output: []utils.Source{
533 {
534 Type: utils.SelectorSource,
535 Returns: promParser.ValueTypeVector,
536 Selector: mustParse[*promParser.VectorSelector](t, "foo", 1),
537 },
538 },
539 },
540 {
541 expr: `sum(foo{job="myjob"})`,
542 output: []utils.Source{
543 {
544 Type: utils.AggregateSource,
545 Returns: promParser.ValueTypeVector,
546 Operation: "sum",
547 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
548 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"})`, 0),
549 FixedLabels: true,
550 ExcludeReason: map[string]utils.ExcludedLabel{
551 "": {
552 Reason: "Query is using aggregation that removes all labels.",
553 },
554 },
555 },
556 },
557 },
558 {
559 expr: `sum(count(foo{job="myjob"}) by(instance))`,
560 output: []utils.Source{
561 {
562 Type: utils.AggregateSource,
563 Returns: promParser.ValueTypeVector,
564 Operation: "sum",
565 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 10),
566 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(count(foo{job="myjob"}) by(instance))`, 0),
567 FixedLabels: true,
568 ExcludeReason: map[string]utils.ExcludedLabel{
569 "": {
570 Reason: "Query is using aggregation that removes all labels.",
571 },
572 },
573 },
574 },
575 },
576 {
577 expr: `sum(foo{job="myjob"}) > 20`,
578 output: []utils.Source{
579 {
580 Type: utils.AggregateSource,
581 Returns: promParser.ValueTypeVector,
582 Operation: "sum",
583 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
584 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"})`, 0),
585 FixedLabels: true,
586 ExcludeReason: map[string]utils.ExcludedLabel{
587 "": {
588 Reason: "Query is using aggregation that removes all labels.",
589 },
590 },
591 IsConditional: true,
592 },
593 },
594 },
595 {
596 expr: `sum(foo{job="myjob"}) without(job)`,
597 output: []utils.Source{
598 {
599 Type: utils.AggregateSource,
600 Returns: promParser.ValueTypeVector,
601 Operation: "sum",
602 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
603 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"}) without(job)`, 0),
604 ExcludedLabels: []string{"job"},
605 ExcludeReason: map[string]utils.ExcludedLabel{
606 "job": {
607 Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.",
608 },
609 },
610 },
611 },
612 },
613 {
614 expr: `sum(foo) by(job)`,
615 output: []utils.Source{
616 {
617 Type: utils.AggregateSource,
618 Returns: promParser.ValueTypeVector,
619 Operation: "sum",
620 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 4),
621 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo) by(job)`, 0),
622 IncludedLabels: []string{"job"},
623 FixedLabels: true,
624 ExcludeReason: map[string]utils.ExcludedLabel{
625 "": {
626 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
627 },
628 },
629 },
630 },
631 },
632 {
633 expr: `sum(foo{job="myjob"}) by(job)`,
634 output: []utils.Source{
635 {
636 Type: utils.AggregateSource,
637 Returns: promParser.ValueTypeVector,
638 Operation: "sum",
639 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
640 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"}) by(job)`, 0),
641 IncludedLabels: []string{"job"},
642 GuaranteedLabels: []string{"job"},
643 FixedLabels: true,
644 ExcludeReason: map[string]utils.ExcludedLabel{
645 "": {
646 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
647 },
648 },
649 },
650 },
651 },
652 {
653 expr: `abs(foo{job="myjob"} offset 5m)`,
654 output: []utils.Source{
655 {
656 Type: utils.FuncSource,
657 Returns: promParser.ValueTypeVector,
658 Operation: "abs",
659 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"} offset 5m`, 4),
660 Call: mustParse[*promParser.Call](t, `abs(foo{job="myjob"} offset 5m)`, 0),
661 GuaranteedLabels: []string{"job"},
662 },
663 },
664 },
665 {
666 expr: `abs(foo{job="myjob"} or bar{cluster="dev"})`,
667 output: []utils.Source{
668 {
669 Type: utils.FuncSource,
670 Returns: promParser.ValueTypeVector,
671 Operation: "abs",
672 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
673 GuaranteedLabels: []string{"job"},
674 Call: mustParse[*promParser.Call](t, `abs(foo{job="myjob"} or bar{cluster="dev"})`, 0),
675 },
676 {
677 Type: utils.FuncSource,
678 Returns: promParser.ValueTypeVector,
679 Operation: "abs",
680 Selector: mustParse[*promParser.VectorSelector](t, `bar{cluster="dev"}`, 24),
681 Call: mustParse[*promParser.Call](t, `abs(foo{job="myjob"} or bar{cluster="dev"})`, 0),
682 GuaranteedLabels: []string{"cluster"},
683 },
684 },
685 },
686 {
687 expr: `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`,
688 output: []utils.Source{
689 {
690 Type: utils.AggregateSource,
691 Returns: promParser.ValueTypeVector,
692 Operation: "sum",
693 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
694 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`, 0),
695 GuaranteedLabels: []string{"job"},
696 ExcludedLabels: []string{"instance"},
697 ExcludeReason: map[string]utils.ExcludedLabel{
698 "instance": {
699 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
700 },
701 },
702 },
703 {
704 Type: utils.AggregateSource,
705 Returns: promParser.ValueTypeVector,
706 Operation: "sum",
707 Selector: mustParse[*promParser.VectorSelector](t, `bar{cluster="dev"}`, 24),
708 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`, 0),
709 GuaranteedLabels: []string{"cluster"},
710 ExcludedLabels: []string{"instance"},
711 ExcludeReason: map[string]utils.ExcludedLabel{
712 "instance": {
713 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
714 },
715 },
716 },
717 },
718 },
719 {
720 expr: `sum(foo{job="myjob"}) without(instance)`,
721 output: []utils.Source{
722 {
723 Type: utils.AggregateSource,
724 Returns: promParser.ValueTypeVector,
725 Operation: "sum",
726 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
727 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"}) without(instance)`, 0),
728 GuaranteedLabels: []string{"job"},
729 ExcludedLabels: []string{"instance"},
730 ExcludeReason: map[string]utils.ExcludedLabel{
731 "instance": {
732 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
733 },
734 },
735 },
736 },
737 },
738 {
739 expr: `min(foo{job="myjob"}) / max(foo{job="myjob"})`,
740 output: []utils.Source{
741 {
742 Type: utils.AggregateSource,
743 Returns: promParser.ValueTypeVector,
744 Operation: "min",
745 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
746 Aggregation: mustParse[*promParser.AggregateExpr](t, `min(foo{job="myjob"})`, 0),
747 FixedLabels: true,
748 ExcludeReason: map[string]utils.ExcludedLabel{
749 "": {
750 Reason: "Query is using aggregation that removes all labels.",
751 },
752 },
753 Joins: []utils.Join{
754 {
755 Src: utils.Source{
756 Type: utils.AggregateSource,
757 Operation: "max",
758 Returns: promParser.ValueTypeVector,
759 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 28),
760 Aggregation: mustParse[*promParser.AggregateExpr](t, `max(foo{job="myjob"})`, 24),
761 FixedLabels: true,
762 ExcludeReason: map[string]utils.ExcludedLabel{
763 "": {
764 Reason: "Query is using aggregation that removes all labels.",
765 },
766 },
767 },
768 },
769 },
770 },
771 },
772 },
773 {
774 expr: `max(foo{job="myjob"}) / min(foo{job="myjob"})`,
775 output: []utils.Source{
776 {
777 Type: utils.AggregateSource,
778 Returns: promParser.ValueTypeVector,
779 Operation: "max",
780 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
781 Aggregation: mustParse[*promParser.AggregateExpr](t, `max(foo{job="myjob"})`, 0),
782 FixedLabels: true,
783 ExcludeReason: map[string]utils.ExcludedLabel{
784 "": {
785 Reason: "Query is using aggregation that removes all labels.",
786 },
787 },
788 Joins: []utils.Join{
789 {
790 Src: utils.Source{
791 Type: utils.AggregateSource,
792 Operation: "min",
793 Returns: promParser.ValueTypeVector,
794 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 28),
795 Aggregation: mustParse[*promParser.AggregateExpr](t, `min(foo{job="myjob"})`, 24),
796 FixedLabels: true,
797 ExcludeReason: map[string]utils.ExcludedLabel{
798 "": {
799 Reason: "Query is using aggregation that removes all labels.",
800 },
801 },
802 },
803 },
804 },
805 },
806 },
807 },
808 {
809 expr: `avg(foo{job="myjob"}) by(job)`,
810 output: []utils.Source{
811 {
812 Type: utils.AggregateSource,
813 Returns: promParser.ValueTypeVector,
814 Operation: "avg",
815 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 4),
816 Aggregation: mustParse[*promParser.AggregateExpr](t, `avg(foo{job="myjob"}) by(job)`, 0),
817 GuaranteedLabels: []string{"job"},
818 IncludedLabels: []string{"job"},
819 FixedLabels: true,
820 ExcludeReason: map[string]utils.ExcludedLabel{
821 "": {
822 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
823 },
824 },
825 },
826 },
827 },
828 {
829 expr: `group(foo) by(job)`,
830 output: []utils.Source{
831 {
832 Type: utils.AggregateSource,
833 Returns: promParser.ValueTypeVector,
834 Operation: "group",
835 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 6),
836 Aggregation: mustParse[*promParser.AggregateExpr](t, `group(foo) by(job)`, 0),
837 IncludedLabels: []string{"job"},
838 FixedLabels: true,
839 ExcludeReason: map[string]utils.ExcludedLabel{
840 "": {
841 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
842 },
843 },
844 },
845 },
846 },
847 {
848 expr: `stddev(rate(foo[5m]))`,
849 output: []utils.Source{
850 {
851 Type: utils.AggregateSource,
852 Returns: promParser.ValueTypeVector,
853 Operation: "stddev",
854 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 12),
855 Call: mustParse[*promParser.Call](t, "rate(foo[5m])", 7),
856 Aggregation: mustParse[*promParser.AggregateExpr](t, `stddev(rate(foo[5m]))`, 0),
857 FixedLabels: true,
858 ExcludeReason: map[string]utils.ExcludedLabel{
859 "": {
860 Reason: "Query is using aggregation that removes all labels.",
861 },
862 },
863 },
864 },
865 },
866 {
867 expr: `stdvar(rate(foo[5m]))`,
868 output: []utils.Source{
869 {
870 Type: utils.AggregateSource,
871 Returns: promParser.ValueTypeVector,
872 Operation: "stdvar",
873 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 12),
874 Call: mustParse[*promParser.Call](t, "rate(foo[5m])", 7),
875 Aggregation: mustParse[*promParser.AggregateExpr](t, `stdvar(rate(foo[5m]))`, 0),
876 FixedLabels: true,
877 ExcludeReason: map[string]utils.ExcludedLabel{
878 "": {
879 Reason: "Query is using aggregation that removes all labels.",
880 },
881 },
882 },
883 },
884 },
885 {
886 expr: `stddev_over_time(foo[5m])`,
887 output: []utils.Source{
888 {
889 Type: utils.FuncSource,
890 Returns: promParser.ValueTypeVector,
891 Operation: "stddev_over_time",
892 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 17),
893 Call: mustParse[*promParser.Call](t, `stddev_over_time(foo[5m])`, 0),
894 },
895 },
896 },
897 {
898 expr: `stdvar_over_time(foo[5m])`,
899 output: []utils.Source{
900 {
901 Type: utils.FuncSource,
902 Returns: promParser.ValueTypeVector,
903 Operation: "stdvar_over_time",
904 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 17),
905 Call: mustParse[*promParser.Call](t, `stdvar_over_time(foo[5m])`, 0),
906 },
907 },
908 },
909 {
910 expr: `quantile(0.9, rate(foo[5m]))`,
911 output: []utils.Source{
912 {
913 Type: utils.AggregateSource,
914 Returns: promParser.ValueTypeVector,
915 Operation: "quantile",
916 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 19),
917 Call: mustParse[*promParser.Call](t, "rate(foo[5m])", 14),
918 Aggregation: mustParse[*promParser.AggregateExpr](t, `quantile(0.9, rate(foo[5m]))`, 0),
919 FixedLabels: true,
920 ExcludeReason: map[string]utils.ExcludedLabel{
921 "": {
922 Reason: "Query is using aggregation that removes all labels.",
923 },
924 },
925 },
926 },
927 },
928 {
929 expr: `count_values("version", build_version)`,
930 output: []utils.Source{
931 {
932 Type: utils.AggregateSource,
933 Returns: promParser.ValueTypeVector,
934 Operation: "count_values",
935 Selector: mustParse[*promParser.VectorSelector](t, `build_version`, 24),
936 Aggregation: mustParse[*promParser.AggregateExpr](t, `count_values("version", build_version)`, 0),
937 GuaranteedLabels: []string{"version"},
938 IncludedLabels: []string{"version"},
939 FixedLabels: true,
940 ExcludeReason: map[string]utils.ExcludedLabel{
941 "": {
942 Reason: "Query is using aggregation that removes all labels.",
943 },
944 },
945 },
946 },
947 },
948 {
949 expr: `count_values("version", build_version) without(job)`,
950 output: []utils.Source{
951 {
952 Type: utils.AggregateSource,
953 Returns: promParser.ValueTypeVector,
954 Operation: "count_values",
955 Selector: mustParse[*promParser.VectorSelector](t, `build_version`, 24),
956 Aggregation: mustParse[*promParser.AggregateExpr](t, `count_values("version", build_version) without(job)`, 0),
957 IncludedLabels: []string{"version"},
958 GuaranteedLabels: []string{"version"},
959 ExcludedLabels: []string{"job"},
960 ExcludeReason: map[string]utils.ExcludedLabel{
961 "job": {
962 Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.",
963 },
964 },
965 },
966 },
967 },
968 {
969 expr: `count_values("version", build_version{job="foo"}) without(job)`,
970 output: []utils.Source{
971 {
972 Type: utils.AggregateSource,
973 Returns: promParser.ValueTypeVector,
974 Operation: "count_values",
975 Selector: mustParse[*promParser.VectorSelector](t, `build_version{job="foo"}`, 24),
976 Aggregation: mustParse[*promParser.AggregateExpr](t, `count_values("version", build_version{job="foo"}) without(job)`, 0),
977 IncludedLabels: []string{"version"},
978 GuaranteedLabels: []string{"version"},
979 ExcludedLabels: []string{"job"},
980 ExcludeReason: map[string]utils.ExcludedLabel{
981 "job": {
982 Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.",
983 },
984 },
985 },
986 },
987 },
988 {
989 expr: `count_values("version", build_version) by(job)`,
990 output: []utils.Source{
991 {
992 Type: utils.AggregateSource,
993 Returns: promParser.ValueTypeVector,
994 Operation: "count_values",
995 Selector: mustParse[*promParser.VectorSelector](t, `build_version`, 24),
996 Aggregation: mustParse[*promParser.AggregateExpr](t, `count_values("version", build_version) by(job)`, 0),
997 GuaranteedLabels: []string{"version"},
998 IncludedLabels: []string{"job", "version"},
999 FixedLabels: true,
1000 ExcludeReason: map[string]utils.ExcludedLabel{
1001 "": {
1002 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
1003 },
1004 },
1005 },
1006 },
1007 },
1008 {
1009 expr: `topk(10, foo{job="myjob"}) > 10`,
1010 output: []utils.Source{
1011 {
1012 Type: utils.AggregateSource,
1013 Returns: promParser.ValueTypeVector,
1014 Operation: "topk",
1015 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 9),
1016 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo{job="myjob"})`, 0),
1017 GuaranteedLabels: []string{"job"},
1018 IsConditional: true,
1019 },
1020 },
1021 },
1022 {
1023 expr: `topk(10, foo or bar)`,
1024 output: []utils.Source{
1025 {
1026 Type: utils.AggregateSource,
1027 Returns: promParser.ValueTypeVector,
1028 Operation: "topk",
1029 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 9),
1030 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo or bar)`, 0),
1031 },
1032 {
1033 Type: utils.AggregateSource,
1034 Operation: "topk",
1035 Returns: promParser.ValueTypeVector,
1036 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 16),
1037 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo or bar)`, 0),
1038 },
1039 },
1040 },
1041 {
1042 expr: `rate(foo[10m])`,
1043 output: []utils.Source{
1044 {
1045 Type: utils.FuncSource,
1046 Returns: promParser.ValueTypeVector,
1047 Operation: "rate",
1048 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 5),
1049 Call: mustParse[*promParser.Call](t, `rate(foo[10m])`, 0),
1050 },
1051 },
1052 },
1053 {
1054 expr: `sum(rate(foo[10m])) without(instance)`,
1055 output: []utils.Source{
1056 {
1057 Type: utils.AggregateSource,
1058 Returns: promParser.ValueTypeVector,
1059 Operation: "sum",
1060 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 9),
1061 Call: mustParse[*promParser.Call](t, "rate(foo[10m])", 4),
1062 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(rate(foo[10m])) without(instance)`, 0),
1063 ExcludedLabels: []string{"instance"},
1064 ExcludeReason: map[string]utils.ExcludedLabel{
1065 "instance": {
1066 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
1067 },
1068 },
1069 },
1070 },
1071 },
1072 {
1073 expr: `foo{job="foo"} / bar`,
1074 output: []utils.Source{
1075 {
1076 Type: utils.SelectorSource,
1077 Returns: promParser.ValueTypeVector,
1078 Operation: promParser.CardOneToOne.String(),
1079 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo"}`, 0),
1080 GuaranteedLabels: []string{"job"},
1081 Joins: []utils.Join{
1082 {
1083 Src: utils.Source{
1084 Type: utils.SelectorSource,
1085 Returns: promParser.ValueTypeVector,
1086 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 17),
1087 },
1088 },
1089 },
1090 },
1091 },
1092 },
1093 {
1094 expr: `foo{job="foo"} * on(instance) bar`,
1095 output: []utils.Source{
1096 {
1097 Type: utils.SelectorSource,
1098 Returns: promParser.ValueTypeVector,
1099 Operation: promParser.CardOneToOne.String(),
1100 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo"}`, 0),
1101 IncludedLabels: []string{"instance"},
1102 FixedLabels: true,
1103 ExcludeReason: map[string]utils.ExcludedLabel{
1104 "": {
1105 Reason: "Query is using one-to-one vector matching with `on(instance)`, only labels included inside `on(...)` will be present on the results.",
1106 },
1107 },
1108 Joins: []utils.Join{
1109 {
1110 Src: utils.Source{
1111 Type: utils.SelectorSource,
1112 Returns: promParser.ValueTypeVector,
1113 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 30),
1114 },
1115 },
1116 },
1117 },
1118 },
1119 },
1120 {
1121 expr: `foo{job="foo"} * on(instance) group_left(bar) bar`,
1122 output: []utils.Source{
1123 {
1124 Type: utils.SelectorSource,
1125 Returns: promParser.ValueTypeVector,
1126 Operation: promParser.CardManyToOne.String(),
1127 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo"}`, 0),
1128 IncludedLabels: []string{"bar", "instance"},
1129 GuaranteedLabels: []string{"job"},
1130 Joins: []utils.Join{
1131 {
1132 Src: utils.Source{
1133 Type: utils.SelectorSource,
1134 Returns: promParser.ValueTypeVector,
1135 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 46),
1136 },
1137 },
1138 },
1139 },
1140 },
1141 },
1142 {
1143 expr: `foo{job="foo"} * on(instance) group_left(cluster) bar{cluster="bar", ignored="true"}`,
1144 output: []utils.Source{
1145 {
1146 Type: utils.SelectorSource,
1147 Returns: promParser.ValueTypeVector,
1148 Operation: promParser.CardManyToOne.String(),
1149 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo"}`, 0),
1150 IncludedLabels: []string{"cluster", "instance"},
1151 GuaranteedLabels: []string{"job"},
1152 Joins: []utils.Join{
1153 {
1154 Src: utils.Source{
1155 Type: utils.SelectorSource,
1156 Returns: promParser.ValueTypeVector,
1157 Selector: mustParse[*promParser.VectorSelector](t, `bar{cluster="bar", ignored="true"}`, 50),
1158 GuaranteedLabels: []string{"cluster", "ignored"},
1159 },
1160 },
1161 },
1162 },
1163 },
1164 },
1165 {
1166 expr: `foo{job="foo", ignored="true"} * on(instance) group_right(job) bar{cluster="bar"}`,
1167 output: []utils.Source{
1168 {
1169 Type: utils.SelectorSource,
1170 Returns: promParser.ValueTypeVector,
1171 Operation: promParser.CardOneToMany.String(),
1172 Selector: mustParse[*promParser.VectorSelector](t, `bar{cluster="bar"}`, 63),
1173 IncludedLabels: []string{"job", "instance"},
1174 GuaranteedLabels: []string{"cluster"},
1175 Joins: []utils.Join{
1176 {
1177 Src: utils.Source{
1178 Type: utils.SelectorSource,
1179 Returns: promParser.ValueTypeVector,
1180 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo", ignored="true"}`, 0),
1181 GuaranteedLabels: []string{"job", "ignored"},
1182 },
1183 },
1184 },
1185 },
1186 },
1187 },
1188 {
1189 expr: `count(foo / bar)`,
1190 output: []utils.Source{
1191 {
1192 Type: utils.AggregateSource,
1193 Returns: promParser.ValueTypeVector,
1194 Operation: "count",
1195 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 6),
1196 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(foo / bar)`, 0),
1197 FixedLabels: true,
1198 ExcludeReason: map[string]utils.ExcludedLabel{
1199 "": {
1200 Reason: "Query is using aggregation that removes all labels.",
1201 },
1202 },
1203 Joins: []utils.Join{
1204 {
1205 Src: utils.Source{
1206 Type: utils.SelectorSource,
1207 Returns: promParser.ValueTypeVector,
1208 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 12),
1209 },
1210 },
1211 },
1212 },
1213 },
1214 },
1215 {
1216 expr: `count(up{job="a"} / on () up{job="b"})`,
1217 output: []utils.Source{
1218 {
1219 Type: utils.AggregateSource,
1220 Returns: promParser.ValueTypeVector,
1221 Operation: "count",
1222 Selector: mustParse[*promParser.VectorSelector](t, `up{job="a"}`, 6),
1223 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(up{job="a"} / on () up{job="b"})`, 0),
1224 FixedLabels: true,
1225 ExcludeReason: map[string]utils.ExcludedLabel{
1226 "": {
1227 Reason: "Query is using aggregation that removes all labels.",
1228 },
1229 },
1230 Joins: []utils.Join{
1231 {
1232 Src: utils.Source{
1233 Type: utils.SelectorSource,
1234 Returns: promParser.ValueTypeVector,
1235 Selector: mustParse[*promParser.VectorSelector](t, `up{job="b"}`, 26),
1236 GuaranteedLabels: []string{"job"},
1237 },
1238 },
1239 },
1240 },
1241 },
1242 },
1243 {
1244 expr: `count(up{job="a"} / on (env) up{job="b"})`,
1245 output: []utils.Source{
1246 {
1247 Type: utils.AggregateSource,
1248 Returns: promParser.ValueTypeVector,
1249 Operation: "count",
1250 Selector: mustParse[*promParser.VectorSelector](t, `up{job="a"}`, 6),
1251 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(up{job="a"} / on (env) up{job="b"})`, 0),
1252 FixedLabels: true,
1253 ExcludeReason: map[string]utils.ExcludedLabel{
1254 "": {
1255 Reason: "Query is using aggregation that removes all labels.",
1256 },
1257 },
1258 Joins: []utils.Join{
1259 {
1260 Src: utils.Source{
1261 Type: utils.SelectorSource,
1262 Returns: promParser.ValueTypeVector,
1263 Selector: mustParse[*promParser.VectorSelector](t, `up{job="b"}`, 29),
1264 GuaranteedLabels: []string{"job"},
1265 },
1266 },
1267 },
1268 },
1269 },
1270 },
1271 {
1272 expr: `foo{job="foo", instance="1"} and bar`,
1273 output: []utils.Source{
1274 {
1275 Type: utils.SelectorSource,
1276 Returns: promParser.ValueTypeVector,
1277 Operation: promParser.CardManyToMany.String(),
1278 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo", instance="1"}`, 0),
1279 GuaranteedLabels: []string{"job", "instance"},
1280 Joins: []utils.Join{
1281 {
1282 Src: utils.Source{
1283 Type: utils.SelectorSource,
1284 Returns: promParser.ValueTypeVector,
1285 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 33),
1286 },
1287 },
1288 },
1289 },
1290 },
1291 },
1292 {
1293 expr: `foo{job="foo", instance="1"} and on(cluster) bar`,
1294 output: []utils.Source{
1295 {
1296 Type: utils.SelectorSource,
1297 Returns: promParser.ValueTypeVector,
1298 Operation: promParser.CardManyToMany.String(),
1299 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo", instance="1"}`, 0),
1300 IncludedLabels: []string{"cluster"},
1301 GuaranteedLabels: []string{"job", "instance"},
1302 Joins: []utils.Join{
1303 {
1304 Src: utils.Source{
1305 Type: utils.SelectorSource,
1306 Returns: promParser.ValueTypeVector,
1307 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 45),
1308 },
1309 },
1310 },
1311 },
1312 },
1313 },
1314 {
1315 expr: `topk(10, foo)`,
1316 output: []utils.Source{
1317 {
1318 Type: utils.AggregateSource,
1319 Returns: promParser.ValueTypeVector,
1320 Operation: "topk",
1321 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 9),
1322 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo)`, 0),
1323 },
1324 },
1325 },
1326 {
1327 expr: `topk(10, foo) without(cluster)`,
1328 output: []utils.Source{
1329 {
1330 Type: utils.AggregateSource,
1331 Returns: promParser.ValueTypeVector,
1332 Operation: "topk",
1333 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 9),
1334 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo) without(cluster)`, 0),
1335 },
1336 },
1337 },
1338 {
1339 expr: `topk(10, foo) by(cluster)`,
1340 output: []utils.Source{
1341 {
1342 Type: utils.AggregateSource,
1343 Returns: promParser.ValueTypeVector,
1344 Operation: "topk",
1345 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 9),
1346 Aggregation: mustParse[*promParser.AggregateExpr](t, `topk(10, foo) by(cluster)`, 0),
1347 },
1348 },
1349 },
1350 {
1351 expr: `bottomk(10, sum(rate(foo[5m])) without(job))`,
1352 output: []utils.Source{
1353 {
1354 Type: utils.AggregateSource,
1355 Returns: promParser.ValueTypeVector,
1356 Operation: "bottomk",
1357 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 21),
1358 Call: mustParse[*promParser.Call](t, "rate(foo[5m])", 16),
1359 Aggregation: mustParse[*promParser.AggregateExpr](t, `bottomk(10, sum(rate(foo[5m])) without(job))`, 0),
1360 ExcludedLabels: []string{"job"},
1361 ExcludeReason: map[string]utils.ExcludedLabel{
1362 "job": {
1363 Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.",
1364 },
1365 },
1366 },
1367 },
1368 },
1369 {
1370 expr: `foo or bar`,
1371 output: []utils.Source{
1372 {
1373 Type: utils.SelectorSource,
1374 Returns: promParser.ValueTypeVector,
1375 Operation: promParser.CardManyToMany.String(),
1376 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 0),
1377 },
1378 {
1379 Type: utils.SelectorSource,
1380 Returns: promParser.ValueTypeVector,
1381 Operation: promParser.CardManyToMany.String(),
1382 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 7),
1383 },
1384 },
1385 },
1386 {
1387 expr: `foo or bar or baz`,
1388 output: []utils.Source{
1389 {
1390 Type: utils.SelectorSource,
1391 Returns: promParser.ValueTypeVector,
1392 Operation: promParser.CardManyToMany.String(),
1393 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 0),
1394 },
1395 {
1396 Type: utils.SelectorSource,
1397 Returns: promParser.ValueTypeVector,
1398 Operation: promParser.CardManyToMany.String(),
1399 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 7),
1400 },
1401 {
1402 Type: utils.SelectorSource,
1403 Returns: promParser.ValueTypeVector,
1404 Operation: promParser.CardManyToMany.String(),
1405 Selector: mustParse[*promParser.VectorSelector](t, `baz`, 14),
1406 },
1407 },
1408 },
1409 {
1410 expr: `(foo or bar) or baz`,
1411 output: []utils.Source{
1412 {
1413 Type: utils.SelectorSource,
1414 Returns: promParser.ValueTypeVector,
1415 Operation: promParser.CardManyToMany.String(),
1416 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 1),
1417 },
1418 {
1419 Type: utils.SelectorSource,
1420 Returns: promParser.ValueTypeVector,
1421 Operation: promParser.CardManyToMany.String(),
1422 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 8),
1423 },
1424 {
1425 Type: utils.SelectorSource,
1426 Returns: promParser.ValueTypeVector,
1427 Operation: promParser.CardManyToMany.String(),
1428 Selector: mustParse[*promParser.VectorSelector](t, `baz`, 16),
1429 },
1430 },
1431 },
1432 {
1433 expr: `foo unless bar`,
1434 output: []utils.Source{
1435 {
1436 Type: utils.SelectorSource,
1437 Returns: promParser.ValueTypeVector,
1438 Operation: promParser.CardManyToMany.String(),
1439 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 0),
1440 Unless: []utils.Join{
1441 {
1442 Src: utils.Source{
1443 Type: utils.SelectorSource,
1444 Returns: promParser.ValueTypeVector,
1445 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 11),
1446 },
1447 },
1448 },
1449 },
1450 },
1451 },
1452 {
1453 expr: `foo unless bar > 5`,
1454 output: []utils.Source{
1455 {
1456 Type: utils.SelectorSource,
1457 Returns: promParser.ValueTypeVector,
1458 Operation: promParser.CardManyToMany.String(),
1459 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 0),
1460 Unless: []utils.Join{
1461 {
1462 Src: utils.Source{
1463 Type: utils.SelectorSource,
1464 Returns: promParser.ValueTypeVector,
1465 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 11),
1466 IsConditional: true,
1467 },
1468 },
1469 },
1470 },
1471 },
1472 },
1473 {
1474 expr: `foo unless bar unless baz`,
1475 output: []utils.Source{
1476 {
1477 Type: utils.SelectorSource,
1478 Returns: promParser.ValueTypeVector,
1479 Operation: promParser.CardManyToMany.String(),
1480 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 0),
1481 Unless: []utils.Join{
1482 {
1483 Src: utils.Source{
1484 Type: utils.SelectorSource,
1485 Returns: promParser.ValueTypeVector,
1486 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 11),
1487 },
1488 },
1489 {
1490 Src: utils.Source{
1491 Type: utils.SelectorSource,
1492 Returns: promParser.ValueTypeVector,
1493 Selector: mustParse[*promParser.VectorSelector](t, `baz`, 22),
1494 },
1495 },
1496 },
1497 },
1498 },
1499 },
1500 {
1501 expr: `count(sum(up{job="foo", cluster="dev"}) by(job, cluster) == 0) without(job, cluster)`,
1502 output: []utils.Source{
1503 {
1504 Type: utils.AggregateSource,
1505 Returns: promParser.ValueTypeVector,
1506 Operation: "count",
1507 Selector: mustParse[*promParser.VectorSelector](t, `up{job="foo", cluster="dev"}`, 10),
1508 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(sum(up{job="foo", cluster="dev"}) by(job, cluster) == 0) without(job, cluster)`, 0),
1509 ExcludedLabels: []string{"job", "cluster"}, // FIXME empty
1510 FixedLabels: true,
1511 ExcludeReason: map[string]utils.ExcludedLabel{
1512 "": {
1513 Reason: "Query is using aggregation with `by(job, cluster)`, only labels included inside `by(...)` will be present on the results.",
1514 },
1515 "job": {
1516 Reason: "Query is using aggregation with `without(job, cluster)`, all labels included inside `without(...)` will be removed from the results.",
1517 },
1518 "cluster": {
1519 Reason: "Query is using aggregation with `without(job, cluster)`, all labels included inside `without(...)` will be removed from the results.",
1520 },
1521 },
1522 IsConditional: true,
1523 },
1524 },
1525 },
1526 {
1527 expr: "year()",
1528 output: []utils.Source{
1529 {
1530 Type: utils.FuncSource,
1531 Returns: promParser.ValueTypeVector,
1532 Operation: "year",
1533 FixedLabels: true,
1534 AlwaysReturns: true,
1535 ExcludeReason: map[string]utils.ExcludedLabel{
1536 "": {
1537 Reason: "Calling `year()` with no arguments will return an empty time series with no labels.",
1538 },
1539 },
1540 Call: mustParse[*promParser.Call](t, `year()`, 0),
1541 },
1542 },
1543 },
1544 {
1545 expr: "year(foo)",
1546 output: []utils.Source{
1547 {
1548 Type: utils.FuncSource,
1549 Returns: promParser.ValueTypeVector,
1550 Operation: "year",
1551 Selector: mustParse[*promParser.VectorSelector](t, "foo", 5),
1552 Call: mustParse[*promParser.Call](t, `year(foo)`, 0),
1553 },
1554 },
1555 },
1556 {
1557 expr: `label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")`,
1558 output: []utils.Source{
1559 {
1560 Type: utils.FuncSource,
1561 Returns: promParser.ValueTypeVector,
1562 Operation: "label_join",
1563 Selector: mustParse[*promParser.VectorSelector](t, `up{job="api-server",src1="a",src2="b",src3="c"}`, 11),
1564 GuaranteedLabels: []string{"job", "src1", "src2", "src3", "foo"},
1565 Call: mustParse[*promParser.Call](t, `label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")`, 0),
1566 },
1567 },
1568 },
1569 {
1570 expr: `
1571(
1572 sum(foo:sum > 0) without(notify)
1573 * on(job) group_left(notify)
1574 job:notify
1575)
1576and on(job)
1577sum(foo:count) by(job) > 20`,
1578 output: []utils.Source{
1579 {
1580 Type: utils.AggregateSource,
1581 Returns: promParser.ValueTypeVector,
1582 Operation: "sum",
1583 Selector: mustParse[*promParser.VectorSelector](t, `foo:sum`, 8),
1584 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo:sum > 0) without(notify)`, 4),
1585 IncludedLabels: []string{"notify", "job"},
1586 ExcludeReason: map[string]utils.ExcludedLabel{},
1587 IsConditional: true,
1588 Joins: []utils.Join{
1589 {
1590 Src: utils.Source{
1591 Type: utils.SelectorSource,
1592 Returns: promParser.ValueTypeVector,
1593 Selector: mustParse[*promParser.VectorSelector](t, `job:notify`, 68),
1594 },
1595 },
1596 {
1597 Src: utils.Source{
1598 Type: utils.AggregateSource,
1599 Returns: promParser.ValueTypeVector,
1600 Operation: "sum",
1601 Selector: mustParse[*promParser.VectorSelector](t, `foo:count`, 97),
1602 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo:count) by(job)`, 93),
1603 IncludedLabels: []string{"job"},
1604 FixedLabels: true,
1605 ExcludeReason: map[string]utils.ExcludedLabel{
1606 "": {
1607 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
1608 },
1609 },
1610 IsConditional: true,
1611 },
1612 },
1613 },
1614 },
1615 },
1616 },
1617 {
1618 expr: `container_file_descriptors / on (instance, app_name) container_ulimits_soft{ulimit="max_open_files"}`,
1619 output: []utils.Source{
1620 {
1621 Type: utils.SelectorSource,
1622 Returns: promParser.ValueTypeVector,
1623 Operation: promParser.CardOneToOne.String(),
1624 Selector: mustParse[*promParser.VectorSelector](t, `container_file_descriptors`, 0),
1625 IncludedLabels: []string{"instance", "app_name"},
1626 FixedLabels: true,
1627 ExcludeReason: map[string]utils.ExcludedLabel{
1628 "": {
1629 Reason: "Query is using one-to-one vector matching with `on(instance, app_name)`, only labels included inside `on(...)` will be present on the results.",
1630 },
1631 },
1632 Joins: []utils.Join{
1633 {
1634 Src: utils.Source{
1635 Type: utils.SelectorSource,
1636 Returns: promParser.ValueTypeVector,
1637 Selector: mustParse[*promParser.VectorSelector](t, `container_ulimits_soft{ulimit="max_open_files"}`, 53),
1638 GuaranteedLabels: []string{"ulimit"},
1639 },
1640 },
1641 },
1642 },
1643 },
1644 },
1645 {
1646 expr: `container_file_descriptors / on (instance, app_name) group_left() container_ulimits_soft{ulimit="max_open_files"}`,
1647 output: []utils.Source{
1648 {
1649 Type: utils.SelectorSource,
1650 Returns: promParser.ValueTypeVector,
1651 Operation: promParser.CardManyToOne.String(),
1652 Selector: mustParse[*promParser.VectorSelector](t, `container_file_descriptors`, 0),
1653 IncludedLabels: []string{"instance", "app_name"},
1654 Joins: []utils.Join{
1655 {
1656 Src: utils.Source{
1657 Type: utils.SelectorSource,
1658 Returns: promParser.ValueTypeVector,
1659 Selector: mustParse[*promParser.VectorSelector](t, `container_ulimits_soft{ulimit="max_open_files"}`, 66),
1660 GuaranteedLabels: []string{"ulimit"},
1661 },
1662 },
1663 },
1664 },
1665 },
1666 },
1667 {
1668 expr: `absent(foo{job="bar"})`,
1669 output: []utils.Source{
1670 {
1671 Type: utils.FuncSource,
1672 Returns: promParser.ValueTypeVector,
1673 Operation: "absent",
1674 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="bar"}`, 7),
1675 IncludedLabels: []string{"job"},
1676 GuaranteedLabels: []string{"job"},
1677 FixedLabels: true,
1678 ExcludeReason: map[string]utils.ExcludedLabel{
1679 "": {
1680 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1681 },
1682 },
1683 Call: mustParse[*promParser.Call](t, `absent(foo{job="bar"})`, 0),
1684 },
1685 },
1686 },
1687 {
1688 expr: `absent(foo{job="bar", cluster!="dev", instance=~".+", env="prod"})`,
1689 output: []utils.Source{
1690 {
1691 Type: utils.FuncSource,
1692 Returns: promParser.ValueTypeVector,
1693 Operation: "absent",
1694 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="bar", cluster!="dev", instance=~".+", env="prod"}`, 7),
1695 IncludedLabels: []string{"job", "env"},
1696 GuaranteedLabels: []string{"job", "env"},
1697 FixedLabels: true,
1698 ExcludeReason: map[string]utils.ExcludedLabel{
1699 "": {
1700 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1701 },
1702 },
1703 Call: mustParse[*promParser.Call](t, `absent(foo{job="bar", cluster!="dev", instance=~".+", env="prod"})`, 0),
1704 },
1705 },
1706 },
1707 {
1708 expr: `absent(sum(foo) by(job, instance))`,
1709 output: []utils.Source{
1710 {
1711 Type: utils.FuncSource,
1712 Returns: promParser.ValueTypeVector,
1713 Operation: "absent",
1714 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 11),
1715 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo) by(job, instance)`, 7),
1716 FixedLabels: true,
1717 ExcludeReason: map[string]utils.ExcludedLabel{
1718 "": {
1719 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1720 },
1721 },
1722 Call: mustParse[*promParser.Call](t, `absent(sum(foo) by(job, instance))`, 0),
1723 },
1724 },
1725 },
1726 {
1727 expr: `absent(foo{job="prometheus", xxx="1"}) AND on(job) prometheus_build_info`,
1728 output: []utils.Source{
1729 {
1730 Type: utils.FuncSource,
1731 Returns: promParser.ValueTypeVector,
1732 Operation: "absent",
1733 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="prometheus", xxx="1"}`, 7),
1734 IncludedLabels: []string{"job", "xxx"},
1735 GuaranteedLabels: []string{"job", "xxx"},
1736 FixedLabels: true,
1737 ExcludeReason: map[string]utils.ExcludedLabel{
1738 "": {
1739 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1740 },
1741 },
1742 Call: mustParse[*promParser.Call](t, `absent(foo{job="prometheus", xxx="1"})`, 0),
1743 Joins: []utils.Join{
1744 {
1745 Src: utils.Source{
1746 Type: utils.SelectorSource,
1747 Returns: promParser.ValueTypeVector,
1748 Selector: mustParse[*promParser.VectorSelector](t, "prometheus_build_info", 51),
1749 },
1750 },
1751 },
1752 },
1753 },
1754 },
1755 {
1756 expr: `1 + sum(foo) by(notjob)`,
1757 output: []utils.Source{
1758 {
1759 Type: utils.AggregateSource,
1760 Returns: promParser.ValueTypeVector,
1761 Operation: "sum",
1762 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 8),
1763 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo) by(notjob)`, 4),
1764 IncludedLabels: []string{"notjob"},
1765 FixedLabels: true,
1766 ExcludeReason: map[string]utils.ExcludedLabel{
1767 "": {
1768 Reason: "Query is using aggregation with `by(notjob)`, only labels included inside `by(...)` will be present on the results.",
1769 },
1770 },
1771 },
1772 },
1773 },
1774 {
1775 expr: `count(node_exporter_build_info) by (instance, version) != ignoring(package,version) group_left(foo) count(deb_package_version) by (instance, version, package)`,
1776 output: []utils.Source{
1777 {
1778 Type: utils.AggregateSource,
1779 Returns: promParser.ValueTypeVector,
1780 Operation: "count",
1781 Selector: mustParse[*promParser.VectorSelector](t, `node_exporter_build_info`, 6),
1782 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(node_exporter_build_info) by (instance, version)`, 0),
1783 IncludedLabels: []string{"instance", "version", "foo"},
1784 FixedLabels: true,
1785 ExcludeReason: map[string]utils.ExcludedLabel{
1786 "": {
1787 Reason: "Query is using aggregation with `by(instance, version)`, only labels included inside `by(...)` will be present on the results.",
1788 },
1789 },
1790 IsConditional: true,
1791 Joins: []utils.Join{
1792 {
1793 Src: utils.Source{
1794 Type: utils.AggregateSource,
1795 Returns: promParser.ValueTypeVector,
1796 Operation: "count",
1797 Selector: mustParse[*promParser.VectorSelector](t, "deb_package_version", 106),
1798 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(deb_package_version) by (instance, version, package)`, 100),
1799 IncludedLabels: []string{"instance", "version", "package"},
1800 FixedLabels: true,
1801 ExcludeReason: map[string]utils.ExcludedLabel{
1802 "": {
1803 Reason: "Query is using aggregation with `by(instance, version, package)`, only labels included inside `by(...)` will be present on the results.",
1804 },
1805 },
1806 },
1807 },
1808 },
1809 },
1810 },
1811 },
1812 {
1813 expr: `absent(foo) or absent(bar)`,
1814 output: []utils.Source{
1815 {
1816 Type: utils.FuncSource,
1817 Returns: promParser.ValueTypeVector,
1818 Operation: "absent",
1819 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 7),
1820 FixedLabels: true,
1821 ExcludeReason: map[string]utils.ExcludedLabel{
1822 "": {
1823 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1824 },
1825 },
1826 Call: mustParse[*promParser.Call](t, `absent(foo)`, 0),
1827 },
1828 {
1829 Type: utils.FuncSource,
1830 Returns: promParser.ValueTypeVector,
1831 Operation: "absent",
1832 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 22),
1833 FixedLabels: true,
1834 ExcludeReason: map[string]utils.ExcludedLabel{
1835 "": {
1836 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1837 },
1838 },
1839 Call: mustParse[*promParser.Call](t, `absent(bar)`, 15),
1840 },
1841 },
1842 },
1843 {
1844 expr: `absent_over_time(foo[5m]) or absent(bar)`,
1845 output: []utils.Source{
1846 {
1847 Type: utils.FuncSource,
1848 Returns: promParser.ValueTypeVector,
1849 Operation: "absent_over_time",
1850 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 17),
1851 FixedLabels: true,
1852 ExcludeReason: map[string]utils.ExcludedLabel{
1853 "": {
1854 Reason: "The [absent_over_time()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent_over_time) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1855 },
1856 },
1857 Call: mustParse[*promParser.Call](t, `absent_over_time(foo[5m])`, 0),
1858 },
1859 {
1860 Type: utils.FuncSource,
1861 Returns: promParser.ValueTypeVector,
1862 Operation: "absent",
1863 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 36),
1864 FixedLabels: true,
1865 ExcludeReason: map[string]utils.ExcludedLabel{
1866 "": {
1867 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1868 },
1869 },
1870 Call: mustParse[*promParser.Call](t, `absent(bar)`, 29),
1871 },
1872 },
1873 },
1874 {
1875 expr: `bar * on() group_right(cluster, env) absent(foo{job="xxx"})`,
1876 output: []utils.Source{
1877 {
1878 Type: utils.FuncSource,
1879 Returns: promParser.ValueTypeVector,
1880 Operation: "absent",
1881 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="xxx"}`, 44),
1882 IncludedLabels: []string{"job", "cluster", "env"},
1883 GuaranteedLabels: []string{"job"},
1884 FixedLabels: true,
1885 ExcludeReason: map[string]utils.ExcludedLabel{
1886 "": {
1887 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1888 },
1889 },
1890 Call: mustParse[*promParser.Call](t, `absent(foo{job="xxx"})`, 37),
1891 Joins: []utils.Join{
1892 {
1893 Src: utils.Source{
1894 Type: utils.SelectorSource,
1895 Returns: promParser.ValueTypeVector,
1896 Selector: mustParse[*promParser.VectorSelector](t, "bar", 0),
1897 },
1898 },
1899 },
1900 },
1901 },
1902 },
1903 {
1904 expr: `bar * on() group_right() absent(foo{job="xxx"})`,
1905 output: []utils.Source{
1906 {
1907 Type: utils.FuncSource,
1908 Returns: promParser.ValueTypeVector,
1909 Operation: "absent",
1910 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="xxx"}`, 32),
1911 IncludedLabels: []string{"job"},
1912 GuaranteedLabels: []string{"job"},
1913 FixedLabels: true,
1914 ExcludeReason: map[string]utils.ExcludedLabel{
1915 "": {
1916 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
1917 },
1918 },
1919 Call: mustParse[*promParser.Call](t, `absent(foo{job="xxx"})`, 25),
1920 Joins: []utils.Join{
1921 {
1922 Src: utils.Source{
1923 Type: utils.SelectorSource,
1924 Returns: promParser.ValueTypeVector,
1925 Selector: mustParse[*promParser.VectorSelector](t, "bar", 0),
1926 },
1927 },
1928 },
1929 },
1930 },
1931 },
1932 {
1933 expr: "vector(1)",
1934 output: []utils.Source{
1935 {
1936 Type: utils.FuncSource,
1937 Returns: promParser.ValueTypeVector,
1938 Operation: "vector",
1939 FixedLabels: true,
1940 AlwaysReturns: true,
1941 KnownReturn: true,
1942 ReturnedNumber: 1,
1943 ExcludeReason: map[string]utils.ExcludedLabel{
1944 "": {
1945 Reason: "Calling `vector()` will return a vector value with no labels.",
1946 },
1947 },
1948 Call: mustParse[*promParser.Call](t, `vector(1)`, 0),
1949 },
1950 },
1951 },
1952 {
1953 expr: "vector(scalar(foo))",
1954 output: []utils.Source{
1955 {
1956 Type: utils.FuncSource,
1957 Returns: promParser.ValueTypeVector,
1958 Operation: "vector",
1959 FixedLabels: true,
1960 AlwaysReturns: true,
1961 ExcludeReason: map[string]utils.ExcludedLabel{
1962 "": {
1963 Reason: "Calling `vector()` will return a vector value with no labels.",
1964 },
1965 },
1966 Call: mustParse[*promParser.Call](t, `vector(scalar(foo))`, 0),
1967 },
1968 },
1969 },
1970 {
1971 expr: "vector(0.0 >= bool 0.5) == 1",
1972 output: []utils.Source{
1973 {
1974 Type: utils.FuncSource,
1975 Returns: promParser.ValueTypeVector,
1976 Operation: "vector",
1977 FixedLabels: true,
1978 AlwaysReturns: true,
1979 KnownReturn: true,
1980 IsDead: true,
1981 IsDeadReason: "this query always evaluates to `0 == 1` which is not possible, so it will never return anything",
1982 ExcludeReason: map[string]utils.ExcludedLabel{
1983 "": {
1984 Reason: "Calling `vector()` will return a vector value with no labels.",
1985 },
1986 },
1987 Call: mustParse[*promParser.Call](t, `vector(0.0 >= bool 0.5)`, 0),
1988 IsConditional: true,
1989 },
1990 },
1991 },
1992 {
1993 expr: `sum_over_time(foo{job="myjob"}[5m])`,
1994 output: []utils.Source{
1995 {
1996 Type: utils.FuncSource,
1997 Returns: promParser.ValueTypeVector,
1998 Operation: "sum_over_time",
1999 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 14),
2000 GuaranteedLabels: []string{"job"},
2001 Call: mustParse[*promParser.Call](t, `sum_over_time(foo{job="myjob"}[5m])`, 0),
2002 },
2003 },
2004 },
2005 {
2006 expr: `days_in_month()`,
2007 output: []utils.Source{
2008 {
2009 Type: utils.FuncSource,
2010 Returns: promParser.ValueTypeVector,
2011 Operation: "days_in_month",
2012 FixedLabels: true,
2013 AlwaysReturns: true,
2014 ExcludeReason: map[string]utils.ExcludedLabel{
2015 "": {
2016 Reason: "Calling `days_in_month()` with no arguments will return an empty time series with no labels.",
2017 },
2018 },
2019 Call: mustParse[*promParser.Call](t, `days_in_month()`, 0),
2020 },
2021 },
2022 },
2023 {
2024 expr: `days_in_month(foo{job="foo"})`,
2025 output: []utils.Source{
2026 {
2027 Type: utils.FuncSource,
2028 Returns: promParser.ValueTypeVector,
2029 Operation: "days_in_month",
2030 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="foo"}`, 14),
2031 GuaranteedLabels: []string{"job"},
2032 Call: mustParse[*promParser.Call](t, `days_in_month(foo{job="foo"})`, 0),
2033 },
2034 },
2035 },
2036 {
2037 expr: `label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")`,
2038 output: []utils.Source{
2039 {
2040 Type: utils.FuncSource,
2041 Returns: promParser.ValueTypeVector,
2042 Operation: "label_replace",
2043 Selector: mustParse[*promParser.VectorSelector](t, `up{job="api-server",service="a:c"}`, 14),
2044 GuaranteedLabels: []string{"job", "service", "foo"},
2045 Call: mustParse[*promParser.Call](t, `label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")`, 0),
2046 },
2047 },
2048 },
2049 {
2050 expr: `label_replace(sum by (pod) (pod_status) > 0, "cluster", "$1", "pod", "(.*)")`,
2051 output: []utils.Source{
2052 {
2053 Type: utils.FuncSource,
2054 Returns: promParser.ValueTypeVector,
2055 Operation: "label_replace",
2056 Selector: mustParse[*promParser.VectorSelector](t, `pod_status`, 28),
2057 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum by (pod) (pod_status)`, 14),
2058 FixedLabels: true,
2059 IsConditional: true,
2060 IncludedLabels: []string{"pod"},
2061 GuaranteedLabels: []string{"cluster"},
2062 Call: mustParse[*promParser.Call](t, `label_replace(sum by (pod) (pod_status) > 0, "cluster", "$1", "pod", "(.*)")`, 0),
2063 ExcludeReason: map[string]utils.ExcludedLabel{
2064 "": {
2065 Reason: "Query is using aggregation with `by(pod)`, only labels included inside `by(...)` will be present on the results.",
2066 },
2067 },
2068 },
2069 },
2070 },
2071 {
2072 expr: `(time() - my_metric) > 5*3600`,
2073 output: []utils.Source{
2074 {
2075 Type: utils.SelectorSource,
2076 Returns: promParser.ValueTypeVector,
2077 Selector: mustParse[*promParser.VectorSelector](t, "my_metric", 10),
2078 IsConditional: true,
2079 },
2080 },
2081 },
2082 {
2083 expr: `up{instance="a", job="prometheus"} * ignoring(job) up{instance="a", job="pint"}`,
2084 output: []utils.Source{
2085 {
2086 Type: utils.SelectorSource,
2087 Returns: promParser.ValueTypeVector,
2088 Operation: promParser.CardOneToOne.String(),
2089 Selector: mustParse[*promParser.VectorSelector](t, `up{instance="a", job="prometheus"}`, 0),
2090 GuaranteedLabels: []string{"instance"},
2091 ExcludedLabels: []string{"job"},
2092 ExcludeReason: map[string]utils.ExcludedLabel{
2093 "job": {
2094 Reason: "Query is using one-to-one vector matching with `ignoring(job)`, all labels included inside `ignoring(...)` will be removed on the results.",
2095 },
2096 },
2097 Joins: []utils.Join{
2098 {
2099 Src: utils.Source{
2100 Type: utils.SelectorSource,
2101 Returns: promParser.ValueTypeVector,
2102 Selector: mustParse[*promParser.VectorSelector](t, `up{instance="a", job="pint"}`, 51),
2103 GuaranteedLabels: []string{"instance", "job"},
2104 },
2105 },
2106 },
2107 },
2108 },
2109 },
2110 {
2111 expr: `
2112avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"})
2113< 0.5 > 0
2114or sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"})
2115< on() count(colo_router_tier:disabled_pops:max{tier="1",router=~"edge.*"}) * 0.4 > 0
2116or avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"})
2117< 0.1 > 0
2118`,
2119 output: []utils.Source{
2120 {
2121 Type: utils.AggregateSource,
2122 Returns: promParser.ValueTypeVector,
2123 Operation: "avg",
2124 Selector: mustParse[*promParser.VectorSelector](t, `router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"}`, 41),
2125 Aggregation: mustParse[*promParser.AggregateExpr](t, `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"})`, 1),
2126
2127 ExcludedLabels: []string{"router", "colo_id", "instance"},
2128 ExcludeReason: map[string]utils.ExcludedLabel{
2129 "router": {
2130 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2131 },
2132 "colo_id": {
2133 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2134 },
2135 "instance": {
2136 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2137 },
2138 },
2139 IsConditional: true,
2140 },
2141 {
2142 Type: utils.AggregateSource,
2143 Returns: promParser.ValueTypeVector,
2144 Operation: "sum",
2145 Selector: mustParse[*promParser.VectorSelector](t, `router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"}`, 155),
2146 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"})`, 115),
2147 ExcludedLabels: []string{"router", "colo_id", "instance"},
2148 FixedLabels: true,
2149 ExcludeReason: map[string]utils.ExcludedLabel{
2150 "router": {
2151 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2152 },
2153 "colo_id": {
2154 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2155 },
2156 "instance": {
2157 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2158 },
2159 "": {
2160 Reason: "Query is using one-to-one vector matching with `on()`, only labels included inside `on(...)` will be present on the results.",
2161 },
2162 },
2163 IsConditional: true,
2164 Joins: []utils.Join{
2165 {
2166 Src: utils.Source{
2167 Type: utils.AggregateSource,
2168 Returns: promParser.ValueTypeVector,
2169 Operation: "count",
2170 Selector: mustParse[*promParser.VectorSelector](t, `colo_router_tier:disabled_pops:max{tier="1",router=~"edge.*"}`, 227),
2171 Aggregation: mustParse[*promParser.AggregateExpr](t, `count(colo_router_tier:disabled_pops:max{tier="1",router=~"edge.*"})`, 221),
2172 FixedLabels: true,
2173 IsConditional: false, // FIXME true?
2174 ExcludeReason: map[string]utils.ExcludedLabel{
2175 "": {
2176 Reason: "Query is using aggregation that removes all labels.",
2177 },
2178 },
2179 },
2180 },
2181 },
2182 },
2183 {
2184 Type: utils.AggregateSource,
2185 Returns: promParser.ValueTypeVector,
2186 Operation: "avg",
2187 Selector: mustParse[*promParser.VectorSelector](t, `router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"}`, 343),
2188 Aggregation: mustParse[*promParser.AggregateExpr](t, `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"})`, 303),
2189 GuaranteedLabels: []string{"cidr_use_case"},
2190 ExcludedLabels: []string{"router", "colo_id", "instance"},
2191 ExcludeReason: map[string]utils.ExcludedLabel{
2192 "router": {
2193 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2194 },
2195 "colo_id": {
2196 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2197 },
2198 "instance": {
2199 Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.",
2200 },
2201 },
2202 IsConditional: true,
2203 },
2204 },
2205 },
2206 {
2207 expr: `label_replace(sum(foo) without(instance), "instance", "none", "", "")`,
2208 output: []utils.Source{
2209 {
2210 Type: utils.FuncSource,
2211 Returns: promParser.ValueTypeVector,
2212 Operation: "label_replace",
2213 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 18),
2214 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo) without(instance)`, 14),
2215 GuaranteedLabels: []string{"instance"},
2216 ExcludeReason: map[string]utils.ExcludedLabel{},
2217 Call: mustParse[*promParser.Call](t, `label_replace(sum(foo) without(instance), "instance", "none", "", "")`, 0),
2218 },
2219 },
2220 },
2221 {
2222 expr: `
2223sum by (region, target, colo_name) (
2224 sum_over_time(probe_success{job="abc"}[5m])
2225 or
2226 vector(1)
2227) == 0`,
2228 output: []utils.Source{
2229 {
2230 Type: utils.AggregateSource,
2231 Returns: promParser.ValueTypeVector,
2232 Operation: "sum",
2233 Selector: mustParse[*promParser.VectorSelector](t, `probe_success{job="abc"}`, 56),
2234 Call: mustParse[*promParser.Call](t, `sum_over_time(probe_success{job="abc"}[5m])`, 42),
2235 Aggregation: mustParse[*promParser.AggregateExpr](t, `
2236sum by (region, target, colo_name) (
2237 sum_over_time(probe_success{job="abc"}[5m])
2238 or
2239 vector(1)
2240)`, 0), // FIXME 0? should be 1
2241 IncludedLabels: []string{"region", "target", "colo_name"},
2242 FixedLabels: true,
2243 ExcludeReason: map[string]utils.ExcludedLabel{
2244 "": {
2245 Reason: "Query is using aggregation with `by(region, target, colo_name)`, only labels included inside `by(...)` will be present on the results.",
2246 },
2247 },
2248 IsConditional: true,
2249 },
2250 {
2251 Type: utils.AggregateSource,
2252 Returns: promParser.ValueTypeVector,
2253 Operation: "sum",
2254 Call: mustParse[*promParser.Call](t, `vector(1)`, 91),
2255 Aggregation: mustParse[*promParser.AggregateExpr](t, `
2256sum by (region, target, colo_name) (
2257 sum_over_time(probe_success{job="abc"}[5m])
2258 or
2259 vector(1)
2260)`, 0), // FIXME 0? should be 1
2261 FixedLabels: true,
2262 AlwaysReturns: true,
2263 KnownReturn: true,
2264 IsDead: true,
2265 IsDeadReason: "this query always evaluates to `1 == 0` which is not possible, so it will never return anything",
2266 ReturnedNumber: 1,
2267 ExcludeReason: map[string]utils.ExcludedLabel{
2268 "": {
2269 Reason: "Calling `vector()` will return a vector value with no labels.",
2270 },
2271 },
2272 IsConditional: true,
2273 },
2274 },
2275 },
2276 {
2277 expr: `vector(1) or foo`,
2278 output: []utils.Source{
2279 {
2280 Type: utils.FuncSource,
2281 Returns: promParser.ValueTypeVector,
2282 Operation: "vector",
2283 FixedLabels: true,
2284 AlwaysReturns: true,
2285 KnownReturn: true,
2286 ReturnedNumber: 1,
2287 ExcludeReason: map[string]utils.ExcludedLabel{
2288 "": {
2289 Reason: "Calling `vector()` will return a vector value with no labels.",
2290 },
2291 },
2292 Call: mustParse[*promParser.Call](t, "vector(1)", 0),
2293 },
2294 {
2295 Type: utils.SelectorSource,
2296 Operation: promParser.CardManyToMany.String(),
2297 Returns: promParser.ValueTypeVector,
2298 Selector: mustParse[*promParser.VectorSelector](t, "foo", 13),
2299 IsDead: true,
2300 IsDeadReason: "the left hand side always returs something and so the right hand side is never used",
2301 },
2302 },
2303 },
2304 {
2305 expr: `vector(0) > 0`,
2306 output: []utils.Source{
2307 {
2308 Type: utils.FuncSource,
2309 Returns: promParser.ValueTypeVector,
2310 Operation: "vector",
2311 FixedLabels: true,
2312 AlwaysReturns: true,
2313 KnownReturn: true,
2314 ReturnedNumber: 0,
2315 IsDead: true,
2316 IsDeadReason: "this query always evaluates to `0 > 0` which is not possible, so it will never return anything",
2317 ExcludeReason: map[string]utils.ExcludedLabel{
2318 "": {
2319 Reason: "Calling `vector()` will return a vector value with no labels.",
2320 },
2321 },
2322 Call: mustParse[*promParser.Call](t, "vector(0)", 0),
2323 IsConditional: true,
2324 },
2325 },
2326 },
2327 {
2328 expr: `vector(0) > vector(1)`,
2329 output: []utils.Source{
2330 {
2331 Type: utils.FuncSource,
2332 Returns: promParser.ValueTypeVector,
2333 Operation: "vector",
2334 FixedLabels: true,
2335 AlwaysReturns: true,
2336 KnownReturn: true,
2337 ReturnedNumber: 0,
2338 IsDead: true,
2339 IsDeadReason: "`vector(0) > vector(1)` always evaluates to `0 > 1` which is not possible, so it will never return anything",
2340 ExcludeReason: map[string]utils.ExcludedLabel{
2341 "": {
2342 Reason: "Calling `vector()` will return a vector value with no labels.",
2343 },
2344 },
2345 Call: mustParse[*promParser.Call](t, "vector(0)", 0),
2346 IsConditional: true,
2347 Joins: []utils.Join{
2348 {
2349 Src: utils.Source{
2350 Type: utils.FuncSource,
2351 Returns: promParser.ValueTypeVector,
2352 Operation: "vector",
2353 FixedLabels: true,
2354 AlwaysReturns: true,
2355 KnownReturn: true,
2356 ReturnedNumber: 1,
2357 ExcludeReason: map[string]utils.ExcludedLabel{
2358 "": {
2359 Reason: "Calling `vector()` will return a vector value with no labels.",
2360 },
2361 },
2362 Call: mustParse[*promParser.Call](t, "vector(1)", 12),
2363 },
2364 },
2365 },
2366 },
2367 },
2368 },
2369 {
2370 expr: `sum(foo or vector(0)) > 0`,
2371 output: []utils.Source{
2372 {
2373 Type: utils.AggregateSource,
2374 Returns: promParser.ValueTypeVector,
2375 Operation: "sum",
2376 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 4),
2377 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(0))`, 0),
2378 FixedLabels: true,
2379 ExcludeReason: map[string]utils.ExcludedLabel{
2380 "": {
2381 Reason: "Query is using aggregation that removes all labels.",
2382 },
2383 },
2384 IsConditional: true,
2385 },
2386 {
2387 Type: utils.AggregateSource,
2388 Returns: promParser.ValueTypeVector,
2389 Operation: "sum",
2390 Call: mustParse[*promParser.Call](t, `vector(0)`, 11),
2391 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(0))`, 0),
2392 FixedLabels: true,
2393 AlwaysReturns: true,
2394 KnownReturn: true,
2395 ReturnedNumber: 0,
2396 IsDead: true,
2397 IsDeadReason: "this query always evaluates to `0 > 0` which is not possible, so it will never return anything",
2398 ExcludeReason: map[string]utils.ExcludedLabel{
2399 "": {
2400 Reason: "Query is using aggregation that removes all labels.",
2401 },
2402 },
2403 IsConditional: true,
2404 },
2405 },
2406 },
2407 {
2408 expr: `(sum(foo or vector(1)) > 0) == 2`,
2409 output: []utils.Source{
2410 {
2411 Type: utils.AggregateSource,
2412 Returns: promParser.ValueTypeVector,
2413 Operation: "sum",
2414 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 5),
2415 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(1))`, 1),
2416 FixedLabels: true,
2417 ExcludeReason: map[string]utils.ExcludedLabel{
2418 "": {
2419 Reason: "Query is using aggregation that removes all labels.",
2420 },
2421 },
2422 IsConditional: true,
2423 },
2424 {
2425 Type: utils.AggregateSource,
2426 Returns: promParser.ValueTypeVector,
2427 Operation: "sum",
2428 Call: mustParse[*promParser.Call](t, `vector(1)`, 12),
2429 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(1))`, 1),
2430 FixedLabels: true,
2431 AlwaysReturns: true,
2432 KnownReturn: true,
2433 ReturnedNumber: 1,
2434 IsDead: true,
2435 IsDeadReason: "this query always evaluates to `1 == 2` which is not possible, so it will never return anything",
2436 ExcludeReason: map[string]utils.ExcludedLabel{
2437 "": {
2438 Reason: "Query is using aggregation that removes all labels.",
2439 },
2440 },
2441 IsConditional: true,
2442 },
2443 },
2444 },
2445 {
2446 expr: `(sum(foo or vector(1)) > 0) != 2`,
2447 output: []utils.Source{
2448 {
2449 Type: utils.AggregateSource,
2450 Returns: promParser.ValueTypeVector,
2451 Operation: "sum",
2452 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 5),
2453 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(1))`, 1),
2454 FixedLabels: true,
2455 ExcludeReason: map[string]utils.ExcludedLabel{
2456 "": {
2457 Reason: "Query is using aggregation that removes all labels.",
2458 },
2459 },
2460 IsConditional: true,
2461 },
2462 {
2463 Type: utils.AggregateSource,
2464 Returns: promParser.ValueTypeVector,
2465 Operation: "sum",
2466 Call: mustParse[*promParser.Call](t, `vector(1)`, 12),
2467 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(1))`, 1),
2468 FixedLabels: true,
2469 AlwaysReturns: true,
2470 KnownReturn: true,
2471 ReturnedNumber: 1,
2472 ExcludeReason: map[string]utils.ExcludedLabel{
2473 "": {
2474 Reason: "Query is using aggregation that removes all labels.",
2475 },
2476 },
2477 IsConditional: true,
2478 },
2479 },
2480 },
2481 {
2482 expr: `(sum(foo or vector(2)) > 0) != 2`,
2483 output: []utils.Source{
2484 {
2485 Type: utils.AggregateSource,
2486 Returns: promParser.ValueTypeVector,
2487 Operation: "sum",
2488 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 5),
2489 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(2))`, 1),
2490 FixedLabels: true,
2491 ExcludeReason: map[string]utils.ExcludedLabel{
2492 "": {
2493 Reason: "Query is using aggregation that removes all labels.",
2494 },
2495 },
2496 IsConditional: true,
2497 },
2498 {
2499 Type: utils.AggregateSource,
2500 Returns: promParser.ValueTypeVector,
2501 Operation: "sum",
2502 Call: mustParse[*promParser.Call](t, `vector(2)`, 12),
2503 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo or vector(2))`, 1),
2504 FixedLabels: true,
2505 AlwaysReturns: true,
2506 KnownReturn: true,
2507 ReturnedNumber: 2,
2508 IsDead: true,
2509 IsDeadReason: "this query always evaluates to `2 != 2` which is not possible, so it will never return anything",
2510 ExcludeReason: map[string]utils.ExcludedLabel{
2511 "": {
2512 Reason: "Query is using aggregation that removes all labels.",
2513 },
2514 },
2515 IsConditional: true,
2516 },
2517 },
2518 },
2519 {
2520 expr: `(sum(sometimes{foo!="bar"} or vector(0)))
2521or
2522((bob > 10) or sum(foo) or vector(1))`,
2523 output: []utils.Source{
2524 {
2525 Type: utils.AggregateSource,
2526 Returns: promParser.ValueTypeVector,
2527 Operation: "sum",
2528 Selector: mustParse[*promParser.VectorSelector](t, `sometimes{foo!="bar"}`, 5),
2529 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(sometimes{foo!="bar"} or vector(0) )`, 1), // FIXME extra end
2530 FixedLabels: true,
2531 ExcludeReason: map[string]utils.ExcludedLabel{
2532 "": {
2533 Reason: "Query is using aggregation that removes all labels.",
2534 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2535 },
2536 },
2537 },
2538 {
2539 Type: utils.AggregateSource,
2540 Returns: promParser.ValueTypeVector,
2541 Operation: "sum",
2542 Call: mustParse[*promParser.Call](t, `vector(0)`, 30),
2543 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(sometimes{foo!="bar"} or vector(0) )`, 1), // FIXME extra end
2544 AlwaysReturns: true,
2545 KnownReturn: true,
2546 ReturnedNumber: 0,
2547 FixedLabels: true,
2548 ExcludeReason: map[string]utils.ExcludedLabel{
2549 "": {
2550 Reason: "Query is using aggregation that removes all labels.",
2551 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2552 },
2553 },
2554 },
2555 {
2556 Type: utils.SelectorSource,
2557 Operation: promParser.CardManyToMany.String(),
2558 Returns: promParser.ValueTypeVector,
2559 Selector: mustParse[*promParser.VectorSelector](t, `bob`, 47),
2560 IsConditional: true,
2561 },
2562 {
2563 Type: utils.AggregateSource,
2564 Returns: promParser.ValueTypeVector,
2565 Operation: "sum",
2566 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 64),
2567 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo)`, 60),
2568 FixedLabels: true,
2569 ExcludeReason: map[string]utils.ExcludedLabel{
2570 "": {
2571 Reason: "Query is using aggregation that removes all labels.",
2572 },
2573 },
2574 },
2575 {
2576 Type: utils.FuncSource,
2577 Returns: promParser.ValueTypeVector,
2578 Operation: "vector",
2579 AlwaysReturns: true,
2580 KnownReturn: true,
2581 ReturnedNumber: 1,
2582 FixedLabels: true,
2583 Call: mustParse[*promParser.Call](t, "vector(1)", 72),
2584 ExcludeReason: map[string]utils.ExcludedLabel{
2585 "": {
2586 Reason: "Calling `vector()` will return a vector value with no labels.",
2587 },
2588 },
2589 },
2590 },
2591 },
2592 {
2593 expr: `
2594(
2595 sum(sometimes{foo!="bar"})
2596 or
2597 vector(1)
2598) and (
2599 ((bob > 10) or sum(bar))
2600 or
2601 notfound > 0
2602)`,
2603 output: []utils.Source{
2604 {
2605 Type: utils.AggregateSource,
2606 Returns: promParser.ValueTypeVector,
2607 Operation: "sum",
2608 Selector: mustParse[*promParser.VectorSelector](t, `sometimes{foo!="bar"}`, 8),
2609 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(sometimes{foo!="bar"})`, 4),
2610 FixedLabels: true,
2611 IsConditional: true,
2612 ExcludeReason: map[string]utils.ExcludedLabel{
2613 "": {
2614 Reason: "Query is using aggregation that removes all labels.",
2615 },
2616 },
2617 Joins: []utils.Join{
2618 {
2619 Src: utils.Source{
2620 Type: utils.SelectorSource,
2621 Operation: promParser.CardManyToMany.String(),
2622 Returns: promParser.ValueTypeVector,
2623 Selector: mustParse[*promParser.VectorSelector](t, `bob`, 57),
2624 IsConditional: true,
2625 },
2626 },
2627 {
2628 Src: utils.Source{
2629 Type: utils.AggregateSource,
2630 Returns: promParser.ValueTypeVector,
2631 Operation: "sum",
2632 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 74),
2633 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(bar )`, 70),
2634 FixedLabels: true,
2635 ExcludeReason: map[string]utils.ExcludedLabel{
2636 "": {
2637 Reason: "Query is using aggregation that removes all labels.",
2638 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2639 },
2640 },
2641 },
2642 },
2643 {
2644 Src: utils.Source{
2645 Type: utils.SelectorSource,
2646 Operation: promParser.CardManyToMany.String(),
2647 Returns: promParser.ValueTypeVector,
2648 Selector: mustParse[*promParser.VectorSelector](t, `notfound`, 85),
2649 IsConditional: true,
2650 },
2651 },
2652 },
2653 },
2654 {
2655 Type: utils.FuncSource,
2656 Returns: promParser.ValueTypeVector,
2657 Operation: "vector",
2658 AlwaysReturns: true,
2659 KnownReturn: true,
2660 ReturnedNumber: 1,
2661 FixedLabels: true,
2662 IsConditional: true,
2663 Call: mustParse[*promParser.Call](t, "vector(1)", 36),
2664 ExcludeReason: map[string]utils.ExcludedLabel{
2665 "": {
2666 Reason: "Calling `vector()` will return a vector value with no labels.",
2667 },
2668 },
2669 Joins: []utils.Join{
2670 {
2671 Src: utils.Source{
2672 Type: utils.SelectorSource,
2673 Operation: promParser.CardManyToMany.String(),
2674 Returns: promParser.ValueTypeVector,
2675 Selector: mustParse[*promParser.VectorSelector](t, `bob`, 57),
2676 IsConditional: true,
2677 },
2678 },
2679 {
2680 Src: utils.Source{
2681 Type: utils.AggregateSource,
2682 Returns: promParser.ValueTypeVector,
2683 Operation: "sum",
2684 Selector: mustParse[*promParser.VectorSelector](t, `bar`, 74),
2685 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(bar )`, 70), // FIXME extra end
2686 FixedLabels: true,
2687 ExcludeReason: map[string]utils.ExcludedLabel{
2688 "": {
2689 Reason: "Query is using aggregation that removes all labels.",
2690 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2691 },
2692 },
2693 },
2694 },
2695 {
2696 Src: utils.Source{
2697 Type: utils.SelectorSource,
2698 Operation: promParser.CardManyToMany.String(),
2699 Returns: promParser.ValueTypeVector,
2700 Selector: mustParse[*promParser.VectorSelector](t, `notfound`, 85),
2701 IsConditional: true,
2702 },
2703 },
2704 },
2705 },
2706 },
2707 },
2708 {
2709 expr: "foo offset 5m > 5",
2710 output: []utils.Source{
2711 {
2712 Type: utils.SelectorSource,
2713 Returns: promParser.ValueTypeVector,
2714 Selector: mustParse[*promParser.VectorSelector](t, "foo offset 5m", 0),
2715 IsConditional: true,
2716 },
2717 },
2718 },
2719 {
2720 expr: `
2721(rate(metric2[5m]) or vector(0)) +
2722(rate(metric1[5m]) or vector(1)) +
2723(rate(metric3{log_name="samplerd"}[5m]) or vector(2)) > 0
2724`,
2725 output: []utils.Source{
2726 {
2727 Type: utils.FuncSource,
2728 Operation: "rate",
2729 Returns: promParser.ValueTypeVector,
2730 Selector: mustParse[*promParser.VectorSelector](t, "metric2", 7),
2731 Call: mustParse[*promParser.Call](t, "rate(metric2[5m])", 2),
2732 IsConditional: true,
2733 Joins: []utils.Join{
2734 {
2735 Src: utils.Source{
2736 Type: utils.FuncSource,
2737 Operation: "rate",
2738 Returns: promParser.ValueTypeVector,
2739 Selector: mustParse[*promParser.VectorSelector](t, "metric1", 42),
2740 Call: mustParse[*promParser.Call](t, "rate(metric1[5m])", 37),
2741 },
2742 },
2743 {
2744 Src: utils.Source{
2745 Type: utils.FuncSource,
2746 Returns: promParser.ValueTypeVector,
2747 Operation: "vector",
2748 AlwaysReturns: true,
2749 KnownReturn: true,
2750 ReturnedNumber: 1,
2751 FixedLabels: true,
2752 Call: mustParse[*promParser.Call](t, "vector(1)", 58),
2753 ExcludeReason: map[string]utils.ExcludedLabel{
2754 "": {
2755 Reason: "Calling `vector()` will return a vector value with no labels.",
2756 },
2757 },
2758 },
2759 },
2760 {
2761 Src: utils.Source{
2762 Type: utils.FuncSource,
2763 Operation: "rate",
2764 Returns: promParser.ValueTypeVector,
2765 Selector: mustParse[*promParser.VectorSelector](t, `metric3{log_name="samplerd"}`, 77),
2766 Call: mustParse[*promParser.Call](t, `rate(metric3{log_name="samplerd"}[5m])`, 72),
2767 GuaranteedLabels: []string{"log_name"},
2768 },
2769 },
2770 {
2771 Src: utils.Source{
2772 Type: utils.FuncSource,
2773 Returns: promParser.ValueTypeVector,
2774 Operation: "vector",
2775 AlwaysReturns: true,
2776 KnownReturn: true,
2777 ReturnedNumber: 2,
2778 FixedLabels: true,
2779 Call: mustParse[*promParser.Call](t, "vector(2)", 114),
2780 ExcludeReason: map[string]utils.ExcludedLabel{
2781 "": {
2782 Reason: "Calling `vector()` will return a vector value with no labels.",
2783 },
2784 },
2785 },
2786 },
2787 },
2788 },
2789 {
2790 Type: utils.FuncSource,
2791 Returns: promParser.ValueTypeVector,
2792 Operation: "vector",
2793 AlwaysReturns: true,
2794 KnownReturn: true,
2795 ReturnedNumber: 3,
2796 FixedLabels: true,
2797 Call: mustParse[*promParser.Call](t, "vector(0)", 23),
2798 ExcludeReason: map[string]utils.ExcludedLabel{
2799 "": {
2800 Reason: "Calling `vector()` will return a vector value with no labels.",
2801 },
2802 },
2803 IsConditional: true,
2804 Joins: []utils.Join{
2805 {
2806 Src: utils.Source{
2807 Type: utils.FuncSource,
2808 Operation: "rate",
2809 Returns: promParser.ValueTypeVector,
2810 Selector: mustParse[*promParser.VectorSelector](t, "metric1", 42),
2811 Call: mustParse[*promParser.Call](t, "rate(metric1[5m])", 37),
2812 },
2813 },
2814 {
2815 Src: utils.Source{
2816 Type: utils.FuncSource,
2817 Returns: promParser.ValueTypeVector,
2818 Operation: "vector",
2819 AlwaysReturns: true,
2820 KnownReturn: true,
2821 ReturnedNumber: 1,
2822 FixedLabels: true,
2823 Call: mustParse[*promParser.Call](t, "vector(1)", 58),
2824 ExcludeReason: map[string]utils.ExcludedLabel{
2825 "": {
2826 Reason: "Calling `vector()` will return a vector value with no labels.",
2827 },
2828 },
2829 },
2830 },
2831 {
2832 Src: utils.Source{
2833 Type: utils.FuncSource,
2834 Operation: "rate",
2835 Returns: promParser.ValueTypeVector,
2836 Selector: mustParse[*promParser.VectorSelector](t, `metric3{log_name="samplerd"}`, 77),
2837 Call: mustParse[*promParser.Call](t, `rate(metric3{log_name="samplerd"}[5m])`, 72),
2838 GuaranteedLabels: []string{"log_name"},
2839 },
2840 },
2841 {
2842 Src: utils.Source{
2843 Type: utils.FuncSource,
2844 Returns: promParser.ValueTypeVector,
2845 Operation: "vector",
2846 AlwaysReturns: true,
2847 KnownReturn: true,
2848 ReturnedNumber: 2,
2849 FixedLabels: true,
2850 Call: mustParse[*promParser.Call](t, "vector(2)", 114),
2851 ExcludeReason: map[string]utils.ExcludedLabel{
2852 "": {
2853 Reason: "Calling `vector()` will return a vector value with no labels.",
2854 },
2855 },
2856 },
2857 },
2858 },
2859 },
2860 },
2861 },
2862 {
2863 expr: `label_replace(vector(1), "nexthop_tag", "$1", "nexthop", "(.+)")`,
2864 output: []utils.Source{
2865 {
2866 Type: utils.FuncSource,
2867 Returns: promParser.ValueTypeVector,
2868 Operation: "label_replace",
2869 AlwaysReturns: true,
2870 KnownReturn: true,
2871 FixedLabels: true,
2872 ReturnedNumber: 1,
2873 GuaranteedLabels: []string{"nexthop_tag"},
2874 Call: mustParse[*promParser.Call](t, `label_replace(vector(1), "nexthop_tag", "$1", "nexthop", "(.+)")`, 0),
2875 ExcludeReason: map[string]utils.ExcludedLabel{
2876 "": {
2877 Reason: "Calling `vector()` will return a vector value with no labels.",
2878 },
2879 },
2880 },
2881 },
2882 },
2883 {
2884 expr: `(sum(foo{job="myjob"}))`,
2885 output: []utils.Source{
2886 {
2887 Type: utils.AggregateSource,
2888 Returns: promParser.ValueTypeVector,
2889 Operation: "sum",
2890 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 5),
2891 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{job="myjob"} )`, 1),
2892 FixedLabels: true,
2893 ExcludeReason: map[string]utils.ExcludedLabel{
2894 "": {
2895 Reason: "Query is using aggregation that removes all labels.",
2896 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2897 },
2898 },
2899 },
2900 },
2901 },
2902 {
2903 expr: `(-foo{job="myjob"})`,
2904 output: []utils.Source{
2905 {
2906 Type: utils.SelectorSource,
2907 Returns: promParser.ValueTypeVector,
2908 Selector: mustParse[*promParser.VectorSelector](t, `foo{job="myjob"}`, 2),
2909 GuaranteedLabels: []string{"job"},
2910 },
2911 },
2912 },
2913 {
2914 expr: "\n((( group(vector(0)) ))) > 0",
2915 output: []utils.Source{
2916 {
2917 Type: utils.AggregateSource,
2918 Operation: "group",
2919 Returns: promParser.ValueTypeVector,
2920 FixedLabels: true,
2921 AlwaysReturns: true,
2922 KnownReturn: true,
2923 IsConditional: true,
2924 IsDead: true,
2925 IsDeadReason: "this query always evaluates to `0 > 0` which is not possible, so it will never return anything",
2926 ReturnedNumber: 0,
2927 Call: mustParse[*promParser.Call](t, `vector(0)`, 11),
2928 Aggregation: mustParse[*promParser.AggregateExpr](t, "group(vector(0) )", 5), // FIXME
2929 ExcludeReason: map[string]utils.ExcludedLabel{
2930 "": {
2931 Reason: "Query is using aggregation that removes all labels.",
2932 Fragment: posrange.PositionRange{Start: 1, End: 1}, // FIXME bogus )
2933 },
2934 },
2935 },
2936 },
2937 },
2938 {
2939 expr: "1 > bool 5",
2940 output: []utils.Source{
2941 {
2942 Type: utils.NumberSource,
2943 Returns: promParser.ValueTypeScalar,
2944 FixedLabels: true,
2945 AlwaysReturns: true,
2946 KnownReturn: true,
2947 IsConditional: true,
2948 IsDead: true,
2949 IsDeadReason: "this query always evaluates to `1 > 5` which is not possible, so it will never return anything",
2950 ReturnedNumber: 1,
2951 ExcludeReason: map[string]utils.ExcludedLabel{
2952 "": {
2953 Reason: "This query returns a number value with no labels.",
2954 },
2955 },
2956 },
2957 },
2958 },
2959 {
2960 expr: `prometheus_ready{job="prometheus"} unless vector(0)`,
2961 output: []utils.Source{
2962 {
2963 Type: utils.SelectorSource,
2964 Operation: promParser.CardManyToMany.String(),
2965 Returns: promParser.ValueTypeVector,
2966 Selector: mustParse[*promParser.VectorSelector](t, `prometheus_ready{job="prometheus"}`, 0),
2967 GuaranteedLabels: []string{"job"},
2968 Unless: []utils.Join{
2969 {
2970 Src: utils.Source{
2971 Type: utils.FuncSource,
2972 Returns: promParser.ValueTypeVector,
2973 Operation: "vector",
2974 AlwaysReturns: true,
2975 KnownReturn: true,
2976 ReturnedNumber: 0,
2977 FixedLabels: true,
2978 Call: mustParse[*promParser.Call](t, "vector(0)", 42),
2979 ExcludeReason: map[string]utils.ExcludedLabel{
2980 "": {
2981 Reason: "Calling `vector()` will return a vector value with no labels.",
2982 },
2983 },
2984 IsDead: true,
2985 IsDeadReason: "The right hand side will never be matched because it doesn't have the `job` label while the left hand side will. Calling `vector()` will return a vector value with no labels.",
2986 },
2987 },
2988 },
2989 },
2990 },
2991 },
2992 {
2993 expr: `prometheus_ready{job="prometheus"} unless on() vector(0)`,
2994 output: []utils.Source{
2995 {
2996 Type: utils.SelectorSource,
2997 Operation: promParser.CardManyToMany.String(),
2998 Returns: promParser.ValueTypeVector,
2999 IsDead: true,
3000 IsDeadReason: "this query will never return anything because the `unless` query always returns something",
3001 Selector: mustParse[*promParser.VectorSelector](t, `prometheus_ready{job="prometheus"}`, 0),
3002 GuaranteedLabels: []string{"job"},
3003 Unless: []utils.Join{
3004 {
3005 Src: utils.Source{
3006 Type: utils.FuncSource,
3007 Returns: promParser.ValueTypeVector,
3008 Operation: "vector",
3009 AlwaysReturns: true,
3010 KnownReturn: true,
3011 ReturnedNumber: 0,
3012 FixedLabels: true,
3013 Call: mustParse[*promParser.Call](t, "vector(0)", 47),
3014 ExcludeReason: map[string]utils.ExcludedLabel{
3015 "": {
3016 Reason: "Calling `vector()` will return a vector value with no labels.",
3017 },
3018 },
3019 },
3020 },
3021 },
3022 },
3023 },
3024 },
3025 {
3026 expr: `prometheus_ready{job="prometheus"} unless on(job) vector(0)`,
3027 output: []utils.Source{
3028 {
3029 Type: utils.SelectorSource,
3030 Operation: promParser.CardManyToMany.String(),
3031 Returns: promParser.ValueTypeVector,
3032 Selector: mustParse[*promParser.VectorSelector](t, `prometheus_ready{job="prometheus"}`, 0),
3033 IncludedLabels: []string{"job"},
3034 GuaranteedLabels: []string{"job"},
3035 Unless: []utils.Join{
3036 {
3037 Src: utils.Source{
3038 Type: utils.FuncSource,
3039 Returns: promParser.ValueTypeVector,
3040 Operation: "vector",
3041 AlwaysReturns: true,
3042 KnownReturn: true,
3043 IsDead: true,
3044 IsDeadReason: "The right hand side will never be matched because it doesn't have the `job` label from `on(...)`. Calling `vector()` will return a vector value with no labels.",
3045 ReturnedNumber: 0,
3046 FixedLabels: true,
3047 Call: mustParse[*promParser.Call](t, "vector(0)", 50),
3048 ExcludeReason: map[string]utils.ExcludedLabel{
3049 "": {
3050 Reason: "Calling `vector()` will return a vector value with no labels.",
3051 },
3052 },
3053 },
3054 },
3055 },
3056 },
3057 },
3058 },
3059 {
3060 expr: `
3061max by (instance, cluster) (cf_node_role{kubernetes_role="master",role="kubernetes"})
3062unless
3063 sum by (instance, cluster) (time() - node_systemd_timer_last_trigger_seconds{name=~"etcd-defrag-.*.timer"})
3064 * on (instance) group_left (cluster)
3065 cf_node_role{kubernetes_role="master",role="kubernetes"}
3066`,
3067 output: []utils.Source{
3068 {
3069 Type: utils.AggregateSource,
3070 Operation: "max",
3071 Returns: promParser.ValueTypeVector,
3072 Selector: mustParse[*promParser.VectorSelector](t, `cf_node_role{kubernetes_role="master",role="kubernetes"}`, 29),
3073 Aggregation: mustParse[*promParser.AggregateExpr](t, `max by (instance, cluster) (cf_node_role{kubernetes_role="master",role="kubernetes"})`, 1),
3074 FixedLabels: true,
3075 IncludedLabels: []string{"instance", "cluster"},
3076 ExcludeReason: map[string]utils.ExcludedLabel{
3077 "": {
3078 Reason: "Query is using aggregation with `by(instance, cluster)`, only labels included inside `by(...)` will be present on the results.",
3079 },
3080 },
3081 Unless: []utils.Join{
3082 {
3083 Src: utils.Source{
3084 Type: utils.AggregateSource,
3085 Operation: "sum",
3086 Returns: promParser.ValueTypeVector,
3087 Selector: mustParse[*promParser.VectorSelector](t, `node_systemd_timer_last_trigger_seconds{name=~"etcd-defrag-.*.timer"}`, 132),
3088 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum by (instance, cluster) (time() - node_systemd_timer_last_trigger_seconds{name=~"etcd-defrag-.*.timer"})`, 95),
3089 FixedLabels: true,
3090 IncludedLabels: []string{"instance", "cluster"},
3091 ExcludeReason: map[string]utils.ExcludedLabel{
3092 "": {
3093 Reason: "Query is using aggregation with `by(instance, cluster)`, only labels included inside `by(...)` will be present on the results.",
3094 },
3095 },
3096 Joins: []utils.Join{
3097 {
3098 Src: utils.Source{
3099 Type: utils.SelectorSource,
3100 Returns: promParser.ValueTypeVector,
3101 Selector: mustParse[*promParser.VectorSelector](t, `cf_node_role{kubernetes_role="master",role="kubernetes"}`, 247),
3102 GuaranteedLabels: []string{"kubernetes_role", "role"},
3103 },
3104 },
3105 },
3106 },
3107 },
3108 },
3109 },
3110 },
3111 },
3112 {
3113 expr: `foo{a="1"} * on() bar{b="2"}`,
3114 output: []utils.Source{
3115 {
3116 Type: utils.SelectorSource,
3117 Returns: promParser.ValueTypeVector,
3118 Operation: promParser.CardOneToOne.String(),
3119 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3120 FixedLabels: true,
3121 ExcludeReason: map[string]utils.ExcludedLabel{
3122 "": {
3123 Reason: "Query is using one-to-one vector matching with `on()`, only labels included inside `on(...)` will be present on the results.",
3124 },
3125 },
3126 Joins: []utils.Join{
3127 {
3128 Src: utils.Source{
3129 Type: utils.SelectorSource,
3130 Returns: promParser.ValueTypeVector,
3131 GuaranteedLabels: []string{"b"},
3132 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 18),
3133 },
3134 },
3135 },
3136 },
3137 },
3138 },
3139 {
3140 expr: `foo{a="1"} * on(instance) group_left(c,d) bar{b="2"}`,
3141 output: []utils.Source{
3142 {
3143 Type: utils.SelectorSource,
3144 Returns: promParser.ValueTypeVector,
3145 Operation: promParser.CardManyToOne.String(),
3146 IncludedLabels: []string{"c", "d", "instance"},
3147 GuaranteedLabels: []string{"a"},
3148 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3149 Joins: []utils.Join{
3150 {
3151 Src: utils.Source{
3152 Type: utils.SelectorSource,
3153 Returns: promParser.ValueTypeVector,
3154 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 42),
3155 GuaranteedLabels: []string{"b"},
3156 },
3157 },
3158 },
3159 },
3160 },
3161 },
3162 {
3163 expr: `foo{a="1"} * on(instance) group_right(c,d) bar{b="2"}`,
3164 output: []utils.Source{
3165 {
3166 Type: utils.SelectorSource,
3167 Returns: promParser.ValueTypeVector,
3168 Operation: promParser.CardOneToMany.String(),
3169 IncludedLabels: []string{"c", "d", "instance"},
3170 GuaranteedLabels: []string{"b"},
3171 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 43),
3172 Joins: []utils.Join{
3173 {
3174 Src: utils.Source{
3175 Type: utils.SelectorSource,
3176 Returns: promParser.ValueTypeVector,
3177 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3178 GuaranteedLabels: []string{"a"},
3179 },
3180 },
3181 },
3182 },
3183 },
3184 },
3185 {
3186 expr: `foo{a="1"} * on(instance) sum(bar{b="2"})`,
3187 output: []utils.Source{
3188 {
3189 Type: utils.SelectorSource,
3190 Returns: promParser.ValueTypeVector,
3191 Operation: promParser.CardOneToOne.String(),
3192 IncludedLabels: []string{"instance"},
3193 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3194 FixedLabels: true,
3195 ExcludeReason: map[string]utils.ExcludedLabel{
3196 "": {
3197 Reason: "Query is using one-to-one vector matching with `on(instance)`, only labels included inside `on(...)` will be present on the results.",
3198 },
3199 },
3200 Joins: []utils.Join{
3201 {
3202 Src: utils.Source{
3203 Type: utils.AggregateSource,
3204 Operation: "sum",
3205 Returns: promParser.ValueTypeVector,
3206 FixedLabels: true,
3207 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 30),
3208 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(bar{b="2"})`, 26),
3209 ExcludeReason: map[string]utils.ExcludedLabel{
3210 "": {
3211 Reason: "Query is using aggregation that removes all labels.",
3212 },
3213 },
3214 IsDead: true,
3215 IsDeadReason: "The right hand side will never be matched because it doesn't have the `instance` label from `on(...)`. Query is using aggregation that removes all labels.",
3216 },
3217 },
3218 },
3219 },
3220 },
3221 },
3222 {
3223 expr: `foo{a="1"} * on(instance) group_left(c,d) sum(bar{b="2"})`,
3224 output: []utils.Source{
3225 {
3226 Type: utils.SelectorSource,
3227 Returns: promParser.ValueTypeVector,
3228 Operation: promParser.CardManyToOne.String(),
3229 IncludedLabels: []string{"c", "d", "instance"},
3230 GuaranteedLabels: []string{"a"},
3231 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3232 Joins: []utils.Join{
3233 {
3234 Src: utils.Source{
3235 Type: utils.AggregateSource,
3236 Operation: "sum",
3237 Returns: promParser.ValueTypeVector,
3238 FixedLabels: true,
3239 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 46),
3240 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(bar{b="2"})`, 42),
3241 ExcludeReason: map[string]utils.ExcludedLabel{
3242 "": {
3243 Reason: "Query is using aggregation that removes all labels.",
3244 },
3245 },
3246 IsDead: true,
3247 IsDeadReason: "The right hand side will never be matched because it doesn't have the `instance` label from `on(...)`. Query is using aggregation that removes all labels.",
3248 },
3249 },
3250 },
3251 },
3252 },
3253 },
3254 {
3255 expr: `sum(foo{a="1"}) * on(instance) group_right(c,d) bar{b="2"}`,
3256 output: []utils.Source{
3257 {
3258 Type: utils.SelectorSource,
3259 Returns: promParser.ValueTypeVector,
3260 Operation: promParser.CardOneToMany.String(),
3261 IncludedLabels: []string{"c", "d", "instance"},
3262 GuaranteedLabels: []string{"b"},
3263 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 48),
3264 Joins: []utils.Join{
3265 {
3266 Src: utils.Source{
3267 Type: utils.AggregateSource,
3268 Operation: "sum",
3269 Returns: promParser.ValueTypeVector,
3270 FixedLabels: true,
3271 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 4),
3272 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{a="1"})`, 0),
3273 ExcludeReason: map[string]utils.ExcludedLabel{
3274 "": {
3275 Reason: "Query is using aggregation that removes all labels.",
3276 },
3277 },
3278 IsDead: true,
3279 IsDeadReason: "The left hand side will never be matched because it doesn't have the `instance` label from `on(...)`. Query is using aggregation that removes all labels.",
3280 },
3281 },
3282 },
3283 },
3284 },
3285 },
3286 {
3287 expr: `foo{a="1"} * on(instance) group_left(c,d) sum(bar{b="2"}) without(instance)`,
3288 output: []utils.Source{
3289 {
3290 Type: utils.SelectorSource,
3291 Returns: promParser.ValueTypeVector,
3292 Operation: promParser.CardManyToOne.String(),
3293 IncludedLabels: []string{"c", "d", "instance"},
3294 GuaranteedLabels: []string{"a"},
3295 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 0),
3296 Joins: []utils.Join{
3297 {
3298 Src: utils.Source{
3299 Type: utils.AggregateSource,
3300 Operation: "sum",
3301 Returns: promParser.ValueTypeVector,
3302 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 46),
3303 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(bar{b="2"}) without(instance)`, 42),
3304 GuaranteedLabels: []string{"b"},
3305 ExcludedLabels: []string{"instance"},
3306 ExcludeReason: map[string]utils.ExcludedLabel{
3307 "instance": {
3308 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
3309 },
3310 },
3311 IsDead: true,
3312 IsDeadReason: "The right hand side will never be matched because it doesn't have the `instance` label from `on(...)`. Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
3313 },
3314 },
3315 },
3316 },
3317 },
3318 },
3319 {
3320 expr: `sum(foo{a="1"}) without(instance) * on(instance) group_right(c,d) bar{b="2"}`,
3321 output: []utils.Source{
3322 {
3323 Type: utils.SelectorSource,
3324 Returns: promParser.ValueTypeVector,
3325 Operation: promParser.CardOneToMany.String(),
3326 IncludedLabels: []string{"c", "d", "instance"},
3327 GuaranteedLabels: []string{"b"},
3328 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 66),
3329 Joins: []utils.Join{
3330 {
3331 Src: utils.Source{
3332 Type: utils.AggregateSource,
3333 Operation: "sum",
3334 Returns: promParser.ValueTypeVector,
3335 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 4),
3336 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{a="1"}) without(instance)`, 0),
3337 GuaranteedLabels: []string{"a"},
3338 ExcludedLabels: []string{"instance"},
3339 ExcludeReason: map[string]utils.ExcludedLabel{
3340 "instance": {
3341 Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
3342 },
3343 },
3344 IsDead: true,
3345 IsDeadReason: "The left hand side will never be matched because it doesn't have the `instance` label from `on(...)`. Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.",
3346 },
3347 },
3348 },
3349 },
3350 },
3351 },
3352 {
3353 expr: `
3354 max without (source_instance) (
3355 increase(kernel_device_io_errors_total{device!~"loop.+"}[120m]) > 3 unless on(instance, device) (
3356 increase(kernel_device_io_soft_errors_total{device!~"loop.+"}[125m])*2 > increase(kernel_device_io_errors_total[120m])
3357 )
3358 and on(device, instance) absent(node_disk_info)
3359 ) * on(instance) group_left(group) label_replace(salt_highstate_runner_configured_minions, "instance", "$1", "minion", "(.+)")
3360`,
3361 output: []utils.Source{
3362 {
3363 Type: utils.AggregateSource,
3364 Returns: promParser.ValueTypeVector,
3365 Operation: "max",
3366 Selector: mustParse[*promParser.VectorSelector](t, `kernel_device_io_errors_total{device!~"loop.+"}`, 46),
3367 Call: mustParse[*promParser.Call](t, `increase(kernel_device_io_errors_total{device!~"loop.+"}[120m])`, 37),
3368 Aggregation: mustParse[*promParser.AggregateExpr](t,
3369 `max without (source_instance) (
3370 increase(kernel_device_io_errors_total{device!~"loop.+"}[120m]) > 3 unless on(instance, device) (
3371 increase(kernel_device_io_soft_errors_total{device!~"loop.+"}[125m])*2 > increase(kernel_device_io_errors_total[120m])
3372 )
3373 and on(device, instance) absent(node_disk_info)
3374 )`, 2),
3375 IsConditional: true,
3376 IncludedLabels: []string{"instance", "device", "group"},
3377 ExcludedLabels: []string{"source_instance"},
3378 ExcludeReason: map[string]utils.ExcludedLabel{
3379 "source_instance": {
3380 Reason: "Query is using aggregation with `without(source_instance)`, all labels included inside `without(...)` will be removed from the results.",
3381 },
3382 },
3383 Joins: []utils.Join{
3384 {
3385 Src: utils.Source{
3386 Type: utils.FuncSource,
3387 Returns: promParser.ValueTypeVector,
3388 Operation: "absent",
3389 FixedLabels: true,
3390 Selector: mustParse[*promParser.VectorSelector](t, `node_disk_info`, 299),
3391 Call: mustParse[*promParser.Call](t, `absent(node_disk_info)`, 292),
3392 IsDead: true,
3393 IsDeadReason: "The right hand side will never be matched because it doesn't have the `device` label from `on(...)`. The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
3394 ExcludeReason: map[string]utils.ExcludedLabel{
3395 "": {
3396 Reason: "The [absent()](https://prometheus.io/docs/prometheus/latest/querying/functions/#absent) function is used to check if provided query doesn't match any time series.\nYou will only get any results back if the metric selector you pass doesn't match anything.\nSince there are no matching time series there are also no labels. If some time series is missing you cannot read its labels.\nThis means that the only labels you can get back from absent call are the ones you pass to it.\nIf you're hoping to get instance specific labels this way and alert when some target is down then that won't work, use the `up` metric instead.",
3397 },
3398 },
3399 },
3400 },
3401 {
3402 Src: utils.Source{
3403 Type: utils.FuncSource,
3404 Returns: promParser.ValueTypeVector,
3405 Operation: "label_replace",
3406 GuaranteedLabels: []string{"instance"},
3407 Selector: mustParse[*promParser.VectorSelector](t, `salt_highstate_runner_configured_minions`, 365),
3408 Call: mustParse[*promParser.Call](t, `label_replace(salt_highstate_runner_configured_minions, "instance", "$1", "minion", "(.+)")`, 351),
3409 },
3410 },
3411 },
3412 Unless: []utils.Join{
3413 {
3414 Src: utils.Source{
3415 Type: utils.FuncSource,
3416 Returns: promParser.ValueTypeVector,
3417 Operation: "increase",
3418 IsConditional: true,
3419 Selector: mustParse[*promParser.VectorSelector](t, `kernel_device_io_soft_errors_total{device!~"loop.+"}`, 149),
3420 Call: mustParse[*promParser.Call](t, `increase(kernel_device_io_soft_errors_total{device!~"loop.+"}[125m])`, 140),
3421 Joins: []utils.Join{
3422 {
3423 Src: utils.Source{
3424 Type: utils.FuncSource,
3425 Returns: promParser.ValueTypeVector,
3426 Operation: "increase",
3427 Selector: mustParse[*promParser.VectorSelector](t, `kernel_device_io_errors_total`, 222),
3428 Call: mustParse[*promParser.Call](t, `increase(kernel_device_io_errors_total[120m])`, 213),
3429 },
3430 },
3431 },
3432 },
3433 },
3434 },
3435 },
3436 },
3437 },
3438 {
3439 expr: `sum(foo{a="1"}) by(job) * on() bar{b="2"}`,
3440 output: []utils.Source{
3441 {
3442 Type: utils.AggregateSource,
3443 Returns: promParser.ValueTypeVector,
3444 Operation: "sum",
3445 Selector: mustParse[*promParser.VectorSelector](t, `foo{a="1"}`, 4),
3446 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(foo{a="1"}) by(job)`, 0),
3447 FixedLabels: true,
3448 ExcludeReason: map[string]utils.ExcludedLabel{
3449 "": {
3450 Reason: "Query is using one-to-one vector matching with `on()`, only labels included inside `on(...)` will be present on the results.",
3451 },
3452 },
3453 Joins: []utils.Join{
3454 {
3455 Src: utils.Source{
3456 Type: utils.SelectorSource,
3457 Returns: promParser.ValueTypeVector,
3458 GuaranteedLabels: []string{"b"},
3459 Selector: mustParse[*promParser.VectorSelector](t, `bar{b="2"}`, 31),
3460 },
3461 },
3462 },
3463 },
3464 },
3465 },
3466 {
3467 expr: `sum(sum(foo) without(job)) by(job)`,
3468 output: []utils.Source{
3469 {
3470 Type: utils.AggregateSource,
3471 Returns: promParser.ValueTypeVector,
3472 Operation: "sum",
3473 Selector: mustParse[*promParser.VectorSelector](t, `foo`, 8),
3474 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum(sum(foo) without(job)) by(job)`, 0),
3475 FixedLabels: true,
3476 ExcludedLabels: []string{"job"},
3477 ExcludeReason: map[string]utils.ExcludedLabel{
3478 "": {
3479 Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.",
3480 },
3481 "job": {
3482 Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.",
3483 },
3484 },
3485 },
3486 },
3487 },
3488 {
3489 expr: `
3490prometheus:scrape_series_added:since_gc:sum
3491* on(prometheus) group_left()
3492label_replace(
3493 max(max_over_time(go_memstats_alloc_bytes{job="prometheus"}[2h])) by(instance)
3494 /
3495 max(max_over_time(prometheus_tsdb_head_series[2h])) by(instance),
3496 "prometheus", "$1",
3497 "instance", "(.+)"
3498)
3499`,
3500 output: []utils.Source{
3501 {
3502 Type: utils.SelectorSource,
3503 Returns: promParser.ValueTypeVector,
3504 Operation: promParser.CardManyToOne.String(),
3505 Selector: mustParse[*promParser.VectorSelector](t, `prometheus:scrape_series_added:since_gc:sum`, 1),
3506 IncludedLabels: []string{"prometheus"},
3507 Joins: []utils.Join{
3508 {
3509 Src: utils.Source{
3510 Type: utils.FuncSource,
3511 Returns: promParser.ValueTypeVector,
3512 Operation: "label_replace",
3513 Selector: mustParse[*promParser.VectorSelector](t, `go_memstats_alloc_bytes{job="prometheus"}`, 110),
3514 Call: mustParse[*promParser.Call](t, `label_replace(
3515 max(max_over_time(go_memstats_alloc_bytes{job="prometheus"}[2h])) by(instance)
3516 /
3517 max(max_over_time(prometheus_tsdb_head_series[2h])) by(instance),
3518 "prometheus", "$1",
3519 "instance", "(.+)"
3520)`, 75),
3521 Aggregation: mustParse[*promParser.AggregateExpr](t, `max(max_over_time(go_memstats_alloc_bytes{job="prometheus"}[2h])) by(instance)`, 92),
3522 GuaranteedLabels: []string{"prometheus"},
3523 IncludedLabels: []string{"instance"},
3524 FixedLabels: true,
3525 ExcludeReason: map[string]utils.ExcludedLabel{
3526 "": {
3527 Reason: "Query is using aggregation with `by(instance)`, only labels included inside `by(...)` will be present on the results.",
3528 },
3529 },
3530 Joins: []utils.Join{
3531 {
3532 Src: utils.Source{
3533 Type: utils.AggregateSource,
3534 Returns: promParser.ValueTypeVector,
3535 Operation: "max",
3536 Selector: mustParse[*promParser.VectorSelector](t, `prometheus_tsdb_head_series`, 195),
3537 Call: mustParse[*promParser.Call](t, `max_over_time(prometheus_tsdb_head_series[2h])`, 181),
3538 Aggregation: mustParse[*promParser.AggregateExpr](t, `max(max_over_time(prometheus_tsdb_head_series[2h])) by(instance)`, 177),
3539 IncludedLabels: []string{"instance"},
3540 FixedLabels: true,
3541 ExcludeReason: map[string]utils.ExcludedLabel{
3542 "": {
3543 Reason: "Query is using aggregation with `by(instance)`, only labels included inside `by(...)` will be present on the results.",
3544 },
3545 },
3546 },
3547 },
3548 },
3549 },
3550 },
3551 },
3552 },
3553 },
3554 },
3555 {
3556 expr: `(day_of_week() == 6 and hour() < 1) or vector(1)`,
3557 output: []utils.Source{
3558 {
3559 Type: utils.FuncSource,
3560 Returns: promParser.ValueTypeVector,
3561 Operation: "day_of_week",
3562 Call: mustParse[*promParser.Call](t, `day_of_week()`, 1),
3563 FixedLabels: true,
3564 AlwaysReturns: true,
3565 IsConditional: true,
3566 ExcludeReason: map[string]utils.ExcludedLabel{
3567 "": {
3568 Reason: "Calling `day_of_week()` with no arguments will return an empty time series with no labels.",
3569 },
3570 },
3571 Joins: []utils.Join{
3572 {
3573 Src: utils.Source{
3574 Type: utils.FuncSource,
3575 Returns: promParser.ValueTypeVector,
3576 Operation: "hour",
3577 Call: mustParse[*promParser.Call](t, `hour()`, 24),
3578 FixedLabels: true,
3579 AlwaysReturns: true,
3580 IsConditional: true,
3581 ExcludeReason: map[string]utils.ExcludedLabel{
3582 "": {
3583 Reason: "Calling `hour()` with no arguments will return an empty time series with no labels.",
3584 },
3585 },
3586 },
3587 },
3588 },
3589 },
3590 {
3591 Type: utils.FuncSource,
3592 Returns: promParser.ValueTypeVector,
3593 Operation: "vector",
3594 AlwaysReturns: true,
3595 KnownReturn: true,
3596 ReturnedNumber: 1,
3597 FixedLabels: true,
3598 Call: mustParse[*promParser.Call](t, "vector(1)", 39),
3599 ExcludeReason: map[string]utils.ExcludedLabel{
3600 "": {
3601 Reason: "Calling `vector()` will return a vector value with no labels.",
3602 },
3603 },
3604 },
3605 },
3606 },
3607 {
3608 expr: `
3609sum by (foo, bar) (
3610 rate(errors_total[5m])
3611 * on (instance) group_left (bob, alice)
3612 server_errors_total
3613)`,
3614 output: []utils.Source{
3615 {
3616 Type: utils.AggregateSource,
3617 Returns: promParser.ValueTypeVector,
3618 Operation: "sum",
3619 Aggregation: mustParse[*promParser.AggregateExpr](t, `sum by (foo, bar) (
3620 rate(errors_total[5m])
3621 * on (instance) group_left (bob, alice)
3622 server_errors_total
3623)`, 1),
3624 Call: mustParse[*promParser.Call](t, "rate(errors_total[5m])", 25),
3625 Selector: mustParse[*promParser.VectorSelector](t, "errors_total", 30),
3626 FixedLabels: true,
3627 IncludedLabels: []string{"foo", "bar"},
3628 ExcludeReason: map[string]utils.ExcludedLabel{
3629 "": {
3630 Reason: "Query is using aggregation with `by(foo, bar)`, only labels included inside `by(...)` will be present on the results.",
3631 },
3632 },
3633 Joins: []utils.Join{
3634 {
3635 Src: utils.Source{
3636 Type: utils.SelectorSource,
3637 Returns: promParser.ValueTypeVector,
3638 Selector: mustParse[*promParser.VectorSelector](t, "server_errors_total", 94),
3639 },
3640 },
3641 },
3642 },
3643 },
3644 },
3645 {
3646 expr: `1 - (foo or vector(0)) < 0.999`,
3647 output: []utils.Source{
3648 {
3649 Type: utils.SelectorSource,
3650 Returns: promParser.ValueTypeVector,
3651 Operation: promParser.CardManyToMany.String(),
3652 IsConditional: true,
3653 Selector: mustParse[*promParser.VectorSelector](t, "foo", 5),
3654 },
3655 {
3656 Type: utils.FuncSource,
3657 Returns: promParser.ValueTypeVector,
3658 Operation: "vector",
3659 AlwaysReturns: true,
3660 IsConditional: true,
3661 FixedLabels: true,
3662 IsDead: true,
3663 KnownReturn: true,
3664 ReturnedNumber: 1,
3665 IsDeadReason: "this query always evaluates to `1 < 0.999` which is not possible, so it will never return anything",
3666 ExcludeReason: map[string]utils.ExcludedLabel{
3667 "": {
3668 Reason: "Calling `vector()` will return a vector value with no labels.",
3669 },
3670 },
3671 Call: mustParse[*promParser.Call](t, "vector(0)", 12),
3672 },
3673 },
3674 },
3675 {
3676 expr: `
3677(
3678 vector(1) and month() == 2
3679) or vector(0)
3680`,
3681 output: []utils.Source{
3682 {
3683 Type: utils.FuncSource,
3684 Returns: promParser.ValueTypeVector,
3685 Operation: "vector",
3686 AlwaysReturns: true,
3687 IsConditional: true,
3688 FixedLabels: true,
3689 KnownReturn: true,
3690 ReturnedNumber: 1,
3691 ExcludeReason: map[string]utils.ExcludedLabel{
3692 "": {
3693 Reason: "Calling `vector()` will return a vector value with no labels.",
3694 },
3695 },
3696 Call: mustParse[*promParser.Call](t, "vector(1)", 5),
3697 Joins: []utils.Join{
3698 {
3699 Src: utils.Source{
3700 Type: utils.FuncSource,
3701 Returns: promParser.ValueTypeVector,
3702 Operation: "month",
3703 AlwaysReturns: true,
3704 FixedLabels: true,
3705 IsConditional: true,
3706 Call: mustParse[*promParser.Call](t, "month()", 19),
3707 ExcludeReason: map[string]utils.ExcludedLabel{
3708 "": {
3709 Reason: "Calling `month()` with no arguments will return an empty time series with no labels.",
3710 },
3711 },
3712 },
3713 },
3714 },
3715 },
3716 {
3717 Type: utils.FuncSource,
3718 Returns: promParser.ValueTypeVector,
3719 Operation: "vector",
3720 AlwaysReturns: true,
3721 FixedLabels: true,
3722 KnownReturn: true,
3723 ReturnedNumber: 0,
3724 ExcludeReason: map[string]utils.ExcludedLabel{
3725 "": {
3726 Reason: "Calling `vector()` will return a vector value with no labels.",
3727 },
3728 },
3729 Call: mustParse[*promParser.Call](t, "vector(0)", 37),
3730 },
3731 },
3732 },
3733 }
3734
3735 for _, tc := range testCases {
3736 t.Run(tc.expr, func(t *testing.T) {
3737 n, err := parser.DecodeExpr(tc.expr)
3738 if err != nil {
3739 t.Error(err)
3740 t.FailNow()
3741 }
3742 output := utils.LabelsSource(tc.expr, n.Expr)
3743 require.Len(t, output, len(tc.output))
3744 if diff := cmp.Diff(tc.output, output,
3745 cmpopts.EquateNaNs(),
3746 cmpopts.IgnoreUnexported(labels.Matcher{}),
3747 cmpopts.IgnoreFields(utils.ExcludedLabel{}, "Fragment"),
3748 cmpopts.IgnoreFields(utils.Source{}, "Position"),
3749 ); diff != "" {
3750 t.Errorf("utils.LabelsSource() returned wrong output (-want +got):\n%s", diff)
3751 return
3752 }
3753 })
3754 }
3755}
3756
3757func TestLabelsSourceCallCoverage(t *testing.T) {
3758 for name, def := range promParser.Functions {
3759 t.Run(name, func(t *testing.T) {
3760 if def.Experimental {
3761 t.SkipNow()
3762 }
3763
3764 var b strings.Builder
3765 b.WriteString(name)
3766 b.WriteRune('(')
3767 for i, at := range def.ArgTypes {
3768 if i > 0 {
3769 b.WriteString(", ")
3770 }
3771 switch at {
3772 case promParser.ValueTypeNone:
3773 case promParser.ValueTypeScalar:
3774 b.WriteRune('1')
3775 case promParser.ValueTypeVector:
3776 b.WriteString("http_requests_total")
3777 case promParser.ValueTypeMatrix:
3778 b.WriteString("http_requests_total[2m]")
3779 case promParser.ValueTypeString:
3780 b.WriteString(`"foo"`)
3781 }
3782 }
3783 b.WriteRune(')')
3784
3785 n, err := parser.DecodeExpr(b.String())
3786 if err != nil {
3787 t.Error(err)
3788 t.FailNow()
3789 }
3790 output := utils.LabelsSource(b.String(), n.Expr)
3791 require.Len(t, output, 1)
3792 require.NotNil(t, output[0].Call, "no call detected in: %q ~> %+v", b.String(), output)
3793 require.Equal(t, name, output[0].Operation)
3794 require.Equal(t, def.ReturnType, output[0].Returns, "incorrect return type on Source{}")
3795 })
3796 }
3797}
3798
3799func TestLabelsSourceCallCoverageFail(t *testing.T) {
3800 n := &parser.PromQLNode{
3801 Expr: &promParser.Call{
3802 Func: &promParser.Function{
3803 Name: "fake_call",
3804 },
3805 },
3806 }
3807 output := utils.LabelsSource("fake_call()", n.Expr)
3808 require.Len(t, output, 1)
3809 require.Nil(t, output[0].Call, "no call should have been detected in fake function")
3810}
3811
3812func TestSourceFragment(t *testing.T) {
3813 type testCaseT struct {
3814 expr string
3815 fragments []string
3816 }
3817
3818 testCases := []testCaseT{
3819 {
3820 expr: "1",
3821 fragments: []string{""},
3822 },
3823 {
3824 expr: `"foo"`,
3825 fragments: []string{""},
3826 },
3827 {
3828 expr: `foo`,
3829 fragments: []string{"foo"},
3830 },
3831 {
3832 expr: `foo{job="bar"}`,
3833 fragments: []string{`foo{job="bar"}`},
3834 },
3835 {
3836 expr: `rate(foo{job="bar"}[5m])`,
3837 fragments: []string{`rate(foo{job="bar"}[5m])`},
3838 },
3839 {
3840 expr: `sum(foo{job="bar"})`,
3841 fragments: []string{`sum(foo{job="bar"})`},
3842 },
3843 }
3844
3845 for _, tc := range testCases {
3846 t.Run(tc.expr, func(t *testing.T) {
3847 n, err := parser.DecodeExpr(tc.expr)
3848 if err != nil {
3849 t.Error(err)
3850 t.FailNow()
3851 }
3852 var got []string
3853 for _, src := range utils.LabelsSource(tc.expr, n.Expr) {
3854 got = append(got, src.Fragment(tc.expr))
3855 }
3856 require.Equal(t, tc.fragments, got)
3857 })
3858 }
3859}
3860