diff --git a/docs/sources/logql/_index.md b/docs/sources/logql/_index.md index 8e265a8fe0..e151851474 100644 --- a/docs/sources/logql/_index.md +++ b/docs/sources/logql/_index.md @@ -534,6 +534,8 @@ Supported function for operating over unwrapped ranges are: - `avg_over_time(unwrapped-range)`: the average value of all points in the specified interval. - `max_over_time(unwrapped-range)`: the maximum value of all points in the specified interval. - `min_over_time(unwrapped-range)`: the minimum value of all points in the specified interval +- `first_over_time(unwrapped-range)`: the first value of all points in the specified interval +- `last_over_time(unwrapped-range)`: the last value of all points in the specified interval - `stdvar_over_time(unwrapped-range)`: the population standard variance of the values in the specified interval. - `stddev_over_time(unwrapped-range)`: the population standard deviation of the values in the specified interval. - `quantile_over_time(scalar,unwrapped-range)`: the φ-quantile (0 ≤ φ ≤ 1) of the values in the specified interval. diff --git a/pkg/logql/ast.go b/pkg/logql/ast.go index 4e258ef087..1e8b15093c 100644 --- a/pkg/logql/ast.go +++ b/pkg/logql/ast.go @@ -574,6 +574,8 @@ const ( OpRangeTypeStdvar = "stdvar_over_time" OpRangeTypeStddev = "stddev_over_time" OpRangeTypeQuantile = "quantile_over_time" + OpRangeTypeFirst = "first_over_time" + OpRangeTypeLast = "last_over_time" OpRangeTypeAbsent = "absent_over_time" // binops - logical/set @@ -691,14 +693,14 @@ func (e *rangeAggregationExpr) Selector() LogSelectorExpr { func (e rangeAggregationExpr) validate() error { if e.grouping != nil { switch e.operation { - case OpRangeTypeAvg, OpRangeTypeStddev, OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeMax, OpRangeTypeMin: + case OpRangeTypeAvg, OpRangeTypeStddev, OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeMax, OpRangeTypeMin, OpRangeTypeFirst, OpRangeTypeLast: default: return fmt.Errorf("grouping not allowed for %s aggregation", e.operation) } } if e.left.unwrap != nil { switch e.operation { - case OpRangeTypeRate, OpRangeTypeAvg, OpRangeTypeSum, OpRangeTypeMax, OpRangeTypeMin, OpRangeTypeStddev, OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeAbsent: + case OpRangeTypeAvg, OpRangeTypeSum, OpRangeTypeMax, OpRangeTypeMin, OpRangeTypeStddev, OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeRate, OpRangeTypeAbsent, OpRangeTypeFirst, OpRangeTypeLast: return nil default: return fmt.Errorf("invalid aggregation %s with unwrap", e.operation) diff --git a/pkg/logql/ast_test.go b/pkg/logql/ast_test.go index 2123a31d74..f896f8642d 100644 --- a/pkg/logql/ast_test.go +++ b/pkg/logql/ast_test.go @@ -115,6 +115,8 @@ func Test_SampleExpr_String(t *testing.T) { count_over_time({namespace="tns"} | logfmt | label_format foo=bar[5m]) )`, `sum_over_time({namespace="tns"} |= "level=error" | json |foo>=5,bar<25ms | unwrap latency | __error__!~".*" | foo >5[5m])`, + `last_over_time({namespace="tns"} |= "level=error" | json |foo>=5,bar<25ms | unwrap latency | __error__!~".*" | foo >5[5m])`, + `first_over_time({namespace="tns"} |= "level=error" | json |foo>=5,bar<25ms | unwrap latency | __error__!~".*" | foo >5[5m])`, `absent_over_time({namespace="tns"} |= "level=error" | json |foo>=5,bar<25ms | unwrap latency | __error__!~".*" | foo >5[5m])`, `sum by (job) ( sum_over_time( diff --git a/pkg/logql/engine_test.go b/pkg/logql/engine_test.go index c5df9ae1a6..bca17b3a43 100644 --- a/pkg/logql/engine_test.go +++ b/pkg/logql/engine_test.go @@ -106,6 +106,16 @@ func TestEngine_LogsInstantQuery(t *testing.T) { }, promql.Vector{promql.Sample{Point: promql.Point{T: 60 * 1000, V: 6}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}}}, }, + { + `first_over_time({app="foo"} |~".+bar" | unwrap foo [1m])`, time.Unix(60, 0), logproto.BACKWARD, 10, + [][]logproto.Series{ + {newSeries(testSize, factor(10, identity), `{app="foo"}`)}, // 10 , 20 , 30 .. 60 = 6 total + }, + []SelectSampleParams{ + {&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `first_over_time({app="foo"}|~".+bar"| unwrap foo [1m])`}}, + }, + promql.Vector{promql.Sample{Point: promql.Point{T: 60 * 1000, V: 1}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}}}, + }, { `count_over_time({app="foo"} |~".+bar" [1m] offset 30s)`, time.Unix(90, 0), logproto.BACKWARD, 10, [][]logproto.Series{ @@ -754,6 +764,33 @@ func TestEngine_RangeQuery(t *testing.T) { }, }, }, + { + `last_over_time(({app="foo"} |~".+bar" | unwrap foo)[5m])`, time.Unix(5*60, 0), time.Unix(5*120, 0), 30 * time.Second, 0, logproto.BACKWARD, 10, + [][]logproto.Series{ + {newSeries(testSize, factor(10, identity), `{app="foo"}`)}, // 10 , 20 , 30 .. 300 = 30 total + }, + []SelectSampleParams{ + {&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(5*120, 0), Selector: `last_over_time({app="foo"}|~".+bar"| unwrap foo[5m])`}}, + }, + promql.Matrix{ + promql.Series{ + Metric: labels.Labels{{Name: "app", Value: "foo"}}, + Points: []promql.Point{ + {T: 300 * 1000, V: 1}, + {T: 330 * 1000, V: 1}, + {T: 360 * 1000, V: 1}, + {T: 390 * 1000, V: 1}, + {T: 420 * 1000, V: 1}, + {T: 450 * 1000, V: 1}, + {T: 480 * 1000, V: 1}, + {T: 510 * 1000, V: 1}, + {T: 540 * 1000, V: 1}, + {T: 570 * 1000, V: 1}, + {T: 600 * 1000, V: 1}, + }, + }, + }, + }, { `avg(count_over_time({app=~"foo|bar"} |~".+bar" [1m]))`, time.Unix(60, 0), time.Unix(180, 0), 30 * time.Second, 0, logproto.FORWARD, 100, [][]logproto.Series{ diff --git a/pkg/logql/expr.y b/pkg/logql/expr.y index 164ad3ba6d..c12d67d22f 100644 --- a/pkg/logql/expr.y +++ b/pkg/logql/expr.y @@ -100,7 +100,7 @@ import ( OPEN_PARENTHESIS CLOSE_PARENTHESIS BY WITHOUT COUNT_OVER_TIME RATE SUM AVG MAX MIN COUNT STDDEV STDVAR BOTTOMK TOPK BYTES_OVER_TIME BYTES_RATE BOOL JSON REGEXP LOGFMT PIPE LINE_FMT LABEL_FMT UNWRAP AVG_OVER_TIME SUM_OVER_TIME MIN_OVER_TIME MAX_OVER_TIME STDVAR_OVER_TIME STDDEV_OVER_TIME QUANTILE_OVER_TIME BYTES_CONV DURATION_CONV DURATION_SECONDS_CONV - ABSENT_OVER_TIME LABEL_REPLACE UNPACK OFFSET + FIRST_OVER_TIME LAST_OVER_TIME ABSENT_OVER_TIME LABEL_REPLACE UNPACK OFFSET // Operators are listed with increasing precedence. %left OR @@ -374,6 +374,8 @@ rangeOp: | STDVAR_OVER_TIME { $$ = OpRangeTypeStdvar } | STDDEV_OVER_TIME { $$ = OpRangeTypeStddev } | QUANTILE_OVER_TIME { $$ = OpRangeTypeQuantile } + | FIRST_OVER_TIME { $$ = OpRangeTypeFirst } + | LAST_OVER_TIME { $$ = OpRangeTypeLast } | ABSENT_OVER_TIME { $$ = OpRangeTypeAbsent } ; diff --git a/pkg/logql/expr.y.go b/pkg/logql/expr.y.go index 6014a7230e..fe657cbb93 100644 --- a/pkg/logql/expr.y.go +++ b/pkg/logql/expr.y.go @@ -6,7 +6,6 @@ package logql import __yyfmt__ "fmt" //line pkg/logql/expr.y:2 - import ( "github.com/grafana/loki/pkg/logql/log" "github.com/prometheus/prometheus/pkg/labels" @@ -113,25 +112,27 @@ const QUANTILE_OVER_TIME = 57396 const BYTES_CONV = 57397 const DURATION_CONV = 57398 const DURATION_SECONDS_CONV = 57399 -const ABSENT_OVER_TIME = 57400 -const LABEL_REPLACE = 57401 -const UNPACK = 57402 -const OFFSET = 57403 -const OR = 57404 -const AND = 57405 -const UNLESS = 57406 -const CMP_EQ = 57407 -const NEQ = 57408 -const LT = 57409 -const LTE = 57410 -const GT = 57411 -const GTE = 57412 -const ADD = 57413 -const SUB = 57414 -const MUL = 57415 -const DIV = 57416 -const MOD = 57417 -const POW = 57418 +const FIRST_OVER_TIME = 57400 +const LAST_OVER_TIME = 57401 +const ABSENT_OVER_TIME = 57402 +const LABEL_REPLACE = 57403 +const UNPACK = 57404 +const OFFSET = 57405 +const OR = 57406 +const AND = 57407 +const UNLESS = 57408 +const CMP_EQ = 57409 +const NEQ = 57410 +const LT = 57411 +const LTE = 57412 +const GT = 57413 +const GTE = 57414 +const ADD = 57415 +const SUB = 57416 +const MUL = 57417 +const DIV = 57418 +const MOD = 57419 +const POW = 57420 var exprToknames = [...]string{ "$end", @@ -191,6 +192,8 @@ var exprToknames = [...]string{ "BYTES_CONV", "DURATION_CONV", "DURATION_SECONDS_CONV", + "FIRST_OVER_TIME", + "LAST_OVER_TIME", "ABSENT_OVER_TIME", "LABEL_REPLACE", "UNPACK", @@ -211,14 +214,13 @@ var exprToknames = [...]string{ "MOD", "POW", } - var exprStatenames = [...]string{} const exprEofCode = 1 const exprErrCode = 2 const exprInitialStackSize = 16 -//line pkg/logql/expr.y:394 +//line pkg/logql/expr.y:396 //line yacctab:1 var exprExca = [...]int{ @@ -229,101 +231,107 @@ var exprExca = [...]int{ const exprPrivate = 57344 -const exprLast = 479 +const exprLast = 530 var exprAct = [...]int{ - 227, 181, 73, 4, 163, 56, 152, 5, 157, 190, - 64, 106, 48, 55, 230, 126, 66, 2, 43, 44, - 45, 46, 47, 48, 69, 59, 15, 45, 46, 47, - 48, 233, 62, 235, 12, 232, 62, 282, 80, 60, - 61, 300, 6, 60, 61, 262, 19, 20, 31, 32, - 34, 35, 33, 36, 37, 38, 39, 21, 22, 231, - 285, 95, 183, 263, 282, 99, 183, 23, 24, 25, - 26, 27, 28, 29, 269, 295, 130, 30, 18, 128, - 232, 230, 135, 96, 63, 122, 124, 125, 63, 287, - 16, 17, 74, 75, 232, 272, 136, 279, 137, 138, + + 229, 183, 75, 4, 165, 58, 154, 5, 159, 192, + 66, 108, 50, 57, 232, 128, 68, 2, 45, 46, + 47, 48, 49, 50, 71, 42, 43, 44, 51, 52, + 55, 56, 53, 54, 45, 46, 47, 48, 49, 50, + 43, 44, 51, 52, 55, 56, 53, 54, 45, 46, + 47, 48, 49, 50, 47, 48, 49, 50, 124, 126, + 127, 64, 237, 97, 167, 126, 127, 101, 62, 63, + 61, 234, 284, 82, 74, 265, 76, 77, 132, 302, + 284, 130, 264, 297, 137, 51, 52, 55, 56, 53, + 54, 45, 46, 47, 48, 49, 50, 287, 138, 232, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 177, 265, 266, 267, 160, 40, 41, 42, - 49, 50, 53, 54, 51, 52, 43, 44, 45, 46, - 47, 48, 172, 62, 254, 242, 188, 184, 186, 123, - 60, 61, 182, 262, 193, 185, 41, 42, 49, 50, - 53, 54, 51, 52, 43, 44, 45, 46, 47, 48, - 196, 197, 198, 49, 50, 53, 54, 51, 52, 43, - 44, 45, 46, 47, 48, 244, 231, 117, 232, 112, - 246, 225, 228, 177, 234, 63, 237, 128, 95, 240, - 99, 241, 116, 154, 229, 226, 62, 109, 238, 72, - 112, 74, 75, 60, 61, 239, 134, 250, 248, 192, - 233, 232, 62, 133, 154, 62, 244, 132, 109, 60, - 61, 245, 60, 61, 298, 270, 183, 192, 194, 255, - 177, 257, 259, 78, 261, 95, 112, 153, 112, 260, - 271, 256, 58, 230, 95, 183, 191, 273, 63, 71, - 203, 119, 178, 294, 109, 275, 109, 276, 277, 165, - 124, 125, 95, 278, 63, 118, 121, 63, 120, 280, - 281, 243, 102, 104, 103, 286, 110, 111, 235, 189, - 127, 12, 290, 202, 291, 292, 199, 12, 12, 129, - 195, 105, 200, 187, 296, 6, 129, 179, 293, 19, - 20, 31, 32, 34, 35, 33, 36, 37, 38, 39, - 21, 22, 171, 166, 169, 170, 167, 168, 284, 283, - 23, 24, 25, 26, 27, 28, 29, 180, 268, 131, - 30, 18, 62, 258, 252, 253, 299, 12, 77, 60, - 61, 76, 236, 16, 17, 6, 297, 288, 249, 19, - 20, 31, 32, 34, 35, 33, 36, 37, 38, 39, - 21, 22, 183, 251, 247, 176, 164, 112, 289, 112, - 23, 24, 25, 26, 27, 28, 29, 180, 112, 3, - 30, 18, 62, 154, 63, 109, 65, 109, 201, 60, - 61, 175, 154, 16, 17, 79, 109, 208, 174, 174, - 209, 207, 173, 102, 104, 103, 223, 110, 111, 224, - 222, 205, 183, 173, 206, 204, 220, 161, 274, 221, - 219, 217, 105, 158, 218, 216, 155, 153, 214, 159, - 70, 215, 213, 151, 63, 155, 153, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 211, 115, 68, 212, 210, 70, 164, 107, 156, - 98, 162, 101, 100, 57, 113, 108, 114, 97, 11, - 10, 9, 14, 8, 264, 13, 7, 67, 1, + 149, 150, 151, 152, 125, 65, 289, 234, 162, 173, + 168, 171, 172, 169, 170, 267, 268, 269, 76, 77, + 98, 264, 179, 233, 174, 233, 235, 274, 190, 186, + 182, 64, 114, 179, 184, 64, 195, 187, 62, 63, + 271, 272, 62, 63, 256, 238, 156, 194, 244, 114, + 111, 281, 198, 199, 200, 241, 234, 235, 234, 114, + 234, 185, 64, 156, 64, 185, 196, 111, 203, 62, + 63, 62, 63, 227, 230, 188, 236, 111, 239, 130, + 97, 242, 101, 243, 194, 65, 231, 228, 119, 65, + 240, 118, 185, 182, 185, 179, 114, 246, 64, 252, + 250, 300, 248, 193, 64, 62, 63, 296, 157, 155, + 156, 62, 63, 232, 111, 246, 65, 180, 65, 277, + 247, 257, 136, 259, 261, 135, 263, 97, 185, 114, + 64, 262, 273, 258, 185, 134, 97, 62, 63, 275, + 12, 80, 73, 156, 123, 245, 204, 111, 131, 278, + 279, 201, 65, 197, 97, 280, 155, 129, 65, 189, + 60, 282, 283, 181, 121, 12, 205, 288, 202, 295, + 286, 15, 285, 131, 292, 270, 293, 294, 120, 12, + 260, 122, 254, 255, 65, 79, 298, 6, 157, 155, + 78, 19, 20, 33, 34, 36, 37, 35, 38, 39, + 40, 41, 21, 22, 210, 301, 176, 211, 209, 299, + 290, 251, 23, 24, 25, 26, 27, 28, 29, 191, + 249, 178, 30, 31, 32, 18, 207, 12, 175, 208, + 206, 253, 177, 176, 166, 6, 175, 16, 17, 19, + 20, 33, 34, 36, 37, 35, 38, 39, 40, 41, + 21, 22, 225, 163, 222, 226, 224, 223, 221, 161, + 23, 24, 25, 26, 27, 28, 29, 133, 153, 117, + 30, 31, 32, 18, 219, 12, 216, 220, 218, 217, + 215, 70, 291, 6, 72, 16, 17, 19, 20, 33, + 34, 36, 37, 35, 38, 39, 40, 41, 21, 22, + 3, 276, 213, 81, 114, 214, 212, 67, 23, 24, + 25, 26, 27, 28, 29, 160, 72, 166, 30, 31, + 32, 18, 111, 109, 158, 100, 164, 103, 102, 59, + 115, 110, 116, 16, 17, 99, 11, 10, 9, 14, + 104, 106, 105, 8, 112, 113, 237, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 107, 114, 266, 13, 7, 69, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 104, 106, + 105, 0, 112, 113, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, } - var exprPact = [...]int{ - 19, -1000, 55, -1000, -1000, 198, 19, -1000, -1000, -1000, - -1000, -1000, 451, 226, 176, -1000, 334, 331, 210, -1000, + + 274, -1000, -39, -1000, -1000, 226, 274, -1000, -1000, -1000, + -1000, -1000, 389, 229, 51, -1000, 293, 288, 228, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, 198, -1000, 119, 362, 446, - -1000, -1000, -1000, -1000, 168, 153, 55, 249, 250, -1000, - 73, 273, 322, 194, 190, 183, -1000, -1000, 19, 19, - -1000, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, -1000, 427, -1000, -1000, 373, - -1000, -1000, 418, -1000, 423, -1000, -1000, -1000, -1000, 233, - 411, 452, 247, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 425, -1000, 396, 392, 385, 359, 228, 278, 368, 266, - 114, 274, 272, 222, 204, 271, 83, 98, 98, -46, - -46, -64, -64, -64, -64, -53, -53, -53, -53, -53, - -53, -1000, 373, 233, 233, 233, 267, -1000, 280, -1000, - 364, -1000, 264, -1000, 238, 407, 393, 447, 424, 417, - 412, 402, -1000, -1000, -1000, -1000, -1000, -1000, 67, 266, - 182, 167, 22, 231, 318, 181, 67, 19, 111, 252, - 197, -1000, -1000, 156, -1000, 358, 195, 373, 174, 418, - 342, -1000, 361, 329, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 226, -1000, 47, + 467, 373, -1000, -1000, -1000, -1000, 177, 174, -39, 272, + 238, -1000, 46, 260, 370, 222, 212, 209, -1000, -1000, + 274, 274, -1000, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, -1000, 372, -1000, + -1000, 234, -1000, -1000, 420, -1000, 363, -1000, -1000, -1000, + -1000, 164, 357, 422, 52, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 421, -1000, 340, 337, 336, 325, 203, 254, + 194, 235, 161, 250, 322, 189, 152, 244, -25, 18, + 18, -21, -21, -66, -66, -66, -66, -55, -55, -55, + -55, -55, -55, -1000, 234, 164, 164, 164, 242, -1000, + 266, -1000, 154, -1000, 237, -1000, 264, 332, 310, 408, + 382, 380, 360, 358, -1000, -1000, -1000, -1000, -1000, -1000, + 103, 235, 160, 124, 158, 409, 131, 141, 103, 274, + 134, 236, 206, -1000, -1000, 188, -1000, 324, 137, 234, + 201, 420, 315, -1000, 339, 287, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 110, 18, -9, 18, - 325, -47, 233, -47, 134, 58, 319, 50, 201, -1000, - -1000, 71, -1000, 19, 413, -1000, -1000, 236, -1000, -1000, - -1000, -1000, -1000, -1000, 67, -9, 18, -9, -1000, -1000, - 373, -1000, -47, -1000, 74, -1000, -1000, -1000, 20, 310, - 309, 36, 67, 65, -1000, 341, -1000, -9, -1000, 363, - -7, -9, -14, -47, -47, 289, -1000, -1000, 234, 51, - -9, -1000, -1000, -47, 340, -1000, -1000, 205, 330, 17, - -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 130, 200, + 27, 200, 282, -49, 164, -49, 122, 70, 276, 126, + 127, -1000, -1000, 113, -1000, 274, 406, -1000, -1000, 210, + -1000, -1000, -1000, -1000, -1000, -1000, 103, 27, 200, 27, + -1000, -1000, 234, -1000, -49, -1000, 138, -1000, -1000, -1000, + 36, 273, 271, 73, 103, 92, -1000, 314, -1000, 27, + -1000, 387, 28, 27, 15, -49, -49, 270, -1000, -1000, + 198, 59, 27, -1000, -1000, -49, 313, -1000, -1000, 192, + 309, 55, -1000, } - var exprPgo = [...]int{ - 0, 478, 16, 25, 2, 9, 379, 3, 15, 11, - 477, 476, 475, 474, 7, 473, 472, 471, 470, 469, - 395, 468, 13, 5, 467, 466, 465, 6, 464, 463, - 462, 4, 461, 460, 8, 459, 1, 458, 0, -} + 0, 477, 16, 70, 2, 9, 410, 3, 15, 11, + 476, 475, 474, 473, 7, 453, 449, 448, 447, 446, + 413, 445, 13, 5, 442, 441, 440, 6, 439, 438, + 437, 4, 436, 435, 8, 434, 1, 433, 0, +} var exprR1 = [...]int{ + 0, 1, 2, 2, 7, 7, 7, 7, 7, 7, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -340,11 +348,11 @@ var exprR1 = [...]int{ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 20, 20, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 38, 5, 5, 4, - 4, 4, 4, + 12, 12, 12, 12, 12, 12, 12, 12, 38, 5, + 5, 4, 4, 4, 4, } - var exprR2 = [...]int{ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 3, 2, 3, 4, 5, 3, 4, 5, 6, 3, 4, 5, 6, 3, 4, 5, 6, 4, @@ -361,83 +369,83 @@ var exprR2 = [...]int{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 1, 3, 4, - 4, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 3, 4, 4, 3, 3, } - var exprChk = [...]int{ + -1000, -1, -2, -6, -7, -14, 23, -11, -15, -17, - -18, -19, 15, -12, -16, 7, 71, 72, 59, 27, + -18, -19, 15, -12, -16, 7, 73, 74, 61, 27, 28, 38, 39, 48, 49, 50, 51, 52, 53, 54, - 58, 29, 30, 33, 31, 32, 34, 35, 36, 37, - 62, 63, 64, 71, 72, 73, 74, 75, 76, 65, - 66, 69, 70, 67, 68, -22, -23, -28, 44, -3, - 21, 22, 14, 66, -7, -6, -2, -10, 2, -9, - 5, 23, 23, -4, 25, 26, 7, 7, 23, -20, - 40, -20, -20, -20, -20, -20, -20, -20, -20, -20, - -20, -20, -20, -20, -20, -23, -3, -21, -33, -27, - -29, -30, 41, 43, 42, 60, -9, -37, -25, 23, - 45, 46, 5, -26, -24, 6, 24, 24, 16, 2, - 19, 16, 12, 66, 13, 14, -8, 7, -14, 23, - -7, 7, 23, 23, 23, -7, -2, -2, -2, -2, + 58, 59, 60, 29, 30, 33, 31, 32, 34, 35, + 36, 37, 64, 65, 66, 73, 74, 75, 76, 77, + 78, 67, 68, 71, 72, 69, 70, -22, -23, -28, + 44, -3, 21, 22, 14, 68, -7, -6, -2, -10, + 2, -9, 5, 23, 23, -4, 25, 26, 7, 7, + 23, -20, 40, -20, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20, -23, -3, -21, + -33, -27, -29, -30, 41, 43, 42, 62, -9, -37, + -25, 23, 45, 46, 5, -26, -24, 6, 24, 24, + 16, 2, 19, 16, 12, 68, 13, 14, -8, 7, + -14, 23, -7, 7, 23, 23, 23, -7, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, 6, -27, 63, 19, 62, -35, -34, 5, 6, - -27, 6, -32, -31, 5, 12, 66, 69, 70, 67, - 68, 65, -9, 6, 6, 6, 6, 2, 24, 19, - 9, -36, -22, 44, -14, -8, 24, 19, -7, 7, - -5, 24, 5, -5, 24, 19, -27, -27, -27, 19, - 12, 24, 19, 12, 8, 4, 7, 8, 4, 7, - 8, 4, 7, 8, 4, 7, 8, 4, 7, 8, - 4, 7, 8, 4, 7, -4, -8, -38, -36, -22, - 61, 9, 44, 9, -36, 47, 24, -36, -22, 24, - -4, -7, 24, 19, 19, 24, 24, 6, -34, 6, - -31, 2, 5, 6, 24, -36, -22, -36, 8, -38, - -27, -38, 9, 5, -13, 55, 56, 57, 9, 24, - 24, -36, 24, -7, 5, 19, -4, -36, -38, 23, - -38, -36, 44, 9, 9, 24, -4, 24, 6, 5, - -36, -38, -38, 9, 19, 24, -38, 6, 19, 6, - 24, + -2, -2, -2, 6, -27, 65, 19, 64, -35, -34, + 5, 6, -27, 6, -32, -31, 5, 12, 68, 71, + 72, 69, 70, 67, -9, 6, 6, 6, 6, 2, + 24, 19, 9, -36, -22, 44, -14, -8, 24, 19, + -7, 7, -5, 24, 5, -5, 24, 19, -27, -27, + -27, 19, 12, 24, 19, 12, 8, 4, 7, 8, + 4, 7, 8, 4, 7, 8, 4, 7, 8, 4, + 7, 8, 4, 7, 8, 4, 7, -4, -8, -38, + -36, -22, 63, 9, 44, 9, -36, 47, 24, -36, + -22, 24, -4, -7, 24, 19, 19, 24, 24, 6, + -34, 6, -31, 2, 5, 6, 24, -36, -22, -36, + 8, -38, -27, -38, 9, 5, -13, 55, 56, 57, + 9, 24, 24, -36, 24, -7, 5, 19, -4, -36, + -38, 23, -38, -36, 44, 9, 9, 24, -4, 24, + 6, 5, -36, -38, -38, 9, 19, 24, -38, 6, + 19, 6, 24, } - var exprDef = [...]int{ + 0, -2, 1, 2, 3, 10, 0, 4, 5, 6, 7, 8, 0, 0, 0, 142, 0, 0, 0, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 11, 69, 71, 0, 0, - 56, 57, 58, 59, 3, 2, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 143, 144, 0, 0, - 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 70, 0, 72, 73, 74, - 75, 76, 79, 80, 0, 82, 91, 92, 93, 0, - 0, 0, 0, 102, 103, 77, 9, 12, 60, 61, - 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 142, 0, 0, 0, 3, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 78, 95, 0, 0, 0, 83, 100, 0, 81, - 0, 84, 90, 87, 0, 0, 0, 0, 0, 0, - 0, 0, 64, 65, 66, 67, 68, 38, 45, 0, - 13, 0, 0, 0, 0, 0, 49, 0, 3, 142, - 0, 171, 167, 0, 172, 0, 96, 97, 98, 0, - 0, 94, 0, 0, 109, 116, 123, 108, 115, 122, - 104, 111, 118, 105, 112, 119, 106, 113, 120, 107, - 114, 121, 110, 117, 124, 47, 0, 14, 17, 33, - 0, 21, 0, 25, 0, 0, 0, 0, 0, 37, - 51, 3, 50, 0, 0, 169, 170, 0, 101, 99, - 88, 89, 85, 86, 46, 18, 34, 35, 166, 22, - 41, 26, 29, 39, 0, 42, 43, 44, 15, 0, - 0, 0, 52, 3, 168, 0, 48, 36, 30, 0, - 16, 19, 0, 23, 27, 0, 53, 54, 0, 0, - 20, 24, 28, 31, 0, 40, 32, 0, 0, 0, - 55, + 165, 166, 167, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 11, 69, 71, + 0, 0, 56, 57, 58, 59, 3, 2, 0, 0, + 0, 63, 0, 0, 0, 0, 0, 0, 143, 144, + 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 70, 0, 72, + 73, 74, 75, 76, 79, 80, 0, 82, 91, 92, + 93, 0, 0, 0, 0, 102, 103, 77, 9, 12, + 60, 61, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 142, 0, 0, 0, 3, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 78, 95, 0, 0, 0, 83, 100, + 0, 81, 0, 84, 90, 87, 0, 0, 0, 0, + 0, 0, 0, 0, 64, 65, 66, 67, 68, 38, + 45, 0, 13, 0, 0, 0, 0, 0, 49, 0, + 3, 142, 0, 173, 169, 0, 174, 0, 96, 97, + 98, 0, 0, 94, 0, 0, 109, 116, 123, 108, + 115, 122, 104, 111, 118, 105, 112, 119, 106, 113, + 120, 107, 114, 121, 110, 117, 124, 47, 0, 14, + 17, 33, 0, 21, 0, 25, 0, 0, 0, 0, + 0, 37, 51, 3, 50, 0, 0, 171, 172, 0, + 101, 99, 88, 89, 85, 86, 46, 18, 34, 35, + 168, 22, 41, 26, 29, 39, 0, 42, 43, 44, + 15, 0, 0, 0, 52, 3, 170, 0, 48, 36, + 30, 0, 16, 19, 0, 23, 27, 0, 53, 54, + 0, 0, 20, 24, 28, 31, 0, 40, 32, 0, + 0, 0, 55, } - var exprTok1 = [...]int{ + 1, } - var exprTok2 = [...]int{ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -445,9 +453,8 @@ var exprTok2 = [...]int{ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, + 72, 73, 74, 75, 76, 77, 78, } - var exprTok3 = [...]int{ 0, } @@ -1764,47 +1771,59 @@ exprdefault: exprDollar = exprS[exprpt-1 : exprpt+1] //line pkg/logql/expr.y:377 { - exprVAL.RangeOp = OpRangeTypeAbsent + exprVAL.RangeOp = OpRangeTypeFirst } case 166: + exprDollar = exprS[exprpt-1 : exprpt+1] +//line pkg/logql/expr.y:378 + { + exprVAL.RangeOp = OpRangeTypeLast + } + case 167: + exprDollar = exprS[exprpt-1 : exprpt+1] +//line pkg/logql/expr.y:379 + { + exprVAL.RangeOp = OpRangeTypeAbsent + } + case 168: exprDollar = exprS[exprpt-2 : exprpt+1] -//line pkg/logql/expr.y:381 +//line pkg/logql/expr.y:383 { exprVAL.OffsetExpr = newOffsetExpr(exprDollar[2].duration) } - case 167: + case 169: exprDollar = exprS[exprpt-1 : exprpt+1] -//line pkg/logql/expr.y:384 +//line pkg/logql/expr.y:386 { exprVAL.Labels = []string{exprDollar[1].str} } - case 168: + case 170: exprDollar = exprS[exprpt-3 : exprpt+1] -//line pkg/logql/expr.y:385 +//line pkg/logql/expr.y:387 { exprVAL.Labels = append(exprDollar[1].Labels, exprDollar[3].str) } - case 169: + case 171: exprDollar = exprS[exprpt-4 : exprpt+1] -//line pkg/logql/expr.y:389 +//line pkg/logql/expr.y:391 { exprVAL.Grouping = &grouping{without: false, groups: exprDollar[3].Labels} } - case 170: + case 172: exprDollar = exprS[exprpt-4 : exprpt+1] -//line pkg/logql/expr.y:390 +//line pkg/logql/expr.y:392 { exprVAL.Grouping = &grouping{without: true, groups: exprDollar[3].Labels} } - case 171: + case 173: exprDollar = exprS[exprpt-3 : exprpt+1] -//line pkg/logql/expr.y:391 +//line pkg/logql/expr.y:393 { exprVAL.Grouping = &grouping{without: false, groups: nil} } - case 172: + case 174: exprDollar = exprS[exprpt-3 : exprpt+1] -//line pkg/logql/expr.y:392 +//line pkg/logql/expr.y:394 { exprVAL.Grouping = &grouping{without: true, groups: nil} } diff --git a/pkg/logql/functions.go b/pkg/logql/functions.go index dfffd8d0ca..dbd87782af 100644 --- a/pkg/logql/functions.go +++ b/pkg/logql/functions.go @@ -111,6 +111,10 @@ func (r rangeAggregationExpr) aggregator() (RangeVectorAggregator, error) { return stdvarOverTime, nil case OpRangeTypeQuantile: return quantileOverTime(*r.params), nil + case OpRangeTypeFirst: + return first, nil + case OpRangeTypeLast: + return last, nil case OpRangeTypeAbsent: return one, nil default: @@ -260,6 +264,20 @@ func quantile(q float64, values vectorByValueHeap) float64 { return values[int(lowerIndex)].V*(1-weight) + values[int(upperIndex)].V*weight } +func first(samples []promql.Point) float64 { + if len(samples) == 0 { + return math.NaN() + } + return samples[0].V +} + +func last(samples []promql.Point) float64 { + if len(samples) == 0 { + return math.NaN() + } + return samples[len(samples)-1].V +} + func one(samples []promql.Point) float64 { return 1.0 } diff --git a/pkg/logql/lex.go b/pkg/logql/lex.go index 067a41d26e..8869dc6a7a 100644 --- a/pkg/logql/lex.go +++ b/pkg/logql/lex.go @@ -77,18 +77,21 @@ var functionTokens = map[string]int{ OpRangeTypeStdvar: STDVAR_OVER_TIME, OpRangeTypeStddev: STDDEV_OVER_TIME, OpRangeTypeQuantile: QUANTILE_OVER_TIME, + OpRangeTypeFirst: FIRST_OVER_TIME, + OpRangeTypeLast: LAST_OVER_TIME, OpRangeTypeAbsent: ABSENT_OVER_TIME, // vec ops - OpTypeSum: SUM, - OpTypeAvg: AVG, - OpTypeMax: MAX, - OpTypeMin: MIN, - OpTypeCount: COUNT, - OpTypeStddev: STDDEV, - OpTypeStdvar: STDVAR, - OpTypeBottomK: BOTTOMK, - OpTypeTopK: TOPK, + OpTypeSum: SUM, + OpTypeAvg: AVG, + OpTypeMax: MAX, + OpTypeMin: MIN, + OpTypeCount: COUNT, + OpTypeStddev: STDDEV, + OpTypeStdvar: STDVAR, + OpTypeBottomK: BOTTOMK, + OpTypeTopK: TOPK, + OpLabelReplace: LABEL_REPLACE, // conversion Op OpConvBytes: BYTES_CONV,