cloudflare/pint
Publicmirrored from https://github.com/cloudflare/pintAvailable
internal/parser/utils/source_test.go
2905lines · modecode
| 1 | package utils_test |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | "time" |
| 7 | |
| 8 | "github.com/stretchr/testify/require" |
| 9 | |
| 10 | "github.com/cloudflare/pint/internal/parser" |
| 11 | "github.com/cloudflare/pint/internal/parser/utils" |
| 12 | |
| 13 | promParser "github.com/prometheus/prometheus/promql/parser" |
| 14 | "github.com/prometheus/prometheus/promql/parser/posrange" |
| 15 | ) |
| 16 | |
| 17 | func TestLabelsSource(t *testing.T) { |
| 18 | type testCaseT struct { |
| 19 | expr string |
| 20 | output []utils.Source |
| 21 | } |
| 22 | |
| 23 | mustParseVector := func(s string, offset int) *promParser.VectorSelector { |
| 24 | m, err := promParser.ParseExpr(s) |
| 25 | require.NoErrorf(t, err, "failed to parse vector selector: %s", s) |
| 26 | v := m.(*promParser.VectorSelector) |
| 27 | v.PosRange.Start += posrange.Pos(offset) |
| 28 | v.PosRange.End += posrange.Pos(offset) |
| 29 | return v |
| 30 | } |
| 31 | |
| 32 | mustParseMatrix := func(s string, offset int) *promParser.MatrixSelector { |
| 33 | e, err := promParser.ParseExpr(s) |
| 34 | require.NoErrorf(t, err, "failed to parse matrix selector: %s", s) |
| 35 | m := e.(*promParser.MatrixSelector) |
| 36 | m.VectorSelector = mustParseVector(m.VectorSelector.String(), offset) |
| 37 | m.EndPos += posrange.Pos(offset) |
| 38 | return m |
| 39 | } |
| 40 | |
| 41 | testCases := []testCaseT{ |
| 42 | { |
| 43 | expr: "1", |
| 44 | output: []utils.Source{ |
| 45 | { |
| 46 | Type: utils.NumberSource, |
| 47 | Returns: promParser.ValueTypeScalar, |
| 48 | FixedLabels: true, |
| 49 | AlwaysReturns: true, |
| 50 | ReturnedNumbers: []float64{1}, |
| 51 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 52 | "": { |
| 53 | Reason: "This returns a number value with no labels.", |
| 54 | Fragment: "1", |
| 55 | }, |
| 56 | }, |
| 57 | }, |
| 58 | }, |
| 59 | }, |
| 60 | { |
| 61 | expr: "1 / 5", |
| 62 | output: []utils.Source{ |
| 63 | { |
| 64 | Type: utils.NumberSource, |
| 65 | Returns: promParser.ValueTypeScalar, |
| 66 | FixedLabels: true, |
| 67 | AlwaysReturns: true, |
| 68 | ReturnedNumbers: []float64{0.2}, |
| 69 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 70 | "": { |
| 71 | Reason: "This returns a number value with no labels.", |
| 72 | Fragment: "1", |
| 73 | }, |
| 74 | }, |
| 75 | }, |
| 76 | }, |
| 77 | }, |
| 78 | { |
| 79 | expr: "(2 ^ 5) == bool 5", |
| 80 | output: []utils.Source{ |
| 81 | { |
| 82 | Type: utils.NumberSource, |
| 83 | Returns: promParser.ValueTypeScalar, |
| 84 | FixedLabels: true, |
| 85 | AlwaysReturns: true, |
| 86 | IsDead: true, |
| 87 | ReturnedNumbers: []float64{32}, |
| 88 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 89 | "": { |
| 90 | Reason: "This returns a number value with no labels.", |
| 91 | Fragment: "2", |
| 92 | }, |
| 93 | }, |
| 94 | }, |
| 95 | }, |
| 96 | }, |
| 97 | { |
| 98 | expr: "(2 ^ 5 + 11) % 5 <= bool 2", |
| 99 | output: []utils.Source{ |
| 100 | { |
| 101 | Type: utils.NumberSource, |
| 102 | Returns: promParser.ValueTypeScalar, |
| 103 | FixedLabels: true, |
| 104 | AlwaysReturns: true, |
| 105 | IsDead: true, |
| 106 | ReturnedNumbers: []float64{3}, |
| 107 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 108 | "": { |
| 109 | Reason: "This returns a number value with no labels.", |
| 110 | Fragment: "2", |
| 111 | }, |
| 112 | }, |
| 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 | IsDead: true, |
| 125 | ReturnedNumbers: []float64{3}, |
| 126 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 127 | "": { |
| 128 | Reason: "This returns a number value with no labels.", |
| 129 | Fragment: "2", |
| 130 | }, |
| 131 | }, |
| 132 | }, |
| 133 | }, |
| 134 | }, |
| 135 | { |
| 136 | expr: "(2 ^ 5 + 11) % 5 <= bool 3", |
| 137 | output: []utils.Source{ |
| 138 | { |
| 139 | Type: utils.NumberSource, |
| 140 | Returns: promParser.ValueTypeScalar, |
| 141 | FixedLabels: true, |
| 142 | AlwaysReturns: true, |
| 143 | ReturnedNumbers: []float64{3}, |
| 144 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 145 | "": { |
| 146 | Reason: "This returns a number value with no labels.", |
| 147 | Fragment: "2", |
| 148 | }, |
| 149 | }, |
| 150 | }, |
| 151 | }, |
| 152 | }, |
| 153 | { |
| 154 | expr: "(2 ^ 5 + 11) % 5 < bool 1", |
| 155 | output: []utils.Source{ |
| 156 | { |
| 157 | Type: utils.NumberSource, |
| 158 | Returns: promParser.ValueTypeScalar, |
| 159 | FixedLabels: true, |
| 160 | AlwaysReturns: true, |
| 161 | IsDead: true, |
| 162 | ReturnedNumbers: []float64{3}, |
| 163 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 164 | "": { |
| 165 | Reason: "This returns a number value with no labels.", |
| 166 | Fragment: "2", |
| 167 | }, |
| 168 | }, |
| 169 | }, |
| 170 | }, |
| 171 | }, |
| 172 | { |
| 173 | expr: "20 - 15 < bool 1", |
| 174 | output: []utils.Source{ |
| 175 | { |
| 176 | Type: utils.NumberSource, |
| 177 | Returns: promParser.ValueTypeScalar, |
| 178 | FixedLabels: true, |
| 179 | AlwaysReturns: true, |
| 180 | IsDead: true, |
| 181 | ReturnedNumbers: []float64{5}, |
| 182 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 183 | "": { |
| 184 | Reason: "This returns a number value with no labels.", |
| 185 | Fragment: "20", |
| 186 | }, |
| 187 | }, |
| 188 | }, |
| 189 | }, |
| 190 | }, |
| 191 | { |
| 192 | expr: "2 * 5", |
| 193 | output: []utils.Source{ |
| 194 | { |
| 195 | Type: utils.NumberSource, |
| 196 | Returns: promParser.ValueTypeScalar, |
| 197 | FixedLabels: true, |
| 198 | AlwaysReturns: true, |
| 199 | ReturnedNumbers: []float64{10}, |
| 200 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 201 | "": { |
| 202 | Reason: "This returns a number value with no labels.", |
| 203 | Fragment: "2", |
| 204 | }, |
| 205 | }, |
| 206 | }, |
| 207 | }, |
| 208 | }, |
| 209 | { |
| 210 | expr: "(foo or bar) * 5", |
| 211 | output: []utils.Source{ |
| 212 | { |
| 213 | Type: utils.SelectorSource, |
| 214 | Returns: promParser.ValueTypeVector, |
| 215 | Operation: promParser.CardManyToMany.String(), |
| 216 | Selectors: []*promParser.VectorSelector{ |
| 217 | mustParseVector("foo", 1), |
| 218 | }, |
| 219 | }, |
| 220 | { |
| 221 | Type: utils.SelectorSource, |
| 222 | Returns: promParser.ValueTypeVector, |
| 223 | Operation: promParser.CardManyToMany.String(), |
| 224 | Selectors: []*promParser.VectorSelector{ |
| 225 | mustParseVector("bar", 8), |
| 226 | }, |
| 227 | }, |
| 228 | }, |
| 229 | }, |
| 230 | { |
| 231 | expr: "(foo or vector(2)) * 5", |
| 232 | output: []utils.Source{ |
| 233 | { |
| 234 | Type: utils.SelectorSource, |
| 235 | Returns: promParser.ValueTypeVector, |
| 236 | Operation: promParser.CardManyToMany.String(), |
| 237 | Selectors: []*promParser.VectorSelector{ |
| 238 | mustParseVector("foo", 1), |
| 239 | }, |
| 240 | }, |
| 241 | { |
| 242 | Type: utils.FuncSource, |
| 243 | Returns: promParser.ValueTypeVector, |
| 244 | Operation: "vector", |
| 245 | FixedLabels: true, |
| 246 | AlwaysReturns: true, |
| 247 | ReturnedNumbers: []float64{10}, |
| 248 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 249 | "": { |
| 250 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 251 | Fragment: "vector(2)", |
| 252 | }, |
| 253 | }, |
| 254 | Call: &promParser.Call{ |
| 255 | Func: &promParser.Function{ |
| 256 | Name: "vector", |
| 257 | ArgTypes: []promParser.ValueType{ |
| 258 | promParser.ValueTypeScalar, |
| 259 | }, |
| 260 | Variadic: 0, |
| 261 | ReturnType: promParser.ValueTypeVector, |
| 262 | }, |
| 263 | Args: promParser.Expressions{ |
| 264 | &promParser.NumberLiteral{ |
| 265 | Val: 2, |
| 266 | PosRange: posrange.PositionRange{ |
| 267 | Start: 15, |
| 268 | End: 16, |
| 269 | }, |
| 270 | }, |
| 271 | }, |
| 272 | PosRange: posrange.PositionRange{ |
| 273 | Start: 8, |
| 274 | End: 17, |
| 275 | }, |
| 276 | }, |
| 277 | }, |
| 278 | }, |
| 279 | }, |
| 280 | { |
| 281 | expr: "(foo or vector(5)) * (vector(2) or bar)", |
| 282 | output: []utils.Source{ |
| 283 | { |
| 284 | Type: utils.SelectorSource, |
| 285 | Returns: promParser.ValueTypeVector, |
| 286 | Operation: promParser.CardManyToMany.String(), |
| 287 | Selectors: []*promParser.VectorSelector{ |
| 288 | mustParseVector("foo", 1), |
| 289 | }, |
| 290 | }, |
| 291 | { |
| 292 | Type: utils.FuncSource, |
| 293 | Returns: promParser.ValueTypeVector, |
| 294 | Operation: "vector", |
| 295 | FixedLabels: true, |
| 296 | AlwaysReturns: true, |
| 297 | ReturnedNumbers: []float64{5}, // FIXME should be 10 really but it's one-to-one binops |
| 298 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 299 | "": { |
| 300 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 301 | Fragment: "vector(5)", |
| 302 | }, |
| 303 | }, |
| 304 | Call: &promParser.Call{ |
| 305 | Func: &promParser.Function{ |
| 306 | Name: "vector", |
| 307 | ArgTypes: []promParser.ValueType{ |
| 308 | promParser.ValueTypeScalar, |
| 309 | }, |
| 310 | Variadic: 0, |
| 311 | ReturnType: promParser.ValueTypeVector, |
| 312 | }, |
| 313 | Args: promParser.Expressions{ |
| 314 | &promParser.NumberLiteral{ |
| 315 | Val: 5, |
| 316 | PosRange: posrange.PositionRange{ |
| 317 | Start: 15, |
| 318 | End: 16, |
| 319 | }, |
| 320 | }, |
| 321 | }, |
| 322 | PosRange: posrange.PositionRange{ |
| 323 | Start: 8, |
| 324 | End: 17, |
| 325 | }, |
| 326 | }, |
| 327 | }, |
| 328 | }, |
| 329 | }, |
| 330 | { |
| 331 | expr: `1 > bool 0`, |
| 332 | output: []utils.Source{ |
| 333 | { |
| 334 | Type: utils.NumberSource, |
| 335 | Returns: promParser.ValueTypeScalar, |
| 336 | FixedLabels: true, |
| 337 | AlwaysReturns: true, |
| 338 | ReturnedNumbers: []float64{1}, |
| 339 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 340 | "": { |
| 341 | Reason: "This returns a number value with no labels.", |
| 342 | Fragment: "1", |
| 343 | }, |
| 344 | }, |
| 345 | }, |
| 346 | }, |
| 347 | }, |
| 348 | { |
| 349 | expr: `20 > bool 10`, |
| 350 | output: []utils.Source{ |
| 351 | { |
| 352 | Type: utils.NumberSource, |
| 353 | Returns: promParser.ValueTypeScalar, |
| 354 | FixedLabels: true, |
| 355 | AlwaysReturns: true, |
| 356 | ReturnedNumbers: []float64{20}, |
| 357 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 358 | "": { |
| 359 | Reason: "This returns a number value with no labels.", |
| 360 | Fragment: "20", |
| 361 | }, |
| 362 | }, |
| 363 | }, |
| 364 | }, |
| 365 | }, |
| 366 | { |
| 367 | expr: `"test"`, |
| 368 | output: []utils.Source{ |
| 369 | { |
| 370 | Type: utils.StringSource, |
| 371 | Returns: promParser.ValueTypeString, |
| 372 | FixedLabels: true, |
| 373 | AlwaysReturns: true, |
| 374 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 375 | "": { |
| 376 | Reason: "This returns a string value with no labels.", |
| 377 | Fragment: `"test"`, |
| 378 | }, |
| 379 | }, |
| 380 | }, |
| 381 | }, |
| 382 | }, |
| 383 | { |
| 384 | expr: "foo", |
| 385 | output: []utils.Source{ |
| 386 | { |
| 387 | Type: utils.SelectorSource, |
| 388 | Returns: promParser.ValueTypeVector, |
| 389 | Selectors: []*promParser.VectorSelector{ |
| 390 | mustParseVector("foo", 0), |
| 391 | }, |
| 392 | }, |
| 393 | }, |
| 394 | }, |
| 395 | { |
| 396 | expr: `foo{job="bar"}`, |
| 397 | output: []utils.Source{ |
| 398 | { |
| 399 | Type: utils.SelectorSource, |
| 400 | Returns: promParser.ValueTypeVector, |
| 401 | Selectors: []*promParser.VectorSelector{ |
| 402 | mustParseVector(`foo{job="bar"}`, 0), |
| 403 | }, |
| 404 | GuaranteedLabels: []string{"job"}, |
| 405 | }, |
| 406 | }, |
| 407 | }, |
| 408 | { |
| 409 | expr: `foo{job="bar"} or bar{job="foo"}`, |
| 410 | output: []utils.Source{ |
| 411 | { |
| 412 | Type: utils.SelectorSource, |
| 413 | Returns: promParser.ValueTypeVector, |
| 414 | Selectors: []*promParser.VectorSelector{ |
| 415 | mustParseVector(`foo{job="bar"}`, 0), |
| 416 | }, |
| 417 | Operation: promParser.CardManyToMany.String(), |
| 418 | GuaranteedLabels: []string{"job"}, |
| 419 | }, |
| 420 | { |
| 421 | Type: utils.SelectorSource, |
| 422 | Returns: promParser.ValueTypeVector, |
| 423 | Selectors: []*promParser.VectorSelector{ |
| 424 | mustParseVector(`bar{job="foo"}`, 18), |
| 425 | }, |
| 426 | Operation: promParser.CardManyToMany.String(), |
| 427 | GuaranteedLabels: []string{"job"}, |
| 428 | }, |
| 429 | }, |
| 430 | }, |
| 431 | { |
| 432 | expr: `foo{a="bar"} or bar{b="foo"}`, |
| 433 | output: []utils.Source{ |
| 434 | { |
| 435 | Type: utils.SelectorSource, |
| 436 | Returns: promParser.ValueTypeVector, |
| 437 | Selectors: []*promParser.VectorSelector{ |
| 438 | mustParseVector(`foo{a="bar"}`, 0), |
| 439 | }, |
| 440 | Operation: promParser.CardManyToMany.String(), |
| 441 | GuaranteedLabels: []string{"a"}, |
| 442 | }, |
| 443 | { |
| 444 | Type: utils.SelectorSource, |
| 445 | Returns: promParser.ValueTypeVector, |
| 446 | Selectors: []*promParser.VectorSelector{ |
| 447 | mustParseVector(`bar{b="foo"}`, 16), |
| 448 | }, |
| 449 | Operation: promParser.CardManyToMany.String(), |
| 450 | GuaranteedLabels: []string{"b"}, |
| 451 | }, |
| 452 | }, |
| 453 | }, |
| 454 | { |
| 455 | expr: "foo[5m]", |
| 456 | output: []utils.Source{ |
| 457 | { |
| 458 | Type: utils.SelectorSource, |
| 459 | Returns: promParser.ValueTypeVector, |
| 460 | Selectors: []*promParser.VectorSelector{ |
| 461 | mustParseVector("foo", 0), |
| 462 | }, |
| 463 | }, |
| 464 | }, |
| 465 | }, |
| 466 | { |
| 467 | expr: "prometheus_build_info[2m:1m]", |
| 468 | output: []utils.Source{ |
| 469 | { |
| 470 | Type: utils.SelectorSource, |
| 471 | Returns: promParser.ValueTypeVector, |
| 472 | Selectors: []*promParser.VectorSelector{ |
| 473 | mustParseVector("prometheus_build_info", 0), |
| 474 | }, |
| 475 | }, |
| 476 | }, |
| 477 | }, |
| 478 | { |
| 479 | expr: "deriv(rate(distance_covered_meters_total[1m])[5m:1m])", |
| 480 | output: []utils.Source{ |
| 481 | { |
| 482 | Type: utils.FuncSource, |
| 483 | Returns: promParser.ValueTypeVector, |
| 484 | Operation: "deriv", |
| 485 | Selectors: []*promParser.VectorSelector{ |
| 486 | mustParseVector("distance_covered_meters_total", 11), |
| 487 | }, |
| 488 | Call: &promParser.Call{ |
| 489 | Func: &promParser.Function{ |
| 490 | Name: "deriv", |
| 491 | ArgTypes: []promParser.ValueType{ |
| 492 | promParser.ValueTypeMatrix, |
| 493 | }, |
| 494 | Variadic: 0, |
| 495 | ReturnType: promParser.ValueTypeVector, |
| 496 | }, |
| 497 | Args: promParser.Expressions{ |
| 498 | &promParser.SubqueryExpr{ |
| 499 | Expr: &promParser.Call{ |
| 500 | Func: &promParser.Function{ |
| 501 | Name: "rate", |
| 502 | ArgTypes: []promParser.ValueType{ |
| 503 | promParser.ValueTypeMatrix, |
| 504 | }, |
| 505 | Variadic: 0, |
| 506 | ReturnType: promParser.ValueTypeVector, |
| 507 | }, |
| 508 | Args: promParser.Expressions{ |
| 509 | mustParseMatrix(`distance_covered_meters_total[1m]`, 11), |
| 510 | }, |
| 511 | PosRange: posrange.PositionRange{ |
| 512 | Start: 6, |
| 513 | End: 45, |
| 514 | }, |
| 515 | }, |
| 516 | Range: time.Minute * 5, |
| 517 | Step: time.Minute, |
| 518 | EndPos: posrange.Pos(52), |
| 519 | }, |
| 520 | }, |
| 521 | PosRange: posrange.PositionRange{ |
| 522 | Start: 0, |
| 523 | End: 53, |
| 524 | }, |
| 525 | }, |
| 526 | }, |
| 527 | }, |
| 528 | }, |
| 529 | { |
| 530 | expr: "foo - 1", |
| 531 | output: []utils.Source{ |
| 532 | { |
| 533 | Type: utils.SelectorSource, |
| 534 | Returns: promParser.ValueTypeVector, |
| 535 | Selectors: []*promParser.VectorSelector{ |
| 536 | mustParseVector("foo", 0), |
| 537 | }, |
| 538 | }, |
| 539 | }, |
| 540 | }, |
| 541 | { |
| 542 | expr: "foo / 5", |
| 543 | output: []utils.Source{ |
| 544 | { |
| 545 | Type: utils.SelectorSource, |
| 546 | Returns: promParser.ValueTypeVector, |
| 547 | Selectors: []*promParser.VectorSelector{ |
| 548 | mustParseVector("foo", 0), |
| 549 | }, |
| 550 | }, |
| 551 | }, |
| 552 | }, |
| 553 | { |
| 554 | expr: "-foo", |
| 555 | output: []utils.Source{ |
| 556 | { |
| 557 | Type: utils.SelectorSource, |
| 558 | Returns: promParser.ValueTypeVector, |
| 559 | Selectors: []*promParser.VectorSelector{ |
| 560 | mustParseVector("foo", 1), |
| 561 | }, |
| 562 | }, |
| 563 | }, |
| 564 | }, |
| 565 | { |
| 566 | expr: `sum(foo{job="myjob"})`, |
| 567 | output: []utils.Source{ |
| 568 | { |
| 569 | Type: utils.AggregateSource, |
| 570 | Returns: promParser.ValueTypeVector, |
| 571 | Operation: "sum", |
| 572 | Selectors: []*promParser.VectorSelector{ |
| 573 | mustParseVector(`foo{job="myjob"}`, 4), |
| 574 | }, |
| 575 | FixedLabels: true, |
| 576 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 577 | "": { |
| 578 | Reason: "Query is using aggregation that removes all labels.", |
| 579 | Fragment: `sum(foo{job="myjob"})`, |
| 580 | }, |
| 581 | }, |
| 582 | }, |
| 583 | }, |
| 584 | }, |
| 585 | { |
| 586 | expr: `sum(foo{job="myjob"}) without(job)`, |
| 587 | output: []utils.Source{ |
| 588 | { |
| 589 | Type: utils.AggregateSource, |
| 590 | Returns: promParser.ValueTypeVector, |
| 591 | Operation: "sum", |
| 592 | Selectors: []*promParser.VectorSelector{ |
| 593 | mustParseVector(`foo{job="myjob"}`, 4), |
| 594 | }, |
| 595 | ExcludedLabels: []string{"job"}, |
| 596 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 597 | "job": { |
| 598 | Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.", |
| 599 | Fragment: `sum(foo{job="myjob"}) without(job)`, |
| 600 | }, |
| 601 | }, |
| 602 | }, |
| 603 | }, |
| 604 | }, |
| 605 | { |
| 606 | expr: `sum(foo) by(job)`, |
| 607 | output: []utils.Source{ |
| 608 | { |
| 609 | Type: utils.AggregateSource, |
| 610 | Returns: promParser.ValueTypeVector, |
| 611 | Operation: "sum", |
| 612 | Selectors: []*promParser.VectorSelector{ |
| 613 | mustParseVector(`foo`, 4), |
| 614 | }, |
| 615 | IncludedLabels: []string{"job"}, |
| 616 | FixedLabels: true, |
| 617 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 618 | "": { |
| 619 | Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.", |
| 620 | Fragment: `sum(foo) by(job)`, |
| 621 | }, |
| 622 | }, |
| 623 | }, |
| 624 | }, |
| 625 | }, |
| 626 | { |
| 627 | expr: `sum(foo{job="myjob"}) by(job)`, |
| 628 | output: []utils.Source{ |
| 629 | { |
| 630 | Type: utils.AggregateSource, |
| 631 | Returns: promParser.ValueTypeVector, |
| 632 | Operation: "sum", |
| 633 | Selectors: []*promParser.VectorSelector{ |
| 634 | mustParseVector(`foo{job="myjob"}`, 4), |
| 635 | }, |
| 636 | IncludedLabels: []string{"job"}, |
| 637 | GuaranteedLabels: []string{"job"}, |
| 638 | FixedLabels: true, |
| 639 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 640 | "": { |
| 641 | Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.", |
| 642 | Fragment: `sum(foo{job="myjob"}) by(job)`, |
| 643 | }, |
| 644 | }, |
| 645 | }, |
| 646 | }, |
| 647 | }, |
| 648 | { |
| 649 | expr: `abs(foo{job="myjob"} or bar{cluster="dev"})`, |
| 650 | output: []utils.Source{ |
| 651 | { |
| 652 | Type: utils.FuncSource, |
| 653 | Returns: promParser.ValueTypeVector, |
| 654 | Operation: "abs", |
| 655 | Selectors: []*promParser.VectorSelector{ |
| 656 | mustParseVector(`foo{job="myjob"}`, 4), |
| 657 | mustParseVector(`bar{cluster="dev"}`, 24), |
| 658 | }, |
| 659 | Call: &promParser.Call{ |
| 660 | Func: &promParser.Function{ |
| 661 | Name: "abs", |
| 662 | ArgTypes: []promParser.ValueType{ |
| 663 | promParser.ValueTypeVector, |
| 664 | }, |
| 665 | Variadic: 0, |
| 666 | ReturnType: promParser.ValueTypeVector, |
| 667 | }, |
| 668 | Args: promParser.Expressions{ |
| 669 | &promParser.BinaryExpr{ |
| 670 | Op: promParser.LOR, |
| 671 | LHS: mustParseVector(`foo{job="myjob"}`, 4), |
| 672 | RHS: mustParseVector(`bar{cluster="dev"}`, 24), |
| 673 | VectorMatching: &promParser.VectorMatching{ |
| 674 | Card: promParser.CardManyToMany, |
| 675 | }, |
| 676 | }, |
| 677 | }, |
| 678 | PosRange: posrange.PositionRange{ |
| 679 | Start: 0, |
| 680 | End: 43, |
| 681 | }, |
| 682 | }, |
| 683 | }, |
| 684 | }, |
| 685 | }, |
| 686 | { |
| 687 | expr: `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`, |
| 688 | output: []utils.Source{ |
| 689 | { |
| 690 | Type: utils.AggregateSource, |
| 691 | Returns: promParser.ValueTypeVector, |
| 692 | Operation: "sum", |
| 693 | Selectors: []*promParser.VectorSelector{ |
| 694 | mustParseVector(`foo{job="myjob"}`, 4), |
| 695 | }, |
| 696 | GuaranteedLabels: []string{"job"}, |
| 697 | ExcludedLabels: []string{"instance"}, |
| 698 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 699 | "instance": { |
| 700 | Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 701 | Fragment: `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`, |
| 702 | }, |
| 703 | }, |
| 704 | }, |
| 705 | { |
| 706 | Type: utils.AggregateSource, |
| 707 | Returns: promParser.ValueTypeVector, |
| 708 | Operation: "sum", |
| 709 | Selectors: []*promParser.VectorSelector{ |
| 710 | mustParseVector(`bar{cluster="dev"}`, 24), |
| 711 | }, |
| 712 | GuaranteedLabels: []string{"cluster"}, |
| 713 | ExcludedLabels: []string{"instance"}, |
| 714 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 715 | "instance": { |
| 716 | Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 717 | Fragment: `sum(foo{job="myjob"} or bar{cluster="dev"}) without(instance)`, |
| 718 | }, |
| 719 | }, |
| 720 | }, |
| 721 | }, |
| 722 | }, |
| 723 | { |
| 724 | expr: `sum(foo{job="myjob"}) without(instance)`, |
| 725 | output: []utils.Source{ |
| 726 | { |
| 727 | Type: utils.AggregateSource, |
| 728 | Returns: promParser.ValueTypeVector, |
| 729 | Operation: "sum", |
| 730 | Selectors: []*promParser.VectorSelector{ |
| 731 | mustParseVector(`foo{job="myjob"}`, 4), |
| 732 | }, |
| 733 | GuaranteedLabels: []string{"job"}, |
| 734 | ExcludedLabels: []string{"instance"}, |
| 735 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 736 | "instance": { |
| 737 | Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 738 | Fragment: `sum(foo{job="myjob"}) without(instance)`, |
| 739 | }, |
| 740 | }, |
| 741 | }, |
| 742 | }, |
| 743 | }, |
| 744 | { |
| 745 | expr: `min(foo{job="myjob"}) / max(foo{job="myjob"})`, |
| 746 | output: []utils.Source{ |
| 747 | { |
| 748 | Type: utils.AggregateSource, |
| 749 | Returns: promParser.ValueTypeVector, |
| 750 | Operation: "min", |
| 751 | Selectors: []*promParser.VectorSelector{ |
| 752 | mustParseVector(`foo{job="myjob"}`, 4), |
| 753 | }, |
| 754 | FixedLabels: true, |
| 755 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 756 | "": { |
| 757 | Reason: "Query is using aggregation that removes all labels.", |
| 758 | Fragment: `min(foo{job="myjob"})`, |
| 759 | }, |
| 760 | }, |
| 761 | }, |
| 762 | }, |
| 763 | }, |
| 764 | { |
| 765 | expr: `max(foo{job="myjob"}) / min(foo{job="myjob"})`, |
| 766 | output: []utils.Source{ |
| 767 | { |
| 768 | Type: utils.AggregateSource, |
| 769 | Returns: promParser.ValueTypeVector, |
| 770 | Operation: "max", |
| 771 | Selectors: []*promParser.VectorSelector{ |
| 772 | mustParseVector(`foo{job="myjob"}`, 4), |
| 773 | }, |
| 774 | FixedLabels: true, |
| 775 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 776 | "": { |
| 777 | Reason: "Query is using aggregation that removes all labels.", |
| 778 | Fragment: `max(foo{job="myjob"})`, |
| 779 | }, |
| 780 | }, |
| 781 | }, |
| 782 | }, |
| 783 | }, |
| 784 | { |
| 785 | expr: `avg(foo{job="myjob"}) by(job)`, |
| 786 | output: []utils.Source{ |
| 787 | { |
| 788 | Type: utils.AggregateSource, |
| 789 | Returns: promParser.ValueTypeVector, |
| 790 | Operation: "avg", |
| 791 | Selectors: []*promParser.VectorSelector{ |
| 792 | mustParseVector(`foo{job="myjob"}`, 4), |
| 793 | }, |
| 794 | GuaranteedLabels: []string{"job"}, |
| 795 | IncludedLabels: []string{"job"}, |
| 796 | FixedLabels: true, |
| 797 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 798 | "": { |
| 799 | Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.", |
| 800 | Fragment: `avg(foo{job="myjob"}) by(job)`, |
| 801 | }, |
| 802 | }, |
| 803 | }, |
| 804 | }, |
| 805 | }, |
| 806 | { |
| 807 | expr: `group(foo) by(job)`, |
| 808 | output: []utils.Source{ |
| 809 | { |
| 810 | Type: utils.AggregateSource, |
| 811 | Returns: promParser.ValueTypeVector, |
| 812 | Operation: "group", |
| 813 | Selectors: []*promParser.VectorSelector{ |
| 814 | mustParseVector(`foo`, 6), |
| 815 | }, |
| 816 | IncludedLabels: []string{"job"}, |
| 817 | FixedLabels: true, |
| 818 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 819 | "": { |
| 820 | Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.", |
| 821 | Fragment: `group(foo) by(job)`, |
| 822 | }, |
| 823 | }, |
| 824 | }, |
| 825 | }, |
| 826 | }, |
| 827 | { |
| 828 | expr: `stddev(rate(foo[5m]))`, |
| 829 | output: []utils.Source{ |
| 830 | { |
| 831 | Type: utils.AggregateSource, |
| 832 | Returns: promParser.ValueTypeVector, |
| 833 | Operation: "stddev", |
| 834 | Selectors: []*promParser.VectorSelector{ |
| 835 | mustParseVector(`foo`, 12), |
| 836 | }, |
| 837 | FixedLabels: true, |
| 838 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 839 | "": { |
| 840 | Reason: "Query is using aggregation that removes all labels.", |
| 841 | Fragment: `stddev(rate(foo[5m]))`, |
| 842 | }, |
| 843 | }, |
| 844 | }, |
| 845 | }, |
| 846 | }, |
| 847 | { |
| 848 | expr: `stdvar(rate(foo[5m]))`, |
| 849 | output: []utils.Source{ |
| 850 | { |
| 851 | Type: utils.AggregateSource, |
| 852 | Returns: promParser.ValueTypeVector, |
| 853 | Operation: "stdvar", |
| 854 | Selectors: []*promParser.VectorSelector{ |
| 855 | mustParseVector(`foo`, 12), |
| 856 | }, |
| 857 | FixedLabels: true, |
| 858 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 859 | "": { |
| 860 | Reason: "Query is using aggregation that removes all labels.", |
| 861 | Fragment: `stdvar(rate(foo[5m]))`, |
| 862 | }, |
| 863 | }, |
| 864 | }, |
| 865 | }, |
| 866 | }, |
| 867 | { |
| 868 | expr: `stddev_over_time(foo[5m])`, |
| 869 | output: []utils.Source{ |
| 870 | { |
| 871 | Type: utils.FuncSource, |
| 872 | Returns: promParser.ValueTypeVector, |
| 873 | Operation: "stddev_over_time", |
| 874 | Selectors: []*promParser.VectorSelector{ |
| 875 | mustParseVector(`foo`, 17), |
| 876 | }, |
| 877 | Call: &promParser.Call{ |
| 878 | Func: &promParser.Function{ |
| 879 | Name: "stddev_over_time", |
| 880 | ArgTypes: []promParser.ValueType{ |
| 881 | promParser.ValueTypeMatrix, |
| 882 | }, |
| 883 | Variadic: 0, |
| 884 | ReturnType: promParser.ValueTypeVector, |
| 885 | }, |
| 886 | Args: promParser.Expressions{ |
| 887 | mustParseMatrix(`foo[5m]`, 17), |
| 888 | }, |
| 889 | PosRange: posrange.PositionRange{ |
| 890 | Start: 0, |
| 891 | End: 25, |
| 892 | }, |
| 893 | }, |
| 894 | }, |
| 895 | }, |
| 896 | }, |
| 897 | { |
| 898 | expr: `stdvar_over_time(foo[5m])`, |
| 899 | output: []utils.Source{ |
| 900 | { |
| 901 | Type: utils.FuncSource, |
| 902 | Returns: promParser.ValueTypeVector, |
| 903 | Operation: "stdvar_over_time", |
| 904 | Selectors: []*promParser.VectorSelector{ |
| 905 | mustParseVector(`foo`, 17), |
| 906 | }, |
| 907 | Call: &promParser.Call{ |
| 908 | Func: &promParser.Function{ |
| 909 | Name: "stdvar_over_time", |
| 910 | ArgTypes: []promParser.ValueType{ |
| 911 | promParser.ValueTypeMatrix, |
| 912 | }, |
| 913 | Variadic: 0, |
| 914 | ReturnType: promParser.ValueTypeVector, |
| 915 | }, |
| 916 | Args: promParser.Expressions{ |
| 917 | mustParseMatrix(`foo[5m]`, 17), |
| 918 | }, |
| 919 | PosRange: posrange.PositionRange{ |
| 920 | Start: 0, |
| 921 | End: 25, |
| 922 | }, |
| 923 | }, |
| 924 | }, |
| 925 | }, |
| 926 | }, |
| 927 | { |
| 928 | expr: `quantile(0.9, rate(foo[5m]))`, |
| 929 | output: []utils.Source{ |
| 930 | { |
| 931 | Type: utils.AggregateSource, |
| 932 | Returns: promParser.ValueTypeVector, |
| 933 | Operation: "quantile", |
| 934 | Selectors: []*promParser.VectorSelector{ |
| 935 | mustParseVector(`foo`, 19), |
| 936 | }, |
| 937 | FixedLabels: true, |
| 938 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 939 | "": { |
| 940 | Reason: "Query is using aggregation that removes all labels.", |
| 941 | Fragment: `quantile(0.9, rate(foo[5m]))`, |
| 942 | }, |
| 943 | }, |
| 944 | }, |
| 945 | }, |
| 946 | }, |
| 947 | { |
| 948 | expr: `count_values("version", build_version)`, |
| 949 | output: []utils.Source{ |
| 950 | { |
| 951 | Type: utils.AggregateSource, |
| 952 | Returns: promParser.ValueTypeVector, |
| 953 | Operation: "count_values", |
| 954 | Selectors: []*promParser.VectorSelector{ |
| 955 | mustParseVector(`build_version`, 24), |
| 956 | }, |
| 957 | GuaranteedLabels: []string{"version"}, |
| 958 | IncludedLabels: []string{"version"}, |
| 959 | FixedLabels: true, |
| 960 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 961 | "": { |
| 962 | Reason: "Query is using aggregation that removes all labels.", |
| 963 | Fragment: `count_values("version", build_version)`, |
| 964 | }, |
| 965 | }, |
| 966 | }, |
| 967 | }, |
| 968 | }, |
| 969 | { |
| 970 | expr: `count_values("version", build_version) without(job)`, |
| 971 | output: []utils.Source{ |
| 972 | { |
| 973 | Type: utils.AggregateSource, |
| 974 | Returns: promParser.ValueTypeVector, |
| 975 | Operation: "count_values", |
| 976 | Selectors: []*promParser.VectorSelector{ |
| 977 | mustParseVector(`build_version`, 24), |
| 978 | }, |
| 979 | IncludedLabels: []string{"version"}, |
| 980 | GuaranteedLabels: []string{"version"}, |
| 981 | ExcludedLabels: []string{"job"}, |
| 982 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 983 | "job": { |
| 984 | Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.", |
| 985 | Fragment: `count_values("version", build_version) without(job)`, |
| 986 | }, |
| 987 | }, |
| 988 | }, |
| 989 | }, |
| 990 | }, |
| 991 | { |
| 992 | expr: `count_values("version", build_version{job="foo"}) without(job)`, |
| 993 | output: []utils.Source{ |
| 994 | { |
| 995 | Type: utils.AggregateSource, |
| 996 | Returns: promParser.ValueTypeVector, |
| 997 | Operation: "count_values", |
| 998 | Selectors: []*promParser.VectorSelector{ |
| 999 | mustParseVector(`build_version{job="foo"}`, 24), |
| 1000 | }, |
| 1001 | IncludedLabels: []string{"version"}, |
| 1002 | GuaranteedLabels: []string{"version"}, |
| 1003 | ExcludedLabels: []string{"job"}, |
| 1004 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1005 | "job": { |
| 1006 | Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.", |
| 1007 | Fragment: `count_values("version", build_version{job="foo"}) without(job)`, |
| 1008 | }, |
| 1009 | }, |
| 1010 | }, |
| 1011 | }, |
| 1012 | }, |
| 1013 | { |
| 1014 | expr: `count_values("version", build_version) by(job)`, |
| 1015 | output: []utils.Source{ |
| 1016 | { |
| 1017 | Type: utils.AggregateSource, |
| 1018 | Returns: promParser.ValueTypeVector, |
| 1019 | Operation: "count_values", |
| 1020 | Selectors: []*promParser.VectorSelector{ |
| 1021 | mustParseVector(`build_version`, 24), |
| 1022 | }, |
| 1023 | GuaranteedLabels: []string{"version"}, |
| 1024 | IncludedLabels: []string{"job", "version"}, |
| 1025 | FixedLabels: true, |
| 1026 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1027 | "": { |
| 1028 | Reason: "Query is using aggregation with `by(job)`, only labels included inside `by(...)` will be present on the results.", |
| 1029 | Fragment: `count_values("version", build_version) by(job)`, |
| 1030 | }, |
| 1031 | }, |
| 1032 | }, |
| 1033 | }, |
| 1034 | }, |
| 1035 | { |
| 1036 | expr: `topk(10, foo{job="myjob"}) > 10`, |
| 1037 | output: []utils.Source{ |
| 1038 | { |
| 1039 | Type: utils.AggregateSource, |
| 1040 | Returns: promParser.ValueTypeVector, |
| 1041 | Operation: "topk", |
| 1042 | Selectors: []*promParser.VectorSelector{ |
| 1043 | mustParseVector(`foo{job="myjob"}`, 9), |
| 1044 | }, |
| 1045 | GuaranteedLabels: []string{"job"}, |
| 1046 | }, |
| 1047 | }, |
| 1048 | }, |
| 1049 | { |
| 1050 | expr: `topk(10, foo or bar)`, |
| 1051 | output: []utils.Source{ |
| 1052 | { |
| 1053 | Type: utils.AggregateSource, |
| 1054 | Returns: promParser.ValueTypeVector, |
| 1055 | Operation: "topk", |
| 1056 | Selectors: []*promParser.VectorSelector{ |
| 1057 | mustParseVector(`foo`, 9), |
| 1058 | }, |
| 1059 | }, |
| 1060 | { |
| 1061 | Type: utils.AggregateSource, |
| 1062 | Operation: "topk", |
| 1063 | Returns: promParser.ValueTypeVector, |
| 1064 | Selectors: []*promParser.VectorSelector{ |
| 1065 | mustParseVector(`bar`, 16), |
| 1066 | }, |
| 1067 | }, |
| 1068 | }, |
| 1069 | }, |
| 1070 | { |
| 1071 | expr: `rate(foo[10m])`, |
| 1072 | output: []utils.Source{ |
| 1073 | { |
| 1074 | Type: utils.FuncSource, |
| 1075 | Returns: promParser.ValueTypeVector, |
| 1076 | Operation: "rate", |
| 1077 | Selectors: []*promParser.VectorSelector{ |
| 1078 | mustParseVector(`foo`, 5), |
| 1079 | }, |
| 1080 | Call: &promParser.Call{ |
| 1081 | Func: &promParser.Function{ |
| 1082 | Name: "rate", |
| 1083 | ArgTypes: []promParser.ValueType{ |
| 1084 | promParser.ValueTypeMatrix, |
| 1085 | }, |
| 1086 | Variadic: 0, |
| 1087 | ReturnType: promParser.ValueTypeVector, |
| 1088 | }, |
| 1089 | Args: promParser.Expressions{ |
| 1090 | mustParseMatrix(`foo[10m]`, 5), |
| 1091 | }, |
| 1092 | PosRange: posrange.PositionRange{ |
| 1093 | Start: 0, |
| 1094 | End: 14, |
| 1095 | }, |
| 1096 | }, |
| 1097 | }, |
| 1098 | }, |
| 1099 | }, |
| 1100 | { |
| 1101 | expr: `sum(rate(foo[10m])) without(instance)`, |
| 1102 | output: []utils.Source{ |
| 1103 | { |
| 1104 | Type: utils.AggregateSource, |
| 1105 | Returns: promParser.ValueTypeVector, |
| 1106 | Operation: "sum", |
| 1107 | Selectors: []*promParser.VectorSelector{ |
| 1108 | mustParseVector(`foo`, 9), |
| 1109 | }, |
| 1110 | ExcludedLabels: []string{"instance"}, |
| 1111 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1112 | "instance": { |
| 1113 | Reason: "Query is using aggregation with `without(instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 1114 | Fragment: `sum(rate(foo[10m])) without(instance)`, |
| 1115 | }, |
| 1116 | }, |
| 1117 | }, |
| 1118 | }, |
| 1119 | }, |
| 1120 | { |
| 1121 | expr: `foo{job="foo"} / bar`, |
| 1122 | output: []utils.Source{ |
| 1123 | { |
| 1124 | Type: utils.SelectorSource, |
| 1125 | Returns: promParser.ValueTypeVector, |
| 1126 | Operation: promParser.CardOneToOne.String(), |
| 1127 | Selectors: []*promParser.VectorSelector{ |
| 1128 | mustParseVector(`foo{job="foo"}`, 0), |
| 1129 | }, |
| 1130 | GuaranteedLabels: []string{"job"}, |
| 1131 | }, |
| 1132 | }, |
| 1133 | }, |
| 1134 | { |
| 1135 | expr: `foo{job="foo"} * on(instance) bar`, |
| 1136 | output: []utils.Source{ |
| 1137 | { |
| 1138 | Type: utils.SelectorSource, |
| 1139 | Returns: promParser.ValueTypeVector, |
| 1140 | Operation: promParser.CardOneToOne.String(), |
| 1141 | Selectors: []*promParser.VectorSelector{ |
| 1142 | mustParseVector(`foo{job="foo"}`, 0), |
| 1143 | }, |
| 1144 | GuaranteedLabels: []string{"job"}, |
| 1145 | IncludedLabels: []string{"instance"}, |
| 1146 | FixedLabels: true, |
| 1147 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1148 | "": { |
| 1149 | Reason: "Query is using one-to-one vector matching with `on(instance)`, only labels included inside `on(...)` will be present on the results.", |
| 1150 | Fragment: `foo{job="foo"} * on(instance) bar`, |
| 1151 | }, |
| 1152 | }, |
| 1153 | }, |
| 1154 | }, |
| 1155 | }, |
| 1156 | { |
| 1157 | expr: `foo{job="foo"} * on(instance) group_left(bar) bar`, |
| 1158 | output: []utils.Source{ |
| 1159 | { |
| 1160 | Type: utils.SelectorSource, |
| 1161 | Returns: promParser.ValueTypeVector, |
| 1162 | Operation: promParser.CardManyToOne.String(), |
| 1163 | Selectors: []*promParser.VectorSelector{ |
| 1164 | mustParseVector(`foo{job="foo"}`, 0), |
| 1165 | }, |
| 1166 | IncludedLabels: []string{"bar", "instance"}, |
| 1167 | GuaranteedLabels: []string{"job"}, |
| 1168 | }, |
| 1169 | }, |
| 1170 | }, |
| 1171 | { |
| 1172 | expr: `foo{job="foo"} * on(instance) group_left(cluster) bar{cluster="bar", ignored="true"}`, |
| 1173 | output: []utils.Source{ |
| 1174 | { |
| 1175 | Type: utils.SelectorSource, |
| 1176 | Returns: promParser.ValueTypeVector, |
| 1177 | Operation: promParser.CardManyToOne.String(), |
| 1178 | Selectors: []*promParser.VectorSelector{ |
| 1179 | mustParseVector(`foo{job="foo"}`, 0), |
| 1180 | }, |
| 1181 | IncludedLabels: []string{"cluster", "instance"}, |
| 1182 | GuaranteedLabels: []string{"job"}, |
| 1183 | }, |
| 1184 | }, |
| 1185 | }, |
| 1186 | { |
| 1187 | expr: `foo{job="foo", ignored="true"} * on(instance) group_right(job) bar{cluster="bar"}`, |
| 1188 | output: []utils.Source{ |
| 1189 | { |
| 1190 | Type: utils.SelectorSource, |
| 1191 | Returns: promParser.ValueTypeVector, |
| 1192 | Operation: promParser.CardOneToMany.String(), |
| 1193 | Selectors: []*promParser.VectorSelector{ |
| 1194 | mustParseVector(`bar{cluster="bar"}`, 63), |
| 1195 | }, |
| 1196 | IncludedLabels: []string{"job", "instance"}, |
| 1197 | GuaranteedLabels: []string{"cluster"}, |
| 1198 | }, |
| 1199 | }, |
| 1200 | }, |
| 1201 | { |
| 1202 | expr: `count(foo / bar)`, |
| 1203 | output: []utils.Source{ |
| 1204 | { |
| 1205 | Type: utils.AggregateSource, |
| 1206 | Returns: promParser.ValueTypeVector, |
| 1207 | Operation: "count", |
| 1208 | Selectors: []*promParser.VectorSelector{ |
| 1209 | mustParseVector(`foo`, 6), |
| 1210 | }, |
| 1211 | FixedLabels: true, |
| 1212 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1213 | "": { |
| 1214 | Reason: "Query is using aggregation that removes all labels.", |
| 1215 | Fragment: `count(foo / bar)`, |
| 1216 | }, |
| 1217 | }, |
| 1218 | }, |
| 1219 | }, |
| 1220 | }, |
| 1221 | { |
| 1222 | expr: `count(up{job="a"} / on () up{job="b"})`, |
| 1223 | output: []utils.Source{ |
| 1224 | { |
| 1225 | Type: utils.AggregateSource, |
| 1226 | Returns: promParser.ValueTypeVector, |
| 1227 | Operation: "count", |
| 1228 | Selectors: []*promParser.VectorSelector{ |
| 1229 | mustParseVector(`up{job="a"}`, 6), |
| 1230 | }, |
| 1231 | FixedLabels: true, |
| 1232 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1233 | "": { |
| 1234 | Reason: "Query is using aggregation that removes all labels.", |
| 1235 | Fragment: `count(up{job="a"} / on () up{job="b"})`, |
| 1236 | }, |
| 1237 | }, |
| 1238 | }, |
| 1239 | }, |
| 1240 | }, |
| 1241 | { |
| 1242 | expr: `count(up{job="a"} / on (env) up{job="b"})`, |
| 1243 | output: []utils.Source{ |
| 1244 | { |
| 1245 | Type: utils.AggregateSource, |
| 1246 | Returns: promParser.ValueTypeVector, |
| 1247 | Operation: "count", |
| 1248 | Selectors: []*promParser.VectorSelector{ |
| 1249 | mustParseVector(`up{job="a"}`, 6), |
| 1250 | }, |
| 1251 | FixedLabels: true, |
| 1252 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1253 | "": { |
| 1254 | Reason: "Query is using aggregation that removes all labels.", |
| 1255 | Fragment: `count(up{job="a"} / on (env) up{job="b"})`, |
| 1256 | }, |
| 1257 | }, |
| 1258 | }, |
| 1259 | }, |
| 1260 | }, |
| 1261 | { |
| 1262 | expr: `foo{job="foo", instance="1"} and bar`, |
| 1263 | output: []utils.Source{ |
| 1264 | { |
| 1265 | Type: utils.SelectorSource, |
| 1266 | Returns: promParser.ValueTypeVector, |
| 1267 | Operation: promParser.CardManyToMany.String(), |
| 1268 | Selectors: []*promParser.VectorSelector{ |
| 1269 | mustParseVector(`foo{job="foo", instance="1"}`, 0), |
| 1270 | }, |
| 1271 | GuaranteedLabels: []string{"job", "instance"}, |
| 1272 | }, |
| 1273 | }, |
| 1274 | }, |
| 1275 | { |
| 1276 | expr: `foo{job="foo", instance="1"} and on(cluster) bar`, |
| 1277 | output: []utils.Source{ |
| 1278 | { |
| 1279 | Type: utils.SelectorSource, |
| 1280 | Returns: promParser.ValueTypeVector, |
| 1281 | Operation: promParser.CardManyToMany.String(), |
| 1282 | Selectors: []*promParser.VectorSelector{ |
| 1283 | mustParseVector(`foo{job="foo", instance="1"}`, 0), |
| 1284 | }, |
| 1285 | IncludedLabels: []string{"cluster"}, |
| 1286 | GuaranteedLabels: []string{"job", "instance"}, |
| 1287 | }, |
| 1288 | }, |
| 1289 | }, |
| 1290 | { |
| 1291 | expr: `topk(10, foo)`, |
| 1292 | output: []utils.Source{ |
| 1293 | { |
| 1294 | Type: utils.AggregateSource, |
| 1295 | Returns: promParser.ValueTypeVector, |
| 1296 | Operation: "topk", |
| 1297 | Selectors: []*promParser.VectorSelector{ |
| 1298 | mustParseVector(`foo`, 9), |
| 1299 | }, |
| 1300 | }, |
| 1301 | }, |
| 1302 | }, |
| 1303 | { |
| 1304 | expr: `topk(10, foo) without(cluster)`, |
| 1305 | output: []utils.Source{ |
| 1306 | { |
| 1307 | Type: utils.AggregateSource, |
| 1308 | Returns: promParser.ValueTypeVector, |
| 1309 | Operation: "topk", |
| 1310 | Selectors: []*promParser.VectorSelector{ |
| 1311 | mustParseVector(`foo`, 9), |
| 1312 | }, |
| 1313 | }, |
| 1314 | }, |
| 1315 | }, |
| 1316 | { |
| 1317 | expr: `topk(10, foo) by(cluster)`, |
| 1318 | output: []utils.Source{ |
| 1319 | { |
| 1320 | Type: utils.AggregateSource, |
| 1321 | Returns: promParser.ValueTypeVector, |
| 1322 | Operation: "topk", |
| 1323 | Selectors: []*promParser.VectorSelector{ |
| 1324 | mustParseVector(`foo`, 9), |
| 1325 | }, |
| 1326 | }, |
| 1327 | }, |
| 1328 | }, |
| 1329 | { |
| 1330 | expr: `bottomk(10, sum(rate(foo[5m])) without(job))`, |
| 1331 | output: []utils.Source{ |
| 1332 | { |
| 1333 | Type: utils.AggregateSource, |
| 1334 | Returns: promParser.ValueTypeVector, |
| 1335 | Operation: "bottomk", |
| 1336 | Selectors: []*promParser.VectorSelector{ |
| 1337 | mustParseVector(`foo`, 21), |
| 1338 | }, |
| 1339 | ExcludedLabels: []string{"job"}, |
| 1340 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1341 | "job": { |
| 1342 | Reason: "Query is using aggregation with `without(job)`, all labels included inside `without(...)` will be removed from the results.", |
| 1343 | Fragment: `sum(rate(foo[5m])) without(job)`, |
| 1344 | }, |
| 1345 | }, |
| 1346 | }, |
| 1347 | }, |
| 1348 | }, |
| 1349 | { |
| 1350 | expr: `foo or bar`, |
| 1351 | output: []utils.Source{ |
| 1352 | { |
| 1353 | Type: utils.SelectorSource, |
| 1354 | Returns: promParser.ValueTypeVector, |
| 1355 | Operation: promParser.CardManyToMany.String(), |
| 1356 | Selectors: []*promParser.VectorSelector{ |
| 1357 | mustParseVector(`foo`, 0), |
| 1358 | }, |
| 1359 | }, |
| 1360 | { |
| 1361 | Type: utils.SelectorSource, |
| 1362 | Returns: promParser.ValueTypeVector, |
| 1363 | Operation: promParser.CardManyToMany.String(), |
| 1364 | Selectors: []*promParser.VectorSelector{ |
| 1365 | mustParseVector(`bar`, 7), |
| 1366 | }, |
| 1367 | }, |
| 1368 | }, |
| 1369 | }, |
| 1370 | { |
| 1371 | expr: `foo or bar or baz`, |
| 1372 | output: []utils.Source{ |
| 1373 | { |
| 1374 | Type: utils.SelectorSource, |
| 1375 | Returns: promParser.ValueTypeVector, |
| 1376 | Operation: promParser.CardManyToMany.String(), |
| 1377 | Selectors: []*promParser.VectorSelector{ |
| 1378 | mustParseVector(`foo`, 0), |
| 1379 | }, |
| 1380 | }, |
| 1381 | { |
| 1382 | Type: utils.SelectorSource, |
| 1383 | Returns: promParser.ValueTypeVector, |
| 1384 | Operation: promParser.CardManyToMany.String(), |
| 1385 | Selectors: []*promParser.VectorSelector{ |
| 1386 | mustParseVector(`bar`, 7), |
| 1387 | }, |
| 1388 | }, |
| 1389 | { |
| 1390 | Type: utils.SelectorSource, |
| 1391 | Returns: promParser.ValueTypeVector, |
| 1392 | Operation: promParser.CardManyToMany.String(), |
| 1393 | Selectors: []*promParser.VectorSelector{ |
| 1394 | mustParseVector(`baz`, 14), |
| 1395 | }, |
| 1396 | }, |
| 1397 | }, |
| 1398 | }, |
| 1399 | { |
| 1400 | expr: `(foo or bar) or baz`, |
| 1401 | output: []utils.Source{ |
| 1402 | { |
| 1403 | Type: utils.SelectorSource, |
| 1404 | Returns: promParser.ValueTypeVector, |
| 1405 | Operation: promParser.CardManyToMany.String(), |
| 1406 | Selectors: []*promParser.VectorSelector{ |
| 1407 | mustParseVector(`foo`, 1), |
| 1408 | }, |
| 1409 | }, |
| 1410 | { |
| 1411 | Type: utils.SelectorSource, |
| 1412 | Returns: promParser.ValueTypeVector, |
| 1413 | Operation: promParser.CardManyToMany.String(), |
| 1414 | Selectors: []*promParser.VectorSelector{ |
| 1415 | mustParseVector(`bar`, 8), |
| 1416 | }, |
| 1417 | }, |
| 1418 | { |
| 1419 | Type: utils.SelectorSource, |
| 1420 | Returns: promParser.ValueTypeVector, |
| 1421 | Operation: promParser.CardManyToMany.String(), |
| 1422 | Selectors: []*promParser.VectorSelector{ |
| 1423 | mustParseVector(`baz`, 16), |
| 1424 | }, |
| 1425 | }, |
| 1426 | }, |
| 1427 | }, |
| 1428 | { |
| 1429 | expr: `foo unless bar`, |
| 1430 | output: []utils.Source{ |
| 1431 | { |
| 1432 | Type: utils.SelectorSource, |
| 1433 | Returns: promParser.ValueTypeVector, |
| 1434 | Operation: promParser.CardManyToMany.String(), |
| 1435 | Selectors: []*promParser.VectorSelector{ |
| 1436 | mustParseVector(`foo`, 0), |
| 1437 | }, |
| 1438 | }, |
| 1439 | }, |
| 1440 | }, |
| 1441 | { |
| 1442 | expr: `count(sum(up{job="foo", cluster="dev"}) by(job, cluster) == 0) without(job, cluster)`, |
| 1443 | output: []utils.Source{ |
| 1444 | { |
| 1445 | Type: utils.AggregateSource, |
| 1446 | Returns: promParser.ValueTypeVector, |
| 1447 | Operation: "count", |
| 1448 | Selectors: []*promParser.VectorSelector{ |
| 1449 | mustParseVector(`up{job="foo", cluster="dev"}`, 10), |
| 1450 | }, |
| 1451 | ExcludedLabels: []string{"job", "cluster"}, // FIXME empty |
| 1452 | FixedLabels: true, |
| 1453 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1454 | "": { |
| 1455 | Reason: "Query is using aggregation with `by(job, cluster)`, only labels included inside `by(...)` will be present on the results.", |
| 1456 | Fragment: `sum(up{job="foo", cluster="dev"}) by(job, cluster)`, |
| 1457 | }, |
| 1458 | "job": { |
| 1459 | Reason: "Query is using aggregation with `without(job, cluster)`, all labels included inside `without(...)` will be removed from the results.", |
| 1460 | Fragment: `count(sum(up{job="foo", cluster="dev"}) by(job, cluster) == 0) without(job, cluster)`, |
| 1461 | }, |
| 1462 | "cluster": { |
| 1463 | Reason: "Query is using aggregation with `without(job, cluster)`, all labels included inside `without(...)` will be removed from the results.", |
| 1464 | Fragment: `count(sum(up{job="foo", cluster="dev"}) by(job, cluster) == 0) without(job, cluster)`, |
| 1465 | }, |
| 1466 | }, |
| 1467 | }, |
| 1468 | }, |
| 1469 | }, |
| 1470 | { |
| 1471 | expr: "year()", |
| 1472 | output: []utils.Source{ |
| 1473 | { |
| 1474 | Type: utils.FuncSource, |
| 1475 | Returns: promParser.ValueTypeVector, |
| 1476 | Operation: "year", |
| 1477 | FixedLabels: true, |
| 1478 | AlwaysReturns: true, |
| 1479 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1480 | "": { |
| 1481 | Reason: "Calling `year()` with no arguments will return an empty time series with no labels.", |
| 1482 | Fragment: `year()`, |
| 1483 | }, |
| 1484 | }, |
| 1485 | Call: &promParser.Call{ |
| 1486 | Func: &promParser.Function{ |
| 1487 | Name: "year", |
| 1488 | ArgTypes: []promParser.ValueType{ |
| 1489 | promParser.ValueTypeVector, |
| 1490 | }, |
| 1491 | Variadic: 1, |
| 1492 | ReturnType: promParser.ValueTypeVector, |
| 1493 | }, |
| 1494 | Args: promParser.Expressions{}, |
| 1495 | PosRange: posrange.PositionRange{ |
| 1496 | Start: 0, |
| 1497 | End: 6, |
| 1498 | }, |
| 1499 | }, |
| 1500 | }, |
| 1501 | }, |
| 1502 | }, |
| 1503 | { |
| 1504 | expr: "year(foo)", |
| 1505 | output: []utils.Source{ |
| 1506 | { |
| 1507 | Type: utils.FuncSource, |
| 1508 | Returns: promParser.ValueTypeVector, |
| 1509 | Operation: "year", |
| 1510 | Selectors: []*promParser.VectorSelector{ |
| 1511 | mustParseVector("foo", 5), |
| 1512 | }, |
| 1513 | Call: &promParser.Call{ |
| 1514 | Func: &promParser.Function{ |
| 1515 | Name: "year", |
| 1516 | ArgTypes: []promParser.ValueType{ |
| 1517 | promParser.ValueTypeVector, |
| 1518 | }, |
| 1519 | Variadic: 1, |
| 1520 | ReturnType: promParser.ValueTypeVector, |
| 1521 | }, |
| 1522 | Args: promParser.Expressions{ |
| 1523 | mustParseVector("foo", 5), |
| 1524 | }, |
| 1525 | PosRange: posrange.PositionRange{ |
| 1526 | Start: 0, |
| 1527 | End: 9, |
| 1528 | }, |
| 1529 | }, |
| 1530 | }, |
| 1531 | }, |
| 1532 | }, |
| 1533 | { |
| 1534 | expr: `label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")`, |
| 1535 | output: []utils.Source{ |
| 1536 | { |
| 1537 | Type: utils.FuncSource, |
| 1538 | Returns: promParser.ValueTypeVector, |
| 1539 | Operation: "label_join", |
| 1540 | Selectors: []*promParser.VectorSelector{ |
| 1541 | mustParseVector(`up{job="api-server",src1="a",src2="b",src3="c"}`, 11), |
| 1542 | }, |
| 1543 | GuaranteedLabels: []string{"job", "src1", "src2", "src3", "foo"}, |
| 1544 | Call: &promParser.Call{ |
| 1545 | Func: &promParser.Function{ |
| 1546 | Name: "label_join", |
| 1547 | ArgTypes: []promParser.ValueType{ |
| 1548 | promParser.ValueTypeVector, |
| 1549 | promParser.ValueTypeString, |
| 1550 | promParser.ValueTypeString, |
| 1551 | promParser.ValueTypeString, |
| 1552 | }, |
| 1553 | Variadic: -1, |
| 1554 | ReturnType: promParser.ValueTypeVector, |
| 1555 | }, |
| 1556 | Args: promParser.Expressions{ |
| 1557 | mustParseVector(`up{job="api-server",src1="a",src2="b",src3="c"}`, 11), |
| 1558 | &promParser.StringLiteral{ |
| 1559 | Val: "foo", |
| 1560 | PosRange: posrange.PositionRange{Start: 60, End: 65}, |
| 1561 | }, |
| 1562 | &promParser.StringLiteral{ |
| 1563 | Val: ",", |
| 1564 | PosRange: posrange.PositionRange{Start: 67, End: 70}, |
| 1565 | }, |
| 1566 | &promParser.StringLiteral{ |
| 1567 | Val: "src1", |
| 1568 | PosRange: posrange.PositionRange{Start: 72, End: 78}, |
| 1569 | }, |
| 1570 | &promParser.StringLiteral{ |
| 1571 | Val: "src2", |
| 1572 | PosRange: posrange.PositionRange{Start: 80, End: 86}, |
| 1573 | }, |
| 1574 | &promParser.StringLiteral{ |
| 1575 | Val: "src3", |
| 1576 | PosRange: posrange.PositionRange{Start: 88, End: 94}, |
| 1577 | }, |
| 1578 | }, |
| 1579 | PosRange: posrange.PositionRange{ |
| 1580 | Start: 0, |
| 1581 | End: 95, |
| 1582 | }, |
| 1583 | }, |
| 1584 | }, |
| 1585 | }, |
| 1586 | }, |
| 1587 | { |
| 1588 | expr: ` |
| 1589 | ( |
| 1590 | sum(foo:sum > 0) without(notify) |
| 1591 | * on(job) group_left(notify) |
| 1592 | job:notify |
| 1593 | ) |
| 1594 | and on(job) |
| 1595 | sum(foo:count) by(job) > 20`, |
| 1596 | output: []utils.Source{ |
| 1597 | { |
| 1598 | Type: utils.AggregateSource, |
| 1599 | Returns: promParser.ValueTypeVector, |
| 1600 | Operation: "sum", |
| 1601 | Selectors: []*promParser.VectorSelector{ |
| 1602 | mustParseVector(`foo:sum`, 8), |
| 1603 | }, |
| 1604 | IncludedLabels: []string{"notify", "job"}, |
| 1605 | ExcludeReason: map[string]utils.ExcludedLabel{}, |
| 1606 | }, |
| 1607 | }, |
| 1608 | }, |
| 1609 | { |
| 1610 | expr: `container_file_descriptors / on (instance, app_name) container_ulimits_soft{ulimit="max_open_files"}`, |
| 1611 | output: []utils.Source{ |
| 1612 | { |
| 1613 | Type: utils.SelectorSource, |
| 1614 | Returns: promParser.ValueTypeVector, |
| 1615 | Operation: promParser.CardOneToOne.String(), |
| 1616 | Selectors: []*promParser.VectorSelector{ |
| 1617 | mustParseVector(`container_file_descriptors`, 0), |
| 1618 | }, |
| 1619 | IncludedLabels: []string{"instance", "app_name"}, |
| 1620 | FixedLabels: true, |
| 1621 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1622 | "": { |
| 1623 | 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.", |
| 1624 | Fragment: `container_file_descriptors / on (instance, app_name) container_ulimits_soft{ulimit="max_open_files"}`, |
| 1625 | }, |
| 1626 | }, |
| 1627 | }, |
| 1628 | }, |
| 1629 | }, |
| 1630 | { |
| 1631 | expr: `container_file_descriptors / on (instance, app_name) group_left() container_ulimits_soft{ulimit="max_open_files"}`, |
| 1632 | output: []utils.Source{ |
| 1633 | { |
| 1634 | Type: utils.SelectorSource, |
| 1635 | Returns: promParser.ValueTypeVector, |
| 1636 | Operation: promParser.CardManyToOne.String(), |
| 1637 | Selectors: []*promParser.VectorSelector{ |
| 1638 | mustParseVector(`container_file_descriptors`, 0), |
| 1639 | }, |
| 1640 | IncludedLabels: []string{"instance", "app_name"}, |
| 1641 | }, |
| 1642 | }, |
| 1643 | }, |
| 1644 | { |
| 1645 | expr: `absent(foo{job="bar"})`, |
| 1646 | output: []utils.Source{ |
| 1647 | { |
| 1648 | Type: utils.FuncSource, |
| 1649 | Returns: promParser.ValueTypeVector, |
| 1650 | Operation: "absent", |
| 1651 | Selectors: []*promParser.VectorSelector{ |
| 1652 | mustParseVector(`foo{job="bar"}`, 7), |
| 1653 | }, |
| 1654 | IncludedLabels: []string{"job"}, |
| 1655 | GuaranteedLabels: []string{"job"}, |
| 1656 | FixedLabels: true, |
| 1657 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1658 | "": { |
| 1659 | 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.", |
| 1660 | Fragment: `absent(foo{job="bar"})`, |
| 1661 | }, |
| 1662 | }, |
| 1663 | Call: &promParser.Call{ |
| 1664 | Func: &promParser.Function{ |
| 1665 | Name: "absent", |
| 1666 | ArgTypes: []promParser.ValueType{ |
| 1667 | promParser.ValueTypeVector, |
| 1668 | }, |
| 1669 | Variadic: 0, |
| 1670 | ReturnType: promParser.ValueTypeVector, |
| 1671 | }, |
| 1672 | Args: promParser.Expressions{ |
| 1673 | mustParseVector(`foo{job="bar"}`, 7), |
| 1674 | }, |
| 1675 | PosRange: posrange.PositionRange{ |
| 1676 | Start: 0, |
| 1677 | End: 22, |
| 1678 | }, |
| 1679 | }, |
| 1680 | }, |
| 1681 | }, |
| 1682 | }, |
| 1683 | { |
| 1684 | expr: `absent(foo{job="bar", cluster!="dev", instance=~".+", env="prod"})`, |
| 1685 | output: []utils.Source{ |
| 1686 | { |
| 1687 | Type: utils.FuncSource, |
| 1688 | Returns: promParser.ValueTypeVector, |
| 1689 | Operation: "absent", |
| 1690 | Selectors: []*promParser.VectorSelector{ |
| 1691 | mustParseVector(`foo{job="bar", cluster!="dev", instance=~".+", env="prod"}`, 7), |
| 1692 | }, |
| 1693 | IncludedLabels: []string{"job", "env"}, |
| 1694 | GuaranteedLabels: []string{"job", "env"}, |
| 1695 | FixedLabels: true, |
| 1696 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1697 | "": { |
| 1698 | 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.", |
| 1699 | Fragment: `absent(foo{job="bar", cluster!="dev", instance=~".+", env="prod"})`, |
| 1700 | }, |
| 1701 | }, |
| 1702 | Call: &promParser.Call{ |
| 1703 | Func: &promParser.Function{ |
| 1704 | Name: "absent", |
| 1705 | ArgTypes: []promParser.ValueType{ |
| 1706 | promParser.ValueTypeVector, |
| 1707 | }, |
| 1708 | Variadic: 0, |
| 1709 | ReturnType: promParser.ValueTypeVector, |
| 1710 | }, |
| 1711 | Args: promParser.Expressions{ |
| 1712 | mustParseVector(`foo{job="bar", cluster!="dev", instance=~".+", env="prod"}`, 7), |
| 1713 | }, |
| 1714 | PosRange: posrange.PositionRange{ |
| 1715 | Start: 0, |
| 1716 | End: 66, |
| 1717 | }, |
| 1718 | }, |
| 1719 | }, |
| 1720 | }, |
| 1721 | }, |
| 1722 | { |
| 1723 | expr: `absent(sum(foo) by(job, instance))`, |
| 1724 | output: []utils.Source{ |
| 1725 | { |
| 1726 | Type: utils.FuncSource, |
| 1727 | Returns: promParser.ValueTypeVector, |
| 1728 | Operation: "absent", |
| 1729 | Selectors: []*promParser.VectorSelector{ |
| 1730 | mustParseVector(`foo`, 11), |
| 1731 | }, |
| 1732 | FixedLabels: true, |
| 1733 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1734 | "": { |
| 1735 | 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.", |
| 1736 | Fragment: `absent(sum(foo) by(job, instance))`, |
| 1737 | }, |
| 1738 | }, |
| 1739 | Call: &promParser.Call{ |
| 1740 | Func: &promParser.Function{ |
| 1741 | Name: "absent", |
| 1742 | ArgTypes: []promParser.ValueType{ |
| 1743 | promParser.ValueTypeVector, |
| 1744 | }, |
| 1745 | Variadic: 0, |
| 1746 | ReturnType: promParser.ValueTypeVector, |
| 1747 | }, |
| 1748 | Args: promParser.Expressions{ |
| 1749 | &promParser.AggregateExpr{ |
| 1750 | Op: promParser.SUM, |
| 1751 | Expr: mustParseVector("foo", 11), |
| 1752 | Grouping: []string{"job", "instance"}, |
| 1753 | PosRange: posrange.PositionRange{ |
| 1754 | Start: 7, |
| 1755 | End: 33, |
| 1756 | }, |
| 1757 | }, |
| 1758 | }, |
| 1759 | PosRange: posrange.PositionRange{ |
| 1760 | Start: 0, |
| 1761 | End: 34, |
| 1762 | }, |
| 1763 | }, |
| 1764 | }, |
| 1765 | }, |
| 1766 | }, |
| 1767 | { |
| 1768 | expr: `absent(foo{job="prometheus", xxx="1"}) AND on(job) prometheus_build_info`, |
| 1769 | output: []utils.Source{ |
| 1770 | { |
| 1771 | Type: utils.FuncSource, |
| 1772 | Returns: promParser.ValueTypeVector, |
| 1773 | Operation: "absent", |
| 1774 | Selectors: []*promParser.VectorSelector{ |
| 1775 | mustParseVector(`foo{job="prometheus", xxx="1"}`, 7), |
| 1776 | }, |
| 1777 | IncludedLabels: []string{"job", "xxx"}, |
| 1778 | GuaranteedLabels: []string{"job", "xxx"}, |
| 1779 | FixedLabels: true, |
| 1780 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1781 | "": { |
| 1782 | 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.", |
| 1783 | Fragment: `absent(foo{job="prometheus", xxx="1"})`, |
| 1784 | }, |
| 1785 | }, |
| 1786 | Call: &promParser.Call{ |
| 1787 | Func: &promParser.Function{ |
| 1788 | Name: "absent", |
| 1789 | ArgTypes: []promParser.ValueType{ |
| 1790 | promParser.ValueTypeVector, |
| 1791 | }, |
| 1792 | Variadic: 0, |
| 1793 | ReturnType: promParser.ValueTypeVector, |
| 1794 | }, |
| 1795 | Args: promParser.Expressions{ |
| 1796 | mustParseVector(`foo{job="prometheus", xxx="1"}`, 7), |
| 1797 | }, |
| 1798 | PosRange: posrange.PositionRange{ |
| 1799 | Start: 0, |
| 1800 | End: 38, |
| 1801 | }, |
| 1802 | }, |
| 1803 | }, |
| 1804 | }, |
| 1805 | }, |
| 1806 | { |
| 1807 | expr: `1 + sum(foo) by(notjob)`, |
| 1808 | output: []utils.Source{ |
| 1809 | { |
| 1810 | Type: utils.AggregateSource, |
| 1811 | Returns: promParser.ValueTypeVector, |
| 1812 | Operation: "sum", |
| 1813 | Selectors: []*promParser.VectorSelector{ |
| 1814 | mustParseVector(`foo`, 8), |
| 1815 | }, |
| 1816 | IncludedLabels: []string{"notjob"}, |
| 1817 | FixedLabels: true, |
| 1818 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1819 | "": { |
| 1820 | Reason: "Query is using aggregation with `by(notjob)`, only labels included inside `by(...)` will be present on the results.", |
| 1821 | Fragment: `sum(foo) by(notjob)`, |
| 1822 | }, |
| 1823 | }, |
| 1824 | }, |
| 1825 | }, |
| 1826 | }, |
| 1827 | { |
| 1828 | expr: `count(node_exporter_build_info) by (instance, version) != ignoring(package,version) group_left(foo) count(deb_package_version) by (instance, version, package)`, |
| 1829 | output: []utils.Source{ |
| 1830 | { |
| 1831 | Type: utils.AggregateSource, |
| 1832 | Returns: promParser.ValueTypeVector, |
| 1833 | Operation: "count", |
| 1834 | Selectors: []*promParser.VectorSelector{ |
| 1835 | mustParseVector(`node_exporter_build_info`, 6), |
| 1836 | }, |
| 1837 | IncludedLabels: []string{"instance", "version", "foo"}, // FIXME foo shouldn't be there because count() doesn't produce it |
| 1838 | FixedLabels: true, |
| 1839 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1840 | "": { |
| 1841 | Reason: "Query is using aggregation with `by(instance, version)`, only labels included inside `by(...)` will be present on the results.", |
| 1842 | Fragment: `count(node_exporter_build_info) by (instance, version)`, |
| 1843 | }, |
| 1844 | }, |
| 1845 | }, |
| 1846 | }, |
| 1847 | }, |
| 1848 | { |
| 1849 | expr: `absent(foo) or absent(bar)`, |
| 1850 | output: []utils.Source{ |
| 1851 | { |
| 1852 | Type: utils.FuncSource, |
| 1853 | Returns: promParser.ValueTypeVector, |
| 1854 | Operation: "absent", |
| 1855 | Selectors: []*promParser.VectorSelector{ |
| 1856 | mustParseVector(`foo`, 7), |
| 1857 | }, |
| 1858 | FixedLabels: true, |
| 1859 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1860 | "": { |
| 1861 | 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.", |
| 1862 | Fragment: `absent(foo)`, |
| 1863 | }, |
| 1864 | }, |
| 1865 | Call: &promParser.Call{ |
| 1866 | Func: &promParser.Function{ |
| 1867 | Name: "absent", |
| 1868 | ArgTypes: []promParser.ValueType{ |
| 1869 | promParser.ValueTypeVector, |
| 1870 | }, |
| 1871 | Variadic: 0, |
| 1872 | ReturnType: promParser.ValueTypeVector, |
| 1873 | }, |
| 1874 | Args: promParser.Expressions{ |
| 1875 | mustParseVector(`foo`, 7), |
| 1876 | }, |
| 1877 | PosRange: posrange.PositionRange{ |
| 1878 | Start: 0, |
| 1879 | End: 11, |
| 1880 | }, |
| 1881 | }, |
| 1882 | }, |
| 1883 | { |
| 1884 | Type: utils.FuncSource, |
| 1885 | Returns: promParser.ValueTypeVector, |
| 1886 | Operation: "absent", |
| 1887 | Selectors: []*promParser.VectorSelector{ |
| 1888 | mustParseVector(`bar`, 22), |
| 1889 | }, |
| 1890 | FixedLabels: true, |
| 1891 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1892 | "": { |
| 1893 | 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.", |
| 1894 | Fragment: `absent(bar)`, |
| 1895 | }, |
| 1896 | }, |
| 1897 | Call: &promParser.Call{ |
| 1898 | Func: &promParser.Function{ |
| 1899 | Name: "absent", |
| 1900 | ArgTypes: []promParser.ValueType{ |
| 1901 | promParser.ValueTypeVector, |
| 1902 | }, |
| 1903 | Variadic: 0, |
| 1904 | ReturnType: promParser.ValueTypeVector, |
| 1905 | }, |
| 1906 | Args: promParser.Expressions{ |
| 1907 | mustParseVector(`bar`, 22), |
| 1908 | }, |
| 1909 | PosRange: posrange.PositionRange{ |
| 1910 | Start: 15, |
| 1911 | End: 26, |
| 1912 | }, |
| 1913 | }, |
| 1914 | }, |
| 1915 | }, |
| 1916 | }, |
| 1917 | { |
| 1918 | expr: `absent_over_time(foo[5m]) or absent(bar)`, |
| 1919 | output: []utils.Source{ |
| 1920 | { |
| 1921 | Type: utils.FuncSource, |
| 1922 | Returns: promParser.ValueTypeVector, |
| 1923 | Operation: "absent_over_time", |
| 1924 | Selectors: []*promParser.VectorSelector{ |
| 1925 | mustParseVector(`foo`, 17), |
| 1926 | }, |
| 1927 | FixedLabels: true, |
| 1928 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1929 | "": { |
| 1930 | 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.", |
| 1931 | Fragment: `absent_over_time(foo[5m])`, |
| 1932 | }, |
| 1933 | }, |
| 1934 | Call: &promParser.Call{ |
| 1935 | Func: &promParser.Function{ |
| 1936 | Name: "absent_over_time", |
| 1937 | ArgTypes: []promParser.ValueType{ |
| 1938 | promParser.ValueTypeMatrix, |
| 1939 | }, |
| 1940 | Variadic: 0, |
| 1941 | ReturnType: promParser.ValueTypeVector, |
| 1942 | }, |
| 1943 | Args: promParser.Expressions{ |
| 1944 | mustParseMatrix(`foo[5m]`, 17), |
| 1945 | }, |
| 1946 | PosRange: posrange.PositionRange{ |
| 1947 | Start: 0, |
| 1948 | End: 25, |
| 1949 | }, |
| 1950 | }, |
| 1951 | }, |
| 1952 | { |
| 1953 | Type: utils.FuncSource, |
| 1954 | Returns: promParser.ValueTypeVector, |
| 1955 | Operation: "absent", |
| 1956 | Selectors: []*promParser.VectorSelector{ |
| 1957 | mustParseVector(`bar`, 36), |
| 1958 | }, |
| 1959 | FixedLabels: true, |
| 1960 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 1961 | "": { |
| 1962 | 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.", |
| 1963 | Fragment: `absent(bar)`, |
| 1964 | }, |
| 1965 | }, |
| 1966 | Call: &promParser.Call{ |
| 1967 | Func: &promParser.Function{ |
| 1968 | Name: "absent", |
| 1969 | ArgTypes: []promParser.ValueType{ |
| 1970 | promParser.ValueTypeVector, |
| 1971 | }, |
| 1972 | Variadic: 0, |
| 1973 | ReturnType: promParser.ValueTypeVector, |
| 1974 | }, |
| 1975 | Args: promParser.Expressions{ |
| 1976 | mustParseVector(`bar`, 36), |
| 1977 | }, |
| 1978 | PosRange: posrange.PositionRange{ |
| 1979 | Start: 29, |
| 1980 | End: 40, |
| 1981 | }, |
| 1982 | }, |
| 1983 | }, |
| 1984 | }, |
| 1985 | }, |
| 1986 | { |
| 1987 | expr: `bar * on() group_right(cluster, env) absent(foo{job="xxx"})`, |
| 1988 | output: []utils.Source{ |
| 1989 | { |
| 1990 | Type: utils.FuncSource, |
| 1991 | Returns: promParser.ValueTypeVector, |
| 1992 | Operation: "absent", |
| 1993 | Selectors: []*promParser.VectorSelector{ |
| 1994 | mustParseVector(`foo{job="xxx"}`, 44), |
| 1995 | }, |
| 1996 | IncludedLabels: []string{"job", "cluster", "env"}, |
| 1997 | GuaranteedLabels: []string{"job"}, |
| 1998 | FixedLabels: true, |
| 1999 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2000 | "": { |
| 2001 | 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.", |
| 2002 | Fragment: `absent(foo{job="xxx"})`, |
| 2003 | }, |
| 2004 | }, |
| 2005 | Call: &promParser.Call{ |
| 2006 | Func: &promParser.Function{ |
| 2007 | Name: "absent", |
| 2008 | ArgTypes: []promParser.ValueType{ |
| 2009 | promParser.ValueTypeVector, |
| 2010 | }, |
| 2011 | Variadic: 0, |
| 2012 | ReturnType: promParser.ValueTypeVector, |
| 2013 | }, |
| 2014 | Args: promParser.Expressions{ |
| 2015 | mustParseVector(`foo{job="xxx"}`, 44), |
| 2016 | }, |
| 2017 | PosRange: posrange.PositionRange{ |
| 2018 | Start: 37, |
| 2019 | End: 59, |
| 2020 | }, |
| 2021 | }, |
| 2022 | }, |
| 2023 | }, |
| 2024 | }, |
| 2025 | { |
| 2026 | expr: `bar * on() group_right() absent(foo{job="xxx"})`, |
| 2027 | output: []utils.Source{ |
| 2028 | { |
| 2029 | Type: utils.FuncSource, |
| 2030 | Returns: promParser.ValueTypeVector, |
| 2031 | Operation: "absent", |
| 2032 | Selectors: []*promParser.VectorSelector{ |
| 2033 | mustParseVector(`foo{job="xxx"}`, 32), |
| 2034 | }, |
| 2035 | IncludedLabels: []string{"job"}, |
| 2036 | GuaranteedLabels: []string{"job"}, |
| 2037 | FixedLabels: true, |
| 2038 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2039 | "": { |
| 2040 | 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.", |
| 2041 | Fragment: `absent(foo{job="xxx"})`, |
| 2042 | }, |
| 2043 | }, |
| 2044 | Call: &promParser.Call{ |
| 2045 | Func: &promParser.Function{ |
| 2046 | Name: "absent", |
| 2047 | ArgTypes: []promParser.ValueType{ |
| 2048 | promParser.ValueTypeVector, |
| 2049 | }, |
| 2050 | Variadic: 0, |
| 2051 | ReturnType: promParser.ValueTypeVector, |
| 2052 | }, |
| 2053 | Args: promParser.Expressions{ |
| 2054 | mustParseVector(`foo{job="xxx"}`, 32), |
| 2055 | }, |
| 2056 | PosRange: posrange.PositionRange{ |
| 2057 | Start: 25, |
| 2058 | End: 47, |
| 2059 | }, |
| 2060 | }, |
| 2061 | }, |
| 2062 | }, |
| 2063 | }, |
| 2064 | { |
| 2065 | expr: "vector(1)", |
| 2066 | output: []utils.Source{ |
| 2067 | { |
| 2068 | Type: utils.FuncSource, |
| 2069 | Returns: promParser.ValueTypeVector, |
| 2070 | Operation: "vector", |
| 2071 | FixedLabels: true, |
| 2072 | AlwaysReturns: true, |
| 2073 | ReturnedNumbers: []float64{1}, |
| 2074 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2075 | "": { |
| 2076 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2077 | Fragment: `vector(1)`, |
| 2078 | }, |
| 2079 | }, |
| 2080 | Call: &promParser.Call{ |
| 2081 | Func: &promParser.Function{ |
| 2082 | Name: "vector", |
| 2083 | ArgTypes: []promParser.ValueType{ |
| 2084 | promParser.ValueTypeScalar, |
| 2085 | }, |
| 2086 | Variadic: 0, |
| 2087 | ReturnType: promParser.ValueTypeVector, |
| 2088 | }, |
| 2089 | Args: promParser.Expressions{ |
| 2090 | &promParser.NumberLiteral{ |
| 2091 | Val: 1, |
| 2092 | PosRange: posrange.PositionRange{ |
| 2093 | Start: 7, |
| 2094 | End: 8, |
| 2095 | }, |
| 2096 | }, |
| 2097 | }, |
| 2098 | PosRange: posrange.PositionRange{ |
| 2099 | Start: 0, |
| 2100 | End: 9, |
| 2101 | }, |
| 2102 | }, |
| 2103 | }, |
| 2104 | }, |
| 2105 | }, |
| 2106 | { |
| 2107 | expr: "vector(scalar(foo))", |
| 2108 | output: []utils.Source{ |
| 2109 | { |
| 2110 | Type: utils.FuncSource, |
| 2111 | Returns: promParser.ValueTypeVector, |
| 2112 | Operation: "vector", |
| 2113 | FixedLabels: true, |
| 2114 | AlwaysReturns: true, |
| 2115 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2116 | "": { |
| 2117 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2118 | Fragment: `vector(scalar(foo))`, |
| 2119 | }, |
| 2120 | }, |
| 2121 | Call: &promParser.Call{ |
| 2122 | Func: &promParser.Function{ |
| 2123 | Name: "vector", |
| 2124 | ArgTypes: []promParser.ValueType{ |
| 2125 | promParser.ValueTypeScalar, |
| 2126 | }, |
| 2127 | Variadic: 0, |
| 2128 | ReturnType: promParser.ValueTypeVector, |
| 2129 | }, |
| 2130 | Args: promParser.Expressions{ |
| 2131 | &promParser.Call{ |
| 2132 | Func: &promParser.Function{ |
| 2133 | Name: "scalar", |
| 2134 | ArgTypes: []promParser.ValueType{ |
| 2135 | promParser.ValueTypeVector, |
| 2136 | }, |
| 2137 | Variadic: 0, |
| 2138 | ReturnType: promParser.ValueTypeScalar, |
| 2139 | }, |
| 2140 | Args: promParser.Expressions{ |
| 2141 | mustParseVector("foo", 14), |
| 2142 | }, |
| 2143 | PosRange: posrange.PositionRange{ |
| 2144 | Start: 7, |
| 2145 | End: 18, |
| 2146 | }, |
| 2147 | }, |
| 2148 | }, |
| 2149 | PosRange: posrange.PositionRange{ |
| 2150 | Start: 0, |
| 2151 | End: 19, |
| 2152 | }, |
| 2153 | }, |
| 2154 | }, |
| 2155 | }, |
| 2156 | }, |
| 2157 | { |
| 2158 | expr: "vector(0.0 >= bool 0.5) == 1", |
| 2159 | output: []utils.Source{ |
| 2160 | { |
| 2161 | Type: utils.FuncSource, |
| 2162 | Returns: promParser.ValueTypeVector, |
| 2163 | Operation: "vector", |
| 2164 | FixedLabels: true, |
| 2165 | AlwaysReturns: true, |
| 2166 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2167 | "": { |
| 2168 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2169 | Fragment: `vector(0.0 >= bool 0.5)`, |
| 2170 | }, |
| 2171 | }, |
| 2172 | Call: &promParser.Call{ |
| 2173 | Func: &promParser.Function{ |
| 2174 | Name: "vector", |
| 2175 | ArgTypes: []promParser.ValueType{ |
| 2176 | promParser.ValueTypeScalar, |
| 2177 | }, |
| 2178 | Variadic: 0, |
| 2179 | ReturnType: promParser.ValueTypeVector, |
| 2180 | }, |
| 2181 | Args: promParser.Expressions{ |
| 2182 | &promParser.BinaryExpr{ |
| 2183 | Op: promParser.GTE, |
| 2184 | LHS: &promParser.NumberLiteral{ |
| 2185 | Val: 0, |
| 2186 | PosRange: posrange.PositionRange{ |
| 2187 | Start: 7, |
| 2188 | End: 10, |
| 2189 | }, |
| 2190 | }, |
| 2191 | RHS: &promParser.NumberLiteral{ |
| 2192 | Val: 0.5, |
| 2193 | PosRange: posrange.PositionRange{ |
| 2194 | Start: 20, |
| 2195 | End: 23, |
| 2196 | }, |
| 2197 | }, |
| 2198 | ReturnBool: true, |
| 2199 | }, |
| 2200 | }, |
| 2201 | PosRange: posrange.PositionRange{ |
| 2202 | Start: 0, |
| 2203 | End: 24, |
| 2204 | }, |
| 2205 | }, |
| 2206 | }, |
| 2207 | }, |
| 2208 | }, |
| 2209 | { |
| 2210 | expr: `sum_over_time(foo{job="myjob"}[5m])`, |
| 2211 | output: []utils.Source{ |
| 2212 | { |
| 2213 | Type: utils.FuncSource, |
| 2214 | Returns: promParser.ValueTypeVector, |
| 2215 | Operation: "sum_over_time", |
| 2216 | Selectors: []*promParser.VectorSelector{ |
| 2217 | mustParseVector(`foo{job="myjob"}`, 14), |
| 2218 | }, |
| 2219 | GuaranteedLabels: []string{"job"}, |
| 2220 | Call: &promParser.Call{ |
| 2221 | Func: &promParser.Function{ |
| 2222 | Name: "sum_over_time", |
| 2223 | ArgTypes: []promParser.ValueType{ |
| 2224 | promParser.ValueTypeMatrix, |
| 2225 | }, |
| 2226 | Variadic: 0, |
| 2227 | ReturnType: promParser.ValueTypeVector, |
| 2228 | }, |
| 2229 | Args: promParser.Expressions{ |
| 2230 | mustParseMatrix(`foo{job="myjob"}[5m]`, 14), |
| 2231 | }, |
| 2232 | PosRange: posrange.PositionRange{ |
| 2233 | Start: 0, |
| 2234 | End: 35, |
| 2235 | }, |
| 2236 | }, |
| 2237 | }, |
| 2238 | }, |
| 2239 | }, |
| 2240 | { |
| 2241 | expr: `days_in_month()`, |
| 2242 | output: []utils.Source{ |
| 2243 | { |
| 2244 | Type: utils.FuncSource, |
| 2245 | Returns: promParser.ValueTypeVector, |
| 2246 | Operation: "days_in_month", |
| 2247 | FixedLabels: true, |
| 2248 | AlwaysReturns: true, |
| 2249 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2250 | "": { |
| 2251 | Reason: "Calling `days_in_month()` with no arguments will return an empty time series with no labels.", |
| 2252 | Fragment: `days_in_month()`, |
| 2253 | }, |
| 2254 | }, |
| 2255 | Call: &promParser.Call{ |
| 2256 | Func: &promParser.Function{ |
| 2257 | Name: "days_in_month", |
| 2258 | ArgTypes: []promParser.ValueType{ |
| 2259 | promParser.ValueTypeVector, |
| 2260 | }, |
| 2261 | Variadic: 1, |
| 2262 | ReturnType: promParser.ValueTypeVector, |
| 2263 | }, |
| 2264 | Args: promParser.Expressions{}, |
| 2265 | PosRange: posrange.PositionRange{ |
| 2266 | Start: 0, |
| 2267 | End: 15, |
| 2268 | }, |
| 2269 | }, |
| 2270 | }, |
| 2271 | }, |
| 2272 | }, |
| 2273 | { |
| 2274 | expr: `days_in_month(foo{job="foo"})`, |
| 2275 | output: []utils.Source{ |
| 2276 | { |
| 2277 | Type: utils.FuncSource, |
| 2278 | Returns: promParser.ValueTypeVector, |
| 2279 | Operation: "days_in_month", |
| 2280 | Selectors: []*promParser.VectorSelector{ |
| 2281 | mustParseVector(`foo{job="foo"}`, 14), |
| 2282 | }, |
| 2283 | GuaranteedLabels: []string{"job"}, |
| 2284 | Call: &promParser.Call{ |
| 2285 | Func: &promParser.Function{ |
| 2286 | Name: "days_in_month", |
| 2287 | ArgTypes: []promParser.ValueType{ |
| 2288 | promParser.ValueTypeVector, |
| 2289 | }, |
| 2290 | Variadic: 1, |
| 2291 | ReturnType: promParser.ValueTypeVector, |
| 2292 | }, |
| 2293 | Args: promParser.Expressions{ |
| 2294 | mustParseVector(`foo{job="foo"}`, 14), |
| 2295 | }, |
| 2296 | PosRange: posrange.PositionRange{ |
| 2297 | Start: 0, |
| 2298 | End: 29, |
| 2299 | }, |
| 2300 | }, |
| 2301 | }, |
| 2302 | }, |
| 2303 | }, |
| 2304 | { |
| 2305 | expr: `label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")`, |
| 2306 | output: []utils.Source{ |
| 2307 | { |
| 2308 | Type: utils.FuncSource, |
| 2309 | Returns: promParser.ValueTypeVector, |
| 2310 | Operation: "label_replace", |
| 2311 | Selectors: []*promParser.VectorSelector{ |
| 2312 | mustParseVector(`up{job="api-server",service="a:c"}`, 14), |
| 2313 | }, |
| 2314 | GuaranteedLabels: []string{"job", "service", "foo"}, |
| 2315 | Call: &promParser.Call{ |
| 2316 | Func: &promParser.Function{ |
| 2317 | Name: "label_replace", |
| 2318 | ArgTypes: []promParser.ValueType{ |
| 2319 | promParser.ValueTypeVector, |
| 2320 | promParser.ValueTypeString, |
| 2321 | promParser.ValueTypeString, |
| 2322 | promParser.ValueTypeString, |
| 2323 | promParser.ValueTypeString, |
| 2324 | }, |
| 2325 | Variadic: 0, |
| 2326 | ReturnType: promParser.ValueTypeVector, |
| 2327 | }, |
| 2328 | Args: promParser.Expressions{ |
| 2329 | mustParseVector(`up{job="api-server",service="a:c"}`, 14), |
| 2330 | &promParser.StringLiteral{ |
| 2331 | Val: "foo", |
| 2332 | PosRange: posrange.PositionRange{ |
| 2333 | Start: 50, |
| 2334 | End: 55, |
| 2335 | }, |
| 2336 | }, |
| 2337 | &promParser.StringLiteral{ |
| 2338 | Val: "$1", |
| 2339 | PosRange: posrange.PositionRange{ |
| 2340 | Start: 57, |
| 2341 | End: 61, |
| 2342 | }, |
| 2343 | }, |
| 2344 | &promParser.StringLiteral{ |
| 2345 | Val: "service", |
| 2346 | PosRange: posrange.PositionRange{ |
| 2347 | Start: 63, |
| 2348 | End: 72, |
| 2349 | }, |
| 2350 | }, |
| 2351 | &promParser.StringLiteral{ |
| 2352 | Val: "(.*):.*", |
| 2353 | PosRange: posrange.PositionRange{ |
| 2354 | Start: 74, |
| 2355 | End: 83, |
| 2356 | }, |
| 2357 | }, |
| 2358 | }, |
| 2359 | PosRange: posrange.PositionRange{ |
| 2360 | Start: 0, |
| 2361 | End: 84, |
| 2362 | }, |
| 2363 | }, |
| 2364 | }, |
| 2365 | }, |
| 2366 | }, |
| 2367 | { |
| 2368 | expr: `(time() - my_metric) > 5*3600`, |
| 2369 | output: []utils.Source{ |
| 2370 | { |
| 2371 | Type: utils.SelectorSource, |
| 2372 | Returns: promParser.ValueTypeVector, |
| 2373 | Selectors: []*promParser.VectorSelector{ |
| 2374 | mustParseVector("my_metric", 10), |
| 2375 | }, |
| 2376 | }, |
| 2377 | }, |
| 2378 | }, |
| 2379 | { |
| 2380 | expr: `up{instance="a", job="prometheus"} * ignoring(job) up{instance="a", job="pint"}`, |
| 2381 | output: []utils.Source{ |
| 2382 | { |
| 2383 | Type: utils.SelectorSource, |
| 2384 | Returns: promParser.ValueTypeVector, |
| 2385 | Operation: promParser.CardOneToOne.String(), |
| 2386 | Selectors: []*promParser.VectorSelector{ |
| 2387 | mustParseVector(`up{instance="a", job="prometheus"}`, 0), |
| 2388 | }, |
| 2389 | GuaranteedLabels: []string{"instance"}, |
| 2390 | ExcludedLabels: []string{"job"}, |
| 2391 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2392 | "job": { |
| 2393 | Reason: "Query is using one-to-one vector matching with `ignoring(job)`, all labels included inside `ignoring(...)` will be removed on the results.", |
| 2394 | Fragment: `up{instance="a", job="prometheus"} * ignoring(job) up{instance="a", job="pint"}`, |
| 2395 | }, |
| 2396 | }, |
| 2397 | }, |
| 2398 | }, |
| 2399 | }, |
| 2400 | { |
| 2401 | expr: ` |
| 2402 | avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"}) |
| 2403 | < 0.5 > 0 |
| 2404 | or sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"}) |
| 2405 | < on() count(colo_router_tier:disabled_pops:max{tier="1",router=~"edge.*"}) * 0.4 > 0 |
| 2406 | or avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"}) |
| 2407 | < 0.1 > 0 |
| 2408 | `, |
| 2409 | output: []utils.Source{ |
| 2410 | { |
| 2411 | Type: utils.AggregateSource, |
| 2412 | Returns: promParser.ValueTypeVector, |
| 2413 | Operation: "avg", |
| 2414 | Selectors: []*promParser.VectorSelector{ |
| 2415 | mustParseVector(`router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"}`, 41), |
| 2416 | }, |
| 2417 | ExcludedLabels: []string{"router", "colo_id", "instance"}, |
| 2418 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2419 | "router": { |
| 2420 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2421 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"})`, |
| 2422 | }, |
| 2423 | "colo_id": { |
| 2424 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2425 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"})`, |
| 2426 | }, |
| 2427 | "instance": { |
| 2428 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2429 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case!~".*offpeak.*"})`, |
| 2430 | }, |
| 2431 | }, |
| 2432 | }, |
| 2433 | { |
| 2434 | Type: utils.AggregateSource, |
| 2435 | Returns: promParser.ValueTypeVector, |
| 2436 | Operation: "sum", |
| 2437 | Selectors: []*promParser.VectorSelector{ |
| 2438 | mustParseVector(`router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"}`, 155), |
| 2439 | }, |
| 2440 | GuaranteedLabels: []string{"cidr_use_case"}, |
| 2441 | ExcludedLabels: []string{"router", "colo_id", "instance"}, |
| 2442 | FixedLabels: true, |
| 2443 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2444 | "router": { |
| 2445 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2446 | Fragment: `sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"})`, |
| 2447 | }, |
| 2448 | "colo_id": { |
| 2449 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2450 | Fragment: `sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"})`, |
| 2451 | }, |
| 2452 | "instance": { |
| 2453 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2454 | Fragment: `sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*tier1.*"})`, |
| 2455 | }, |
| 2456 | "": { |
| 2457 | Reason: "Query is using one-to-one vector matching with `on()`, only labels included inside `on(...)` will be present on the results.", |
| 2458 | Fragment: "sum without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~\".*tier1.*\"})\n< on() count(colo_router_tier:disabled_pops:max{tier=\"1\",router=~\"edge.*\"}) * 0.4", |
| 2459 | }, |
| 2460 | }, |
| 2461 | }, |
| 2462 | { |
| 2463 | Type: utils.AggregateSource, |
| 2464 | Returns: promParser.ValueTypeVector, |
| 2465 | Operation: "avg", |
| 2466 | Selectors: []*promParser.VectorSelector{ |
| 2467 | mustParseVector(`router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"}`, 343), |
| 2468 | }, |
| 2469 | GuaranteedLabels: []string{"cidr_use_case"}, |
| 2470 | ExcludedLabels: []string{"router", "colo_id", "instance"}, |
| 2471 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2472 | "router": { |
| 2473 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2474 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"})`, |
| 2475 | }, |
| 2476 | "colo_id": { |
| 2477 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2478 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"})`, |
| 2479 | }, |
| 2480 | "instance": { |
| 2481 | Reason: "Query is using aggregation with `without(router, colo_id, instance)`, all labels included inside `without(...)` will be removed from the results.", |
| 2482 | Fragment: `avg without(router, colo_id, instance) (router_anycast_prefix_enabled{cidr_use_case=~".*regional.*"})`, |
| 2483 | }, |
| 2484 | }, |
| 2485 | }, |
| 2486 | }, |
| 2487 | }, |
| 2488 | { |
| 2489 | expr: `label_replace(sum(foo) without(instance), "instance", "none", "", "")`, |
| 2490 | output: []utils.Source{ |
| 2491 | { |
| 2492 | Type: utils.FuncSource, |
| 2493 | Returns: promParser.ValueTypeVector, |
| 2494 | Operation: "label_replace", |
| 2495 | Selectors: []*promParser.VectorSelector{ |
| 2496 | mustParseVector(`foo`, 18), |
| 2497 | }, |
| 2498 | GuaranteedLabels: []string{"instance"}, |
| 2499 | Call: &promParser.Call{ |
| 2500 | Func: &promParser.Function{ |
| 2501 | Name: "label_replace", |
| 2502 | ArgTypes: []promParser.ValueType{ |
| 2503 | promParser.ValueTypeVector, |
| 2504 | promParser.ValueTypeString, |
| 2505 | promParser.ValueTypeString, |
| 2506 | promParser.ValueTypeString, |
| 2507 | promParser.ValueTypeString, |
| 2508 | }, |
| 2509 | Variadic: 0, |
| 2510 | ReturnType: promParser.ValueTypeVector, |
| 2511 | }, |
| 2512 | Args: promParser.Expressions{ |
| 2513 | &promParser.AggregateExpr{ |
| 2514 | Op: promParser.SUM, |
| 2515 | Expr: mustParseVector("foo", 18), |
| 2516 | Grouping: []string{"instance"}, |
| 2517 | Without: true, |
| 2518 | PosRange: posrange.PositionRange{ |
| 2519 | Start: 14, |
| 2520 | End: 40, |
| 2521 | }, |
| 2522 | }, |
| 2523 | &promParser.StringLiteral{ |
| 2524 | Val: "instance", |
| 2525 | PosRange: posrange.PositionRange{ |
| 2526 | Start: 42, |
| 2527 | End: 52, |
| 2528 | }, |
| 2529 | }, |
| 2530 | &promParser.StringLiteral{ |
| 2531 | Val: "none", |
| 2532 | PosRange: posrange.PositionRange{ |
| 2533 | Start: 54, |
| 2534 | End: 60, |
| 2535 | }, |
| 2536 | }, |
| 2537 | &promParser.StringLiteral{ |
| 2538 | Val: "", |
| 2539 | PosRange: posrange.PositionRange{ |
| 2540 | Start: 62, |
| 2541 | End: 64, |
| 2542 | }, |
| 2543 | }, |
| 2544 | &promParser.StringLiteral{ |
| 2545 | Val: "", |
| 2546 | PosRange: posrange.PositionRange{ |
| 2547 | Start: 66, |
| 2548 | End: 68, |
| 2549 | }, |
| 2550 | }, |
| 2551 | }, |
| 2552 | PosRange: posrange.PositionRange{ |
| 2553 | Start: 0, |
| 2554 | End: 69, |
| 2555 | }, |
| 2556 | }, |
| 2557 | }, |
| 2558 | }, |
| 2559 | }, |
| 2560 | { |
| 2561 | expr: ` |
| 2562 | sum by (region, target, colo_name) ( |
| 2563 | sum_over_time(probe_success{job="abc"}[5m]) |
| 2564 | or |
| 2565 | vector(1) |
| 2566 | ) == 0`, |
| 2567 | output: []utils.Source{ |
| 2568 | { |
| 2569 | Type: utils.AggregateSource, |
| 2570 | Returns: promParser.ValueTypeVector, |
| 2571 | Operation: "sum", |
| 2572 | Selectors: []*promParser.VectorSelector{ |
| 2573 | mustParseVector(`probe_success{job="abc"}`, 56), |
| 2574 | }, |
| 2575 | IncludedLabels: []string{"region", "target", "colo_name"}, |
| 2576 | FixedLabels: true, |
| 2577 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2578 | "": { |
| 2579 | Reason: "Query is using aggregation with `by(region, target, colo_name)`, only labels included inside `by(...)` will be present on the results.", |
| 2580 | Fragment: "sum by (region, target, colo_name) (\n sum_over_time(probe_success{job=\"abc\"}[5m])\n\tor\n\tvector(1)\n)", |
| 2581 | }, |
| 2582 | }, |
| 2583 | }, |
| 2584 | { |
| 2585 | Type: utils.AggregateSource, |
| 2586 | Returns: promParser.ValueTypeVector, |
| 2587 | Operation: "sum", |
| 2588 | FixedLabels: true, |
| 2589 | AlwaysReturns: true, |
| 2590 | IsDead: true, |
| 2591 | ReturnedNumbers: []float64{1}, |
| 2592 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2593 | "": { |
| 2594 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2595 | Fragment: "vector(1)", |
| 2596 | }, |
| 2597 | }, |
| 2598 | }, |
| 2599 | }, |
| 2600 | }, |
| 2601 | { |
| 2602 | expr: `vector(1) or foo`, |
| 2603 | output: []utils.Source{ |
| 2604 | { |
| 2605 | Type: utils.FuncSource, |
| 2606 | Returns: promParser.ValueTypeVector, |
| 2607 | Operation: "vector", |
| 2608 | FixedLabels: true, |
| 2609 | AlwaysReturns: true, |
| 2610 | ReturnedNumbers: []float64{1}, |
| 2611 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2612 | "": { |
| 2613 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2614 | Fragment: "vector(1)", |
| 2615 | }, |
| 2616 | }, |
| 2617 | Call: &promParser.Call{ |
| 2618 | Func: &promParser.Function{ |
| 2619 | Name: "vector", |
| 2620 | ArgTypes: []promParser.ValueType{ |
| 2621 | promParser.ValueTypeScalar, |
| 2622 | }, |
| 2623 | Variadic: 0, |
| 2624 | ReturnType: promParser.ValueTypeVector, |
| 2625 | }, |
| 2626 | Args: promParser.Expressions{ |
| 2627 | &promParser.NumberLiteral{ |
| 2628 | Val: 1, |
| 2629 | PosRange: posrange.PositionRange{ |
| 2630 | Start: 7, |
| 2631 | End: 8, |
| 2632 | }, |
| 2633 | }, |
| 2634 | }, |
| 2635 | PosRange: posrange.PositionRange{ |
| 2636 | Start: 0, |
| 2637 | End: 9, |
| 2638 | }, |
| 2639 | }, |
| 2640 | }, |
| 2641 | { |
| 2642 | Type: utils.SelectorSource, |
| 2643 | Operation: promParser.CardManyToMany.String(), |
| 2644 | Returns: promParser.ValueTypeVector, |
| 2645 | Selectors: []*promParser.VectorSelector{ |
| 2646 | mustParseVector("foo", 13), |
| 2647 | }, |
| 2648 | IsDead: true, |
| 2649 | }, |
| 2650 | }, |
| 2651 | }, |
| 2652 | { |
| 2653 | expr: `vector(0) > 0`, |
| 2654 | output: []utils.Source{ |
| 2655 | { |
| 2656 | Type: utils.FuncSource, |
| 2657 | Returns: promParser.ValueTypeVector, |
| 2658 | Operation: "vector", |
| 2659 | FixedLabels: true, |
| 2660 | AlwaysReturns: true, |
| 2661 | ReturnedNumbers: []float64{0}, |
| 2662 | IsDead: true, |
| 2663 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2664 | "": { |
| 2665 | Reason: "Calling `vector()` will return a vector value with no labels.", |
| 2666 | Fragment: "vector(0)", |
| 2667 | }, |
| 2668 | }, |
| 2669 | Call: &promParser.Call{ |
| 2670 | Func: &promParser.Function{ |
| 2671 | Name: "vector", |
| 2672 | ArgTypes: []promParser.ValueType{ |
| 2673 | promParser.ValueTypeScalar, |
| 2674 | }, |
| 2675 | Variadic: 0, |
| 2676 | ReturnType: promParser.ValueTypeVector, |
| 2677 | }, |
| 2678 | Args: promParser.Expressions{ |
| 2679 | &promParser.NumberLiteral{ |
| 2680 | Val: 0, |
| 2681 | PosRange: posrange.PositionRange{ |
| 2682 | Start: 7, |
| 2683 | End: 8, |
| 2684 | }, |
| 2685 | }, |
| 2686 | }, |
| 2687 | PosRange: posrange.PositionRange{ |
| 2688 | Start: 0, |
| 2689 | End: 9, |
| 2690 | }, |
| 2691 | }, |
| 2692 | }, |
| 2693 | }, |
| 2694 | }, |
| 2695 | { |
| 2696 | expr: `sum(foo or vector(0)) > 0`, |
| 2697 | output: []utils.Source{ |
| 2698 | { |
| 2699 | Type: utils.AggregateSource, |
| 2700 | Returns: promParser.ValueTypeVector, |
| 2701 | Operation: "sum", |
| 2702 | Selectors: []*promParser.VectorSelector{ |
| 2703 | mustParseVector(`foo`, 4), |
| 2704 | }, |
| 2705 | FixedLabels: true, |
| 2706 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2707 | "": { |
| 2708 | Reason: "Query is using aggregation that removes all labels.", |
| 2709 | Fragment: `sum(foo or vector(0))`, |
| 2710 | }, |
| 2711 | }, |
| 2712 | }, |
| 2713 | { |
| 2714 | Type: utils.AggregateSource, |
| 2715 | Returns: promParser.ValueTypeVector, |
| 2716 | Operation: "sum", |
| 2717 | FixedLabels: true, |
| 2718 | AlwaysReturns: true, |
| 2719 | ReturnedNumbers: []float64{0}, |
| 2720 | IsDead: true, |
| 2721 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2722 | "": { |
| 2723 | Reason: "Query is using aggregation that removes all labels.", |
| 2724 | Fragment: "sum(foo or vector(0))", |
| 2725 | }, |
| 2726 | }, |
| 2727 | }, |
| 2728 | }, |
| 2729 | }, |
| 2730 | { |
| 2731 | expr: `(sum(foo or vector(1)) > 0) == 2`, |
| 2732 | output: []utils.Source{ |
| 2733 | { |
| 2734 | Type: utils.AggregateSource, |
| 2735 | Returns: promParser.ValueTypeVector, |
| 2736 | Operation: "sum", |
| 2737 | Selectors: []*promParser.VectorSelector{ |
| 2738 | mustParseVector(`foo`, 5), |
| 2739 | }, |
| 2740 | FixedLabels: true, |
| 2741 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2742 | "": { |
| 2743 | Reason: "Query is using aggregation that removes all labels.", |
| 2744 | Fragment: `sum(foo or vector(1))`, |
| 2745 | }, |
| 2746 | }, |
| 2747 | }, |
| 2748 | { |
| 2749 | Type: utils.AggregateSource, |
| 2750 | Returns: promParser.ValueTypeVector, |
| 2751 | Operation: "sum", |
| 2752 | FixedLabels: true, |
| 2753 | AlwaysReturns: true, |
| 2754 | ReturnedNumbers: []float64{1}, |
| 2755 | IsDead: true, |
| 2756 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2757 | "": { |
| 2758 | Reason: "Query is using aggregation that removes all labels.", |
| 2759 | Fragment: "sum(foo or vector(1))", |
| 2760 | }, |
| 2761 | }, |
| 2762 | }, |
| 2763 | }, |
| 2764 | }, |
| 2765 | { |
| 2766 | expr: `(sum(foo or vector(1)) > 0) != 2`, |
| 2767 | output: []utils.Source{ |
| 2768 | { |
| 2769 | Type: utils.AggregateSource, |
| 2770 | Returns: promParser.ValueTypeVector, |
| 2771 | Operation: "sum", |
| 2772 | Selectors: []*promParser.VectorSelector{ |
| 2773 | mustParseVector(`foo`, 5), |
| 2774 | }, |
| 2775 | FixedLabels: true, |
| 2776 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2777 | "": { |
| 2778 | Reason: "Query is using aggregation that removes all labels.", |
| 2779 | Fragment: `sum(foo or vector(1))`, |
| 2780 | }, |
| 2781 | }, |
| 2782 | }, |
| 2783 | { |
| 2784 | Type: utils.AggregateSource, |
| 2785 | Returns: promParser.ValueTypeVector, |
| 2786 | Operation: "sum", |
| 2787 | FixedLabels: true, |
| 2788 | AlwaysReturns: true, |
| 2789 | ReturnedNumbers: []float64{1}, |
| 2790 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2791 | "": { |
| 2792 | Reason: "Query is using aggregation that removes all labels.", |
| 2793 | Fragment: "sum(foo or vector(1))", |
| 2794 | }, |
| 2795 | }, |
| 2796 | }, |
| 2797 | }, |
| 2798 | }, |
| 2799 | { |
| 2800 | expr: `(sum(foo or vector(2)) > 0) != 2`, |
| 2801 | output: []utils.Source{ |
| 2802 | { |
| 2803 | Type: utils.AggregateSource, |
| 2804 | Returns: promParser.ValueTypeVector, |
| 2805 | Operation: "sum", |
| 2806 | Selectors: []*promParser.VectorSelector{ |
| 2807 | mustParseVector(`foo`, 5), |
| 2808 | }, |
| 2809 | FixedLabels: true, |
| 2810 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2811 | "": { |
| 2812 | Reason: "Query is using aggregation that removes all labels.", |
| 2813 | Fragment: `sum(foo or vector(2))`, |
| 2814 | }, |
| 2815 | }, |
| 2816 | }, |
| 2817 | { |
| 2818 | Type: utils.AggregateSource, |
| 2819 | Returns: promParser.ValueTypeVector, |
| 2820 | Operation: "sum", |
| 2821 | FixedLabels: true, |
| 2822 | AlwaysReturns: true, |
| 2823 | ReturnedNumbers: []float64{2}, |
| 2824 | IsDead: true, |
| 2825 | ExcludeReason: map[string]utils.ExcludedLabel{ |
| 2826 | "": { |
| 2827 | Reason: "Query is using aggregation that removes all labels.", |
| 2828 | Fragment: "sum(foo or vector(2))", |
| 2829 | }, |
| 2830 | }, |
| 2831 | }, |
| 2832 | }, |
| 2833 | }, |
| 2834 | } |
| 2835 | |
| 2836 | for _, tc := range testCases { |
| 2837 | t.Run(tc.expr, func(t *testing.T) { |
| 2838 | n, err := parser.DecodeExpr(tc.expr) |
| 2839 | if err != nil { |
| 2840 | t.Error(err) |
| 2841 | t.FailNow() |
| 2842 | } |
| 2843 | output := utils.LabelsSource(tc.expr, n.Expr) |
| 2844 | require.Len(t, output, len(tc.output)) |
| 2845 | for i := range len(tc.output) { |
| 2846 | require.EqualExportedValues(t, tc.output[i], output[i], "Mismatch at index %d", i) |
| 2847 | } |
| 2848 | }) |
| 2849 | } |
| 2850 | } |
| 2851 | |
| 2852 | func TestLabelsSourceCallCoverage(t *testing.T) { |
| 2853 | for name, def := range promParser.Functions { |
| 2854 | t.Run(name, func(t *testing.T) { |
| 2855 | if def.Experimental { |
| 2856 | t.SkipNow() |
| 2857 | } |
| 2858 | |
| 2859 | var b strings.Builder |
| 2860 | b.WriteString(name) |
| 2861 | b.WriteRune('(') |
| 2862 | for i, at := range def.ArgTypes { |
| 2863 | if i > 0 { |
| 2864 | b.WriteString(", ") |
| 2865 | } |
| 2866 | switch at { |
| 2867 | case promParser.ValueTypeNone: |
| 2868 | case promParser.ValueTypeScalar: |
| 2869 | b.WriteRune('1') |
| 2870 | case promParser.ValueTypeVector: |
| 2871 | b.WriteString("http_requests_total") |
| 2872 | case promParser.ValueTypeMatrix: |
| 2873 | b.WriteString("http_requests_total[2m]") |
| 2874 | case promParser.ValueTypeString: |
| 2875 | b.WriteString(`"foo"`) |
| 2876 | } |
| 2877 | } |
| 2878 | b.WriteRune(')') |
| 2879 | |
| 2880 | n, err := parser.DecodeExpr(b.String()) |
| 2881 | if err != nil { |
| 2882 | t.Error(err) |
| 2883 | t.FailNow() |
| 2884 | } |
| 2885 | output := utils.LabelsSource(b.String(), n.Expr) |
| 2886 | require.Len(t, output, 1) |
| 2887 | require.NotNil(t, output[0].Call, "no call detected in: %q ~> %+v", b.String(), output) |
| 2888 | require.Equal(t, name, output[0].Operation) |
| 2889 | require.Equal(t, def.ReturnType, output[0].Returns, "incorrect return type on Source{}") |
| 2890 | }) |
| 2891 | } |
| 2892 | } |
| 2893 | |
| 2894 | func TestLabelsSourceCallCoverageFail(t *testing.T) { |
| 2895 | n := &parser.PromQLNode{ |
| 2896 | Expr: &promParser.Call{ |
| 2897 | Func: &promParser.Function{ |
| 2898 | Name: "fake_call", |
| 2899 | }, |
| 2900 | }, |
| 2901 | } |
| 2902 | output := utils.LabelsSource("fake_call()", n.Expr) |
| 2903 | require.Len(t, output, 1) |
| 2904 | require.Nil(t, output[0].Call, "no call should have been detected in fake function") |
| 2905 | } |
| 2906 | |