cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.73.5

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/utils/source_test.go

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