load 5m http_requests{job="api-server", instance="0", group="production"} 0+10x10 http_requests{job="api-server", instance="1", group="production"} 0+20x10 http_requests{job="api-server", instance="0", group="canary"} 0+30x10 http_requests{job="api-server", instance="1", group="canary"} 0+40x10 http_requests{job="app-server", instance="0", group="production"} 0+50x10 http_requests{job="app-server", instance="1", group="production"} 0+60x10 http_requests{job="app-server", instance="0", group="canary"} 0+70x10 http_requests{job="app-server", instance="1", group="canary"} 0+80x10 load 5m x{y="testvalue"} 0+10x10 load 5m testcounter_reset_middle 0+10x4 0+10x5 testcounter_reset_end 0+10x9 0 10 load 5m label_grouping_test{a="aa", b="bb"} 0+10x10 label_grouping_test{a="a", b="abb"} 0+20x10 load 5m vector_matching_a{l="x"} 0+1x100 vector_matching_a{l="y"} 0+2x50 vector_matching_b{l="x"} 0+4x25 load 5m cpu_count{instance="0", type="numa"} 0+30x10 cpu_count{instance="0", type="smp"} 0+10x20 cpu_count{instance="1", type="smp"} 0+20x10 eval instant at 50m SUM(http_requests) {} 3600 eval instant at 50m SUM(http_requests{instance="0"}) BY(job) {job="api-server"} 400 {job="app-server"} 1200 eval instant at 50m SUM(http_requests{instance="0"}) BY(job) KEEP_COMMON {instance="0", job="api-server"} 400 {instance="0", job="app-server"} 1200 eval instant at 50m SUM(http_requests) BY (job) {job="api-server"} 1000 {job="app-server"} 2600 # Non-existent labels mentioned in BY-clauses shouldn't propagate to output. eval instant at 50m SUM(http_requests) BY (job, nonexistent) {job="api-server"} 1000 {job="app-server"} 2600 eval instant at 50m COUNT(http_requests) BY (job) {job="api-server"} 4 {job="app-server"} 4 eval instant at 50m SUM(http_requests) BY (job, group) {group="canary", job="api-server"} 700 {group="canary", job="app-server"} 1500 {group="production", job="api-server"} 300 {group="production", job="app-server"} 1100 eval instant at 50m AVG(http_requests) BY (job) {job="api-server"} 250 {job="app-server"} 650 eval instant at 50m MIN(http_requests) BY (job) {job="api-server"} 100 {job="app-server"} 500 eval instant at 50m MAX(http_requests) BY (job) {job="api-server"} 400 {job="app-server"} 800 eval instant at 50m SUM(http_requests) BY (job) - COUNT(http_requests) BY (job) {job="api-server"} 996 {job="app-server"} 2596 eval instant at 50m 2 - SUM(http_requests) BY (job) {job="api-server"} -998 {job="app-server"} -2598 eval instant at 50m 1000 / SUM(http_requests) BY (job) {job="api-server"} 1 {job="app-server"} 0.38461538461538464 eval instant at 50m SUM(http_requests) BY (job) - 2 {job="api-server"} 998 {job="app-server"} 2598 eval instant at 50m SUM(http_requests) BY (job) % 3 {job="api-server"} 1 {job="app-server"} 2 eval instant at 50m SUM(http_requests) BY (job) / 0 {job="api-server"} +Inf {job="app-server"} +Inf eval instant at 50m SUM(http_requests) BY (job) + SUM(http_requests) BY (job) {job="api-server"} 2000 {job="app-server"} 5200 eval instant at 50m http_requests{job="api-server", group="canary"} http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="canary", instance="1", job="api-server"} 400 eval instant at 50m http_requests{job="api-server", group="canary"} + rate(http_requests{job="api-server"}[5m]) * 5 * 60 {group="canary", instance="0", job="api-server"} 330 {group="canary", instance="1", job="api-server"} 440 eval instant at 50m rate(http_requests[25m]) * 25 * 60 {group="canary", instance="0", job="api-server"} 150 {group="canary", instance="0", job="app-server"} 350 {group="canary", instance="1", job="api-server"} 200 {group="canary", instance="1", job="app-server"} 400 {group="production", instance="0", job="api-server"} 50 {group="production", instance="0", job="app-server"} 249.99999999999997 {group="production", instance="1", job="api-server"} 100 {group="production", instance="1", job="app-server"} 300 eval_ordered instant at 50m sort(http_requests) http_requests{group="production", instance="0", job="api-server"} 100 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="canary", instance="1", job="api-server"} 400 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="app-server"} 600 http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="canary", instance="1", job="app-server"} 800 eval_ordered instant at 50m sort(0 / round(http_requests, 400) + http_requests) {group="production", instance="0", job="api-server"} NaN {group="production", instance="1", job="api-server"} 200 {group="canary", instance="0", job="api-server"} 300 {group="canary", instance="1", job="api-server"} 400 {group="production", instance="0", job="app-server"} 500 {group="production", instance="1", job="app-server"} 600 {group="canary", instance="0", job="app-server"} 700 {group="canary", instance="1", job="app-server"} 800 eval_ordered instant at 50m sort_desc(http_requests) http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="production", instance="1", job="app-server"} 600 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="canary", instance="1", job="api-server"} 400 http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="0", job="api-server"} 100 eval_ordered instant at 50m topk(3, http_requests) http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="production", instance="1", job="app-server"} 600 eval_ordered instant at 50m topk(5, http_requests{group="canary",job="app-server"}) http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="canary", instance="0", job="app-server"} 700 eval_ordered instant at 50m bottomk(3, http_requests) http_requests{group="production", instance="0", job="api-server"} 100 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="canary", instance="0", job="api-server"} 300 eval_ordered instant at 50m bottomk(5, http_requests{group="canary",job="app-server"}) http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="canary", instance="1", job="app-server"} 800 # Single-letter label names and values. eval instant at 50m x{y="testvalue"} x{y="testvalue"} 100 # Lower-cased aggregation operators should work too. eval instant at 50m sum(http_requests) by (job) + min(http_requests) by (job) + max(http_requests) by (job) + avg(http_requests) by (job) {job="app-server"} 4550 {job="api-server"} 1750 # Deltas should be adjusted for target interval vs. samples under target interval. eval instant at 50m delta(http_requests{group="canary", instance="1", job="app-server"}[18m]) {group="canary", instance="1", job="app-server"} 288 # Rates should calculate per-second rates. eval instant at 50m rate(http_requests{group="canary", instance="1", job="app-server"}[60m]) {group="canary", instance="1", job="app-server"} 0.26666666666666666 # Counter resets at in the middle of range are handled correctly by rate(). eval instant at 50m rate(testcounter_reset_middle[60m]) {} 0.03 # Counter resets at end of range are ignored by rate(). eval instant at 50m rate(testcounter_reset_end[5m]) {} 0 # count_scalar for a non-empty vector should return scalar element count. eval instant at 50m count_scalar(http_requests) 8 # count_scalar for an empty vector should return scalar 0. eval instant at 50m count_scalar(nonexistent) 0 eval instant at 50m http_requests{group!="canary"} http_requests{group="production", instance="1", job="app-server"} 600 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="0", job="api-server"} 100 eval instant at 50m http_requests{job=~"server",group!="canary"} http_requests{group="production", instance="1", job="app-server"} 600 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="0", job="api-server"} 100 eval instant at 50m http_requests{job!~"api",group!="canary"} http_requests{group="production", instance="1", job="app-server"} 600 http_requests{group="production", instance="0", job="app-server"} 500 eval instant at 50m count_scalar(http_requests{job=~"^server$"}) 0 eval instant at 50m http_requests{group="production",job=~"^api"} http_requests{group="production", instance="0", job="api-server"} 100 http_requests{group="production", instance="1", job="api-server"} 200 eval instant at 50m abs(-1 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 100 {group="production", instance="1", job="api-server"} 200 eval instant at 50m floor(0.004 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 0 {group="production", instance="1", job="api-server"} 0 eval instant at 50m ceil(0.004 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 1 {group="production", instance="1", job="api-server"} 1 eval instant at 50m round(0.004 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 0 {group="production", instance="1", job="api-server"} 1 # Round should correctly handle negative numbers. eval instant at 50m round(-1 * (0.004 * http_requests{group="production",job="api-server"})) {group="production", instance="0", job="api-server"} 0 {group="production", instance="1", job="api-server"} -1 # Round should round half up. eval instant at 50m round(0.005 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 1 {group="production", instance="1", job="api-server"} 1 eval instant at 50m round(-1 * (0.005 * http_requests{group="production",job="api-server"})) {group="production", instance="0", job="api-server"} 0 {group="production", instance="1", job="api-server"} -1 eval instant at 50m round(1 + 0.005 * http_requests{group="production",job="api-server"}) {group="production", instance="0", job="api-server"} 2 {group="production", instance="1", job="api-server"} 2 eval instant at 50m round(-1 * (1 + 0.005 * http_requests{group="production",job="api-server"})) {group="production", instance="0", job="api-server"} -1 {group="production", instance="1", job="api-server"} -2 # Round should accept the number to round nearest to. eval instant at 50m round(0.0005 * http_requests{group="production",job="api-server"}, 0.1) {group="production", instance="0", job="api-server"} 0.1 {group="production", instance="1", job="api-server"} 0.1 eval instant at 50m round(2.1 + 0.0005 * http_requests{group="production",job="api-server"}, 0.1) {group="production", instance="0", job="api-server"} 2.2 {group="production", instance="1", job="api-server"} 2.2 eval instant at 50m round(5.2 + 0.0005 * http_requests{group="production",job="api-server"}, 0.1) {group="production", instance="0", job="api-server"} 5.3 {group="production", instance="1", job="api-server"} 5.3 # Round should work correctly with negative numbers and multiple decimal places. eval instant at 50m round(-1 * (5.2 + 0.0005 * http_requests{group="production",job="api-server"}), 0.1) {group="production", instance="0", job="api-server"} -5.2 {group="production", instance="1", job="api-server"} -5.3 # Round should work correctly with big toNearests. eval instant at 50m round(0.025 * http_requests{group="production",job="api-server"}, 5) {group="production", instance="0", job="api-server"} 5 {group="production", instance="1", job="api-server"} 5 eval instant at 50m round(0.045 * http_requests{group="production",job="api-server"}, 5) {group="production", instance="0", job="api-server"} 5 {group="production", instance="1", job="api-server"} 10 eval instant at 50m avg_over_time(http_requests{group="production",job="api-server"}[1h]) {group="production", instance="0", job="api-server"} 50 {group="production", instance="1", job="api-server"} 100 eval instant at 50m count_over_time(http_requests{group="production",job="api-server"}[1h]) {group="production", instance="0", job="api-server"} 11 {group="production", instance="1", job="api-server"} 11 eval instant at 50m max_over_time(http_requests{group="production",job="api-server"}[1h]) {group="production", instance="0", job="api-server"} 100 {group="production", instance="1", job="api-server"} 200 eval instant at 50m min_over_time(http_requests{group="production",job="api-server"}[1h]) {group="production", instance="0", job="api-server"} 0 {group="production", instance="1", job="api-server"} 0 eval instant at 50m sum_over_time(http_requests{group="production",job="api-server"}[1h]) {group="production", instance="0", job="api-server"} 550 {group="production", instance="1", job="api-server"} 1100 eval instant at 50m time() 3000 eval instant at 50m drop_common_labels(http_requests{group="production",job="api-server"}) http_requests{instance="0"} 100 http_requests{instance="1"} 200 eval instant at 50m {__name__=~".+"} http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="canary", instance="1", job="api-server"} 400 http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="production", instance="0", job="api-server"} 100 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="1", job="app-server"} 600 testcounter_reset_end 0 testcounter_reset_middle 50 x{y="testvalue"} 100 label_grouping_test{a="a", b="abb"} 200 label_grouping_test{a="aa", b="bb"} 100 vector_matching_a{l="x"} 10 vector_matching_a{l="y"} 20 vector_matching_b{l="x"} 40 cpu_count{instance="1", type="smp"} 200 cpu_count{instance="0", type="smp"} 100 cpu_count{instance="0", type="numa"} 300 eval instant at 50m {job=~"server", job!~"api"} http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="app-server"} 600 # Test alternative "by"-clause order. eval instant at 50m sum by (group) (http_requests{job="api-server"}) {group="canary"} 700 {group="production"} 300 # Test alternative "by"-clause order with "keep_common". eval instant at 50m sum by (group) keep_common (http_requests{job="api-server"}) {group="canary", job="api-server"} 700 {group="production", job="api-server"} 300 # Test both alternative "by"-clause orders in one expression. # Public health warning: stick to one form within an expression (or even # in an organization), or risk serious user confusion. eval instant at 50m sum(sum by (group) keep_common (http_requests{job="api-server"})) by (job) {job="api-server"} 1000 eval instant at 50m http_requests{group="canary"} and http_requests{instance="0"} http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="canary", instance="0", job="app-server"} 700 eval instant at 50m (http_requests{group="canary"} + 1) and http_requests{instance="0"} {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 eval instant at 50m (http_requests{group="canary"} + 1) and on(instance, job) http_requests{instance="0", group="production"} {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 eval instant at 50m (http_requests{group="canary"} + 1) and on(instance) http_requests{instance="0", group="production"} {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 eval instant at 50m http_requests{group="canary"} or http_requests{group="production"} http_requests{group="canary", instance="0", job="api-server"} 300 http_requests{group="canary", instance="0", job="app-server"} 700 http_requests{group="canary", instance="1", job="api-server"} 400 http_requests{group="canary", instance="1", job="app-server"} 800 http_requests{group="production", instance="0", job="api-server"} 100 http_requests{group="production", instance="0", job="app-server"} 500 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="1", job="app-server"} 600 # On overlap the rhs samples must be dropped. eval instant at 50m (http_requests{group="canary"} + 1) or http_requests{instance="1"} {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 {group="canary", instance="1", job="api-server"} 401 {group="canary", instance="1", job="app-server"} 801 http_requests{group="production", instance="1", job="api-server"} 200 http_requests{group="production", instance="1", job="app-server"} 600 # Matching only on instance excludes everything that has instance=0/1 but includes # entries without the instance label. eval instant at 50m (http_requests{group="canary"} + 1) or on(instance) (http_requests or cpu_count or vector_matching_a) {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 {group="canary", instance="1", job="api-server"} 401 {group="canary", instance="1", job="app-server"} 801 vector_matching_a{l="x"} 10 vector_matching_a{l="y"} 20 eval instant at 50m http_requests{group="canary"} / on(instance,job) http_requests{group="production"} {instance="0", job="api-server"} 3 {instance="0", job="app-server"} 1.4 {instance="1", job="api-server"} 2 {instance="1", job="app-server"} 1.3333333333333333 # Include labels must guarantee uniquely identifiable time series. eval_fail instant at 50m http_requests{group="production"} / on(instance) group_left(group) cpu_count{type="smp"} # Many-to-many matching is not allowed. eval_fail instant at 50m http_requests{group="production"} / on(instance) group_left(job,type) cpu_count # Many-to-one matching must be explicit. eval_fail instant at 50m http_requests{group="production"} / on(instance) cpu_count{type="smp"} eval instant at 50m http_requests{group="production"} / on(instance) group_left(job) cpu_count{type="smp"} {instance="1", job="api-server"} 1 {instance="0", job="app-server"} 5 {instance="1", job="app-server"} 3 {instance="0", job="api-server"} 1 # Ensure sidedness of grouping preserves operand sides. eval instant at 50m cpu_count{type="smp"} / on(instance) group_right(job) http_requests{group="production"} {instance="1", job="app-server"} 0.3333333333333333 {instance="0", job="app-server"} 0.2 {instance="1", job="api-server"} 1 {instance="0", job="api-server"} 1 # Include labels from both sides. eval instant at 50m http_requests{group="production"} / on(instance) group_left(job) cpu_count{type="smp"} {instance="1", job="api-server"} 1 {instance="0", job="app-server"} 5 {instance="1", job="app-server"} 3 {instance="0", job="api-server"} 1 eval instant at 50m http_requests{group="production"} < on(instance,job) http_requests{group="canary"} {instance="1", job="app-server"} 600 {instance="0", job="app-server"} 500 {instance="1", job="api-server"} 200 {instance="0", job="api-server"} 100 eval instant at 50m http_requests{group="production"} > on(instance,job) http_requests{group="canary"} # no output eval instant at 50m http_requests{group="production"} == on(instance,job) http_requests{group="canary"} # no output eval instant at 50m http_requests > on(instance) group_left(group,job) cpu_count{type="smp"} {group="canary", instance="0", job="app-server"} 700 {group="canary", instance="1", job="app-server"} 800 {group="canary", instance="0", job="api-server"} 300 {group="canary", instance="1", job="api-server"} 400 {group="production", instance="0", job="app-server"} 500 {group="production", instance="1", job="app-server"} 600 eval instant at 50m {l="x"} + on(__name__) {l="y"} vector_matching_a 30 eval instant at 50m absent(nonexistent) {} 1 eval instant at 50m absent(nonexistent{job="testjob", instance="testinstance", method=~".x"}) {instance="testinstance", job="testjob"} 1 eval instant at 50m count_scalar(absent(http_requests)) 0 eval instant at 50m count_scalar(absent(sum(http_requests))) 0 eval instant at 50m absent(sum(nonexistent{job="testjob", instance="testinstance"})) {} 1 eval instant at 50m http_requests{group="production",job="api-server"} offset 5m http_requests{group="production", instance="0", job="api-server"} 90 http_requests{group="production", instance="1", job="api-server"} 180 eval instant at 50m rate(http_requests{group="production",job="api-server"}[10m] offset 5m) {group="production", instance="0", job="api-server"} 0.03333333333333333 {group="production", instance="1", job="api-server"} 0.06666666666666667 # Regression test for missing separator byte in labelsToGroupingKey. eval instant at 50m sum(label_grouping_test) by (a, b) {a="a", b="abb"} 200 {a="aa", b="bb"} 100 eval instant at 50m http_requests{group="canary", instance="0", job="api-server"} / 0 {group="canary", instance="0", job="api-server"} +Inf eval instant at 50m -1 * http_requests{group="canary", instance="0", job="api-server"} / 0 {group="canary", instance="0", job="api-server"} -Inf eval instant at 50m 0 * http_requests{group="canary", instance="0", job="api-server"} / 0 {group="canary", instance="0", job="api-server"} NaN eval instant at 50m 0 * http_requests{group="canary", instance="0", job="api-server"} % 0 {group="canary", instance="0", job="api-server"} NaN eval instant at 50m exp(vector_matching_a) {l="x"} 22026.465794806718 {l="y"} 485165195.4097903 eval instant at 50m exp(vector_matching_a - 10) {l="y"} 22026.465794806718 {l="x"} 1 eval instant at 50m exp(vector_matching_a - 20) {l="x"} 4.5399929762484854e-05 {l="y"} 1 eval instant at 50m ln(vector_matching_a) {l="x"} 2.302585092994046 {l="y"} 2.995732273553991 eval instant at 50m ln(vector_matching_a - 10) {l="y"} 2.302585092994046 {l="x"} -Inf eval instant at 50m ln(vector_matching_a - 20) {l="y"} -Inf {l="x"} NaN eval instant at 50m exp(ln(vector_matching_a)) {l="y"} 20 {l="x"} 10 eval instant at 50m sqrt(vector_matching_a) {l="x"} 3.1622776601683795 {l="y"} 4.47213595499958 eval instant at 50m log2(vector_matching_a) {l="x"} 3.3219280948873626 {l="y"} 4.321928094887363 eval instant at 50m log2(vector_matching_a - 10) {l="y"} 3.3219280948873626 {l="x"} -Inf eval instant at 50m log2(vector_matching_a - 20) {l="x"} NaN {l="y"} -Inf eval instant at 50m log10(vector_matching_a) {l="x"} 1 {l="y"} 1.301029995663981 eval instant at 50m log10(vector_matching_a - 10) {l="y"} 1 {l="x"} -Inf eval instant at 50m log10(vector_matching_a - 20) {l="x"} NaN {l="y"} -Inf eval instant at 50m stddev(http_requests) {} 229.12878474779 eval instant at 50m stddev by (instance)(http_requests) {instance="0"} 223.60679774998 {instance="1"} 223.60679774998 eval instant at 50m stdvar(http_requests) {} 52500 eval instant at 50m stdvar by (instance)(http_requests) {instance="0"} 50000 {instance="1"} 50000 # Matrix tests. clear load 1h testmetric{testlabel="1"} 1 1 testmetric{testlabel="2"} _ 2 eval instant at 0h drop_common_labels(testmetric) testmetric 1 eval instant at 1h drop_common_labels(testmetric) testmetric{testlabel="1"} 1 testmetric{testlabel="2"} 2 clear load 1h testmetric{testlabel="1"} 1 1 testmetric{testlabel="2"} 2 _ eval instant at 0h sum(testmetric) keep_common {} 3 eval instant at 1h sum(testmetric) keep_common {testlabel="1"} 1 clear load 1h testmetric{aa="bb"} 1 testmetric{a="abb"} 2 eval instant at 0h testmetric testmetric{aa="bb"} 1 testmetric{a="abb"} 2