add group_{left,right} to LogQL (#4510)

* Add group_left/group_right support

* Update docs/sources/logql/_index.md

* Minor change for a test case

* removes CardManyToMany

* removes now-unused IsSetOperator helper

Co-authored-by: Owen Diehl <ow.diehl@gmail.com>
pull/4588/head
lingpeng0314 4 years ago committed by GitHub
parent 3c16658ee0
commit 76e2a14029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      clients/pkg/promtail/server/ui/assets_vfsdata.go
  2. 17
      docs/sources/logql/_index.md
  3. 58
      pkg/logql/ast.go
  4. 1
      pkg/logql/ast_test.go
  5. 103
      pkg/logql/engine_test.go
  6. 299
      pkg/logql/evaluator.go
  7. 10
      pkg/logql/evaluator_test.go
  8. 67
      pkg/logql/expr.y
  9. 516
      pkg/logql/expr.y.go
  10. 2
      pkg/logql/lex.go
  11. 216
      pkg/logql/parser_test.go
  12. 8
      pkg/logql/shardmapper_test.go

@ -1,5 +1,6 @@
// Code generated by vfsgen; DO NOT EDIT.
//go:build !dev
// +build !dev
package ui

@ -163,6 +163,23 @@ This example will return every machine total count within the last minutes ratio
sum by(machine) (count_over_time({app="foo"}[1m])) / on() sum(count_over_time({app="foo"}[1m]))
```
### Many-to-one and one-to-many vector matches
Many-to-one and one-to-many matchings occur when each vector element on the "one"-side can match with multiple elements on the "many"-side. You must explicitly request matching by using the group_left or group_right modifier, where left or right determines which vector has the higher cardinality.
The syntax:
```logql
<vector expr> <bin-op> ignoring(<labels>) group_left(<labels>) <vector expr>
<vector expr> <bin-op> ignoring(<labels>) group_right(<labels>) <vector expr>
<vector expr> <bin-op> on(<labels>) group_left(<labels>) <vector expr>
<vector expr> <bin-op> on(<labels>) group_right(<labels>) <vector expr>
```
The label list provided with the group modifier contains additional labels from the "one"-side that are included in the result metrics. And a label should only appear in one of the lists specified by `on` and `group_x`. Every time series of the result vector must be uniquely identifiable.
Grouping modifiers can only be used for comparison and arithmetic. By default, the system matches `and`, `unless`, and `or` operations with all entries in the right vector.
The following example returns sum results for the same application with the many part labels and the labels specified by the group_right operation.
```logql
sum by (app,pool) (count_over_time({foo="bar"}[1m])) + on (app) group_right (pool) sum by (app,machine) (count_over_time({foo="bar"}[1m]))
```
## Comments
LogQL queries can be commented using the `#` character:

@ -717,6 +717,9 @@ const (
OpOn = "on"
OpIgnoring = "ignoring"
OpGroupLeft = "group_left"
OpGroupRight = "group_right"
// conversion Op
OpConvBytes = "bytes"
OpConvDuration = "duration"
@ -964,8 +967,41 @@ func (e *VectorAggregationExpr) Walk(f WalkFn) {
e.Left.Walk(f)
}
// VectorMatchCardinality describes the cardinality relationship
// of two Vectors in a binary operation.
type VectorMatchCardinality int
const (
CardOneToOne VectorMatchCardinality = iota
CardManyToOne
CardOneToMany
)
func (vmc VectorMatchCardinality) String() string {
switch vmc {
case CardOneToOne:
return "one-to-one"
case CardManyToOne:
return "many-to-one"
case CardOneToMany:
return "one-to-many"
}
panic("promql.VectorMatchCardinality.String: unknown match cardinality")
}
// VectorMatching describes how elements from two Vectors in a binary
// operation are supposed to be matched.
type VectorMatching struct {
On bool
// The cardinality of the two Vectors.
Card VectorMatchCardinality
// MatchingLabels contains the labels which define equality of a pair of
// elements from the Vectors.
MatchingLabels []string
// On includes the given label names from matching,
// rather than excluding them.
On bool
// Include contains additional labels that should be included in
// the result from the side with the lower cardinality.
Include []string
}
@ -988,10 +1024,22 @@ func (e *BinOpExpr) String() string {
op = fmt.Sprintf("%s bool", op)
}
if e.Opts.VectorMatching != nil {
if e.Opts.VectorMatching.On {
op = fmt.Sprintf("%s %s (%s)", op, OpOn, strings.Join(e.Opts.VectorMatching.Include, ","))
} else {
op = fmt.Sprintf("%s %s (%s)", op, OpIgnoring, strings.Join(e.Opts.VectorMatching.Include, ","))
group := ""
if e.Opts.VectorMatching.Card == CardManyToOne {
group = OpGroupLeft
} else if e.Opts.VectorMatching.Card == CardOneToMany {
group = OpGroupRight
}
if e.Opts.VectorMatching.Include != nil {
group = fmt.Sprintf("%s (%s)", group, strings.Join(e.Opts.VectorMatching.Include, ","))
}
if e.Opts.VectorMatching.On || e.Opts.VectorMatching.MatchingLabels != nil {
on := OpOn
if !e.Opts.VectorMatching.On {
on = OpIgnoring
}
op = fmt.Sprintf("%s %s (%s) %s", op, on, strings.Join(e.Opts.VectorMatching.MatchingLabels, ","), group)
}
}
}

@ -318,7 +318,6 @@ func TestStringer(t *testing.T) {
out: `(0 > bool count_over_time({foo="bar"}[1m]))`,
},
{
in: `0 > count_over_time({foo="bar"}[1m])`,
out: `(0 > count_over_time({foo="bar"}[1m]))`,
},

@ -537,9 +537,7 @@ func TestEngine_LogsInstantQuery(t *testing.T) {
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `count_over_time({app="foo"}[1m])`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `count_over_time({app="bar"}[1m])`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}},
},
promql.Vector{},
},
{
`sum without(app) (count_over_time({app="foo"}[1m])) > bool sum without(app) (count_over_time({app="bar"}[1m]))`,
@ -554,9 +552,7 @@ func TestEngine_LogsInstantQuery(t *testing.T) {
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum without (app) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum without (app) (count_over_time({app="bar"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{}},
},
promql.Vector{},
},
{
`sum without(app) (count_over_time({app="foo"}[1m])) >= sum without(app) (count_over_time({app="bar"}[1m]))`,
@ -649,7 +645,24 @@ func TestEngine_LogsInstantQuery(t *testing.T) {
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 120}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 120}, Metric: labels.Labels{}},
},
},
{
`sum by (app,machine) (count_over_time({app="foo"}[1m])) + on (app) sum by (app) (count_over_time({app="foo"}[1m]))`,
time.Unix(60, 0),
logproto.FORWARD,
0,
[][]logproto.Series{
{newSeries(testSize, identity, `{app="foo",machine="fuzz"}`)},
{newSeries(testSize, identity, `{app="foo"}`)},
},
[]SelectSampleParams{
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 120}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}},
},
},
{
@ -666,7 +679,7 @@ func TestEngine_LogsInstantQuery(t *testing.T) {
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}},
},
},
{
@ -682,7 +695,79 @@ func TestEngine_LogsInstantQuery(t *testing.T) {
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
errors.New("multiple matches for labels"),
errors.New("multiple matches for labels: many-to-one matching must be explicit (group_left/group_right)"),
},
{
`sum by (app,machine) (count_over_time({app="foo"}[1m])) > bool on () group_left sum by (app) (count_over_time({app="foo"}[1m]))`,
time.Unix(60, 0),
logproto.FORWARD,
0,
[][]logproto.Series{
{newSeries(testSize, identity, `{app="foo",machine="fuzz"}`), newSeries(testSize, identity, `{app="foo",machine="buzz"}`)},
{newSeries(testSize, identity, `{app="foo"}`)},
},
[]SelectSampleParams{
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "buzz"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}}},
},
},
{
`sum by (app,machine) (count_over_time({app="foo"}[1m])) > bool on () group_left () sum by (app) (count_over_time({app="foo"}[1m]))`,
time.Unix(60, 0),
logproto.FORWARD,
0,
[][]logproto.Series{
{newSeries(testSize, identity, `{app="foo",machine="fuzz"}`), newSeries(testSize, identity, `{app="foo",machine="buzz"}`)},
{newSeries(testSize, identity, `{app="foo"}`)},
},
[]SelectSampleParams{
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "buzz"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}}},
},
},
{
`sum by (app,machine) (count_over_time({app="foo"}[1m])) > bool on (app) group_left (pool) sum by (app,pool) (count_over_time({app="foo"}[1m]))`,
time.Unix(60, 0),
logproto.FORWARD,
0,
[][]logproto.Series{
{newSeries(testSize, identity, `{app="foo",machine="fuzz"}`), newSeries(testSize, identity, `{app="foo",machine="buzz"}`)},
{newSeries(testSize, identity, `{app="foo",pool="foo"}`)},
},
[]SelectSampleParams{
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,pool) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "buzz"}, labels.Label{Name: "pool", Value: "foo"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}, labels.Label{Name: "pool", Value: "foo"}}},
},
},
{
`sum by (app,pool) (count_over_time({app="foo"}[1m])) > bool on (app) group_right (pool) sum by (app,machine) (count_over_time({app="foo"}[1m]))`,
time.Unix(60, 0),
logproto.FORWARD,
0,
[][]logproto.Series{
{newSeries(testSize, identity, `{app="foo",pool="foo"}`)},
{newSeries(testSize, identity, `{app="foo",machine="fuzz"}`), newSeries(testSize, identity, `{app="foo",machine="buzz"}`)},
},
[]SelectSampleParams{
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,pool) (count_over_time({app="foo"}[1m]))`}},
{&logproto.SampleQueryRequest{Start: time.Unix(0, 0), End: time.Unix(60, 0), Selector: `sum by (app,machine) (count_over_time({app="foo"}[1m]))`}},
},
promql.Vector{
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "buzz"}, labels.Label{Name: "pool", Value: "foo"}}},
promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}, labels.Label{Name: "machine", Value: "fuzz"}, labels.Label{Name: "pool", Value: "foo"}}},
},
},
} {
test := test

@ -3,6 +3,7 @@ package logql
import (
"container/heap"
"context"
"fmt"
"math"
"sort"
"time"
@ -547,71 +548,56 @@ func binOpStepEvaluator(
}
// we have two non literal legs
lhs, err := ev.StepEvaluator(ctx, ev, expr.SampleExpr, q)
lse, err := ev.StepEvaluator(ctx, ev, expr.SampleExpr, q)
if err != nil {
return nil, err
}
rhs, err := ev.StepEvaluator(ctx, ev, expr.RHS, q)
rse, err := ev.StepEvaluator(ctx, ev, expr.RHS, q)
if err != nil {
return nil, err
}
return newStepEvaluator(func() (bool, int64, promql.Vector) {
pairs := map[uint64][2]*promql.Sample{}
var ts int64
// populate pairs
for i, eval := range []StepEvaluator{lhs, rhs} {
next, timestamp, vec := eval.Next()
ts = timestamp
// These should _always_ happen at the same step on each evaluator.
if !next {
return next, ts, nil
}
for _, sample := range vec {
// TODO(owen-d): this seems wildly inefficient: we're calculating
// the hash on each sample & step per evaluator.
// We seem limited to this approach due to using the StepEvaluator ifc.
var hash uint64
if expr.Opts == nil || expr.Opts.VectorMatching == nil {
hash = sample.Metric.Hash()
} else if expr.Opts.VectorMatching.On {
hash = sample.Metric.WithLabels(expr.Opts.VectorMatching.Include...).Hash()
} else {
hash = sample.Metric.WithoutLabels(expr.Opts.VectorMatching.Include...).Hash()
}
pair := pairs[hash]
if pair[i] != nil {
err = errors.New("multiple matches for labels")
return false, ts, nil
}
pair[i] = &promql.Sample{
Metric: sample.Metric,
Point: sample.Point,
}
pairs[hash] = pair
}
var (
ts int64
next bool
lhs, rhs promql.Vector
)
next, ts, rhs = rse.Next()
// These should _always_ happen at the same step on each evaluator.
if !next {
return next, ts, nil
}
// build matching signature for each sample in right vector
rsigs := make([]uint64, len(rhs))
for i, sample := range rhs {
rsigs[i] = matchingSignature(sample, expr.Opts)
}
results := make(promql.Vector, 0, len(pairs))
for _, pair := range pairs {
// merge
filter := true
if expr.Opts != nil && expr.Opts.ReturnBool {
filter = false
}
if merged := mergeBinOp(expr.Op, pair[0], pair[1], filter, IsComparisonOperator(expr.Op)); merged != nil {
results = append(results, *merged)
}
next, ts, lhs = lse.Next()
if !next {
return next, ts, nil
}
// build matching signature for each sample in left vector
lsigs := make([]uint64, len(lhs))
for i, sample := range lhs {
lsigs[i] = matchingSignature(sample, expr.Opts)
}
var results promql.Vector
switch expr.Op {
case OpTypeAnd:
results = vectorAnd(lhs, rhs, lsigs, rsigs)
case OpTypeOr:
results = vectorOr(lhs, rhs, lsigs, rsigs)
case OpTypeUnless:
results = vectorUnless(lhs, rhs, lsigs, rsigs)
default:
results, err = vectorBinop(expr.Op, expr.Opts, lhs, rhs, lsigs, rsigs)
}
return true, ts, results
}, func() (lastError error) {
for _, ev := range []StepEvaluator{lhs, rhs} {
for _, ev := range []StepEvaluator{lse, rse} {
if err := ev.Close(); err != nil {
lastError = err
}
@ -622,7 +608,7 @@ func binOpStepEvaluator(
if err != nil {
errs = append(errs, err)
}
for _, ev := range []StepEvaluator{lhs, rhs} {
for _, ev := range []StepEvaluator{lse, rse} {
if err := ev.Error(); err != nil {
errs = append(errs, err)
}
@ -638,37 +624,190 @@ func binOpStepEvaluator(
})
}
func mergeBinOp(op string, left, right *promql.Sample, filter, isVectorComparison bool) *promql.Sample {
var merger func(left, right *promql.Sample) *promql.Sample
func matchingSignature(sample promql.Sample, opts *BinOpOptions) uint64 {
if opts == nil || opts.VectorMatching == nil {
return sample.Metric.Hash()
} else if opts.VectorMatching.On {
return sample.Metric.WithLabels(opts.VectorMatching.MatchingLabels...).Hash()
} else {
return sample.Metric.WithoutLabels(opts.VectorMatching.MatchingLabels...).Hash()
}
}
switch op {
case OpTypeOr:
merger = func(left, right *promql.Sample) *promql.Sample {
// return the left entry found (prefers left hand side)
if left != nil {
return left
func vectorBinop(op string, opts *BinOpOptions, lhs, rhs promql.Vector, lsigs, rsigs []uint64) (promql.Vector, error) {
// handle one-to-one or many-to-one matching
//for one-to-many, swap
if opts != nil && opts.VectorMatching.Card == CardOneToMany {
lhs, rhs = rhs, lhs
lsigs, rsigs = rsigs, lsigs
}
rightSigs := make(map[uint64]*promql.Sample)
matchedSigs := make(map[uint64]map[uint64]struct{})
results := make(promql.Vector, 0)
// Add all rhs samples to a map so we can easily find matches later.
for i, sample := range rhs {
sig := rsigs[i]
if rightSigs[sig] != nil {
side := "right"
if opts.VectorMatching.Card == CardOneToMany {
side = "left"
}
return right
return nil, fmt.Errorf("found duplicate series on the %s hand-side"+
";many-to-many matching not allowed: matching labels must be unique on one side", side)
}
rightSigs[sig] = &promql.Sample{
Metric: sample.Metric,
Point: sample.Point,
}
}
case OpTypeAnd:
merger = func(left, right *promql.Sample) *promql.Sample {
// return left sample if there's a second sample for that label set
if left != nil && right != nil {
return left
for i, sample := range lhs {
ls := &sample
sig := lsigs[i]
rs, found := rightSigs[sig] // Look for a match in the rhs Vector.
if !found {
continue
}
metric := resultMetric(ls.Metric, rs.Metric, opts)
insertedSigs, exists := matchedSigs[sig]
filter := true
if opts != nil {
if opts.VectorMatching.Card == CardOneToOne {
if exists {
return nil, errors.New("multiple matches for labels: many-to-one matching must be explicit (group_left/group_right)")
}
matchedSigs[sig] = nil
} else {
insertSig := metric.Hash()
if !exists {
insertedSigs = map[uint64]struct{}{}
matchedSigs[sig] = insertedSigs
} else if _, duplicate := insertedSigs[insertSig]; duplicate {
return nil, errors.New("multiple matches for labels: grouping labels must ensure unique matches")
}
insertedSigs[insertSig] = struct{}{}
}
// merge
if opts.ReturnBool {
filter = false
}
// swap back before apply binary operator
if opts.VectorMatching.Card == CardOneToMany {
ls, rs = rs, ls
}
return nil
}
case OpTypeUnless:
merger = func(left, right *promql.Sample) *promql.Sample {
// return left sample if there's not a second sample for that label set
if right == nil {
return left
if merged := mergeBinOp(op, ls, rs, filter, IsComparisonOperator(op)); merged != nil {
// replace with labels specified by expr
merged.Metric = metric
results = append(results, *merged)
}
}
return results, nil
}
func vectorAnd(lhs, rhs promql.Vector, lsigs, rsigs []uint64) promql.Vector {
if len(lhs) == 0 || len(rhs) == 0 {
return nil // Short-circuit: AND with nothing is nothing.
}
rightSigs := make(map[uint64]struct{})
results := make(promql.Vector, 0)
for _, sig := range rsigs {
rightSigs[sig] = struct{}{}
}
for i, ls := range lhs {
if _, ok := rightSigs[lsigs[i]]; ok {
results = append(results, ls)
}
}
return results
}
func vectorOr(lhs, rhs promql.Vector, lsigs, rsigs []uint64) promql.Vector {
if len(lhs) == 0 {
return rhs
} else if len(rhs) == 0 {
return lhs
}
leftSigs := make(map[uint64]struct{})
results := make(promql.Vector, 0)
for i, ls := range lhs {
leftSigs[lsigs[i]] = struct{}{}
results = append(results, ls)
}
for i, rs := range rhs {
if _, ok := leftSigs[rsigs[i]]; !ok {
results = append(results, rs)
}
}
return results
}
func vectorUnless(lhs, rhs promql.Vector, lsigs, rsigs []uint64) promql.Vector {
if len(lhs) == 0 || len(rhs) == 0 {
return lhs
}
rightSigs := make(map[uint64]struct{})
results := make(promql.Vector, 0)
for _, sig := range rsigs {
rightSigs[sig] = struct{}{}
}
for i, ls := range lhs {
if _, ok := rightSigs[lsigs[i]]; !ok {
results = append(results, ls)
}
}
return results
}
// resultMetric returns the metric for the given sample(s) based on the Vector
// binary operation and the matching options.
func resultMetric(lhs, rhs labels.Labels, opts *BinOpOptions) labels.Labels {
lb := labels.NewBuilder(lhs)
if opts != nil {
matching := opts.VectorMatching
if matching.Card == CardOneToOne {
if matching.On {
Outer:
for _, l := range lhs {
for _, n := range matching.MatchingLabels {
if l.Name == n {
continue Outer
}
}
lb.Del(l.Name)
}
} else {
lb.Del(matching.MatchingLabels...)
}
}
for _, ln := range matching.Include {
// Included labels from the `group_x` modifier are taken from the "one"-side.
if v := rhs.Get(ln); v != "" {
lb.Set(ln, v)
} else {
lb.Del(ln)
}
return nil
}
}
return lb.Labels()
}
func mergeBinOp(op string, left, right *promql.Sample, filter, isVectorComparison bool) *promql.Sample {
var merger func(left, right *promql.Sample) *promql.Sample
switch op {
case OpTypeAdd:
merger = func(left, right *promql.Sample) *promql.Sample {
if left == nil || right == nil {
@ -901,20 +1040,6 @@ func mergeBinOp(op string, left, right *promql.Sample, filter, isVectorCompariso
if res != nil {
return left
}
// otherwise it's been filtered out
return res
}
// This only leaves vector comparisons which are not filters.
// If we could not find a match but we have a left node to compare, create an entry with a 0 value.
// This can occur when we don't find a matching label set in the vectors.
if res == nil && left != nil && right == nil {
res = &promql.Sample{
Metric: left.Metric,
Point: left.Point,
}
res.Point.V = 0
}
return res
}

@ -203,15 +203,7 @@ func TestEvaluator_mergeBinOpComparisons(t *testing.T) {
require.Equal(t, tc.expected, mergeBinOp(tc.op, tc.lhs, tc.rhs, false, false))
require.Equal(t, tc.expected, mergeBinOp(tc.op, tc.lhs, tc.rhs, false, true))
// vector-vector comparing when not filtering should propagate the labels for nil right hand side matches,
// but set the value to zero.
require.Equal(
t,
&promql.Sample{
Point: promql.Point{V: 0},
},
mergeBinOp(tc.op, tc.lhs, nil, false, true),
)
require.Nil(t, mergeBinOp(tc.op, tc.lhs, nil, false, true))
// test filtered variants
if tc.expected.V == 0 {

@ -35,6 +35,7 @@ import (
LiteralExpr *LiteralExpr
BinOpModifier *BinOpOptions
BoolModifier *BinOpOptions
OnOrIgnoringModifier *BinOpOptions
LabelParser *LabelParserExpr
LineFilters *LineFilterExpr
LineFilter *LineFilterExpr
@ -80,6 +81,7 @@ import (
%type <LabelReplaceExpr> labelReplaceExpr
%type <BinOpModifier> binOpModifier
%type <BoolModifier> boolModifier
%type <OnOrIgnoringModifier> onOrIgnoringModifier
%type <LabelParser> labelParser
%type <PipelineExpr> pipelineExpr
%type <PipelineStage> pipelineStage
@ -108,7 +110,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
FIRST_OVER_TIME LAST_OVER_TIME ABSENT_OVER_TIME LABEL_REPLACE UNPACK OFFSET PATTERN IP ON IGNORING
FIRST_OVER_TIME LAST_OVER_TIME ABSENT_OVER_TIME LABEL_REPLACE UNPACK OFFSET PATTERN IP ON IGNORING GROUP_LEFT GROUP_RIGHT
// Operators are listed with increasing precedence.
%left <binOp> OR
@ -363,34 +365,75 @@ binOpExpr:
| expr LTE binOpModifier expr { $$ = mustNewBinOpExpr("<=", $3, $1, $4) }
;
binOpModifier:
boolModifier { $$ = $1 }
| boolModifier ON OPEN_PARENTHESIS labels CLOSE_PARENTHESIS
boolModifier:
{
$$ = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}}
}
| BOOL
{
$$ = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}, ReturnBool:true}
}
;
onOrIgnoringModifier:
boolModifier ON OPEN_PARENTHESIS labels CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching = &VectorMatching{On: true, Include: $4}
$$.VectorMatching.On=true
$$.VectorMatching.MatchingLabels=$4
}
| boolModifier ON OPEN_PARENTHESIS CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching = &VectorMatching{On: true, Include: nil}
$$.VectorMatching.On=true
}
| boolModifier IGNORING OPEN_PARENTHESIS labels CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching = &VectorMatching{On: false, Include: $4}
$$.VectorMatching.MatchingLabels=$4
}
| boolModifier IGNORING OPEN_PARENTHESIS CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching = &VectorMatching{On: false, Include: nil}
}
;
boolModifier:
{ $$ = &BinOpOptions{} }
| BOOL { $$ = &BinOpOptions{ ReturnBool: true } }
;
binOpModifier:
boolModifier {$$ = $1 }
| onOrIgnoringModifier {$$ = $1 }
| onOrIgnoringModifier GROUP_LEFT
{
$$ = $1
$$.VectorMatching.Card = CardManyToOne
}
| onOrIgnoringModifier GROUP_LEFT OPEN_PARENTHESIS CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching.Card = CardManyToOne
}
| onOrIgnoringModifier GROUP_LEFT OPEN_PARENTHESIS labels CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching.Card = CardManyToOne
$$.VectorMatching.Include = $4
}
| onOrIgnoringModifier GROUP_RIGHT
{
$$ = $1
$$.VectorMatching.Card = CardOneToMany
}
| onOrIgnoringModifier GROUP_RIGHT OPEN_PARENTHESIS CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching.Card = CardOneToMany
}
| onOrIgnoringModifier GROUP_RIGHT OPEN_PARENTHESIS labels CLOSE_PARENTHESIS
{
$$ = $1
$$.VectorMatching.Card = CardOneToMany
$$.VectorMatching.Include = $4
}
;
literalExpr:
NUMBER { $$ = mustNewLiteralExpr( $1, false ) }

@ -38,6 +38,7 @@ type exprSymType struct {
LiteralExpr *LiteralExpr
BinOpModifier *BinOpOptions
BoolModifier *BinOpOptions
OnOrIgnoringModifier *BinOpOptions
LabelParser *LabelParserExpr
LineFilters *LineFilterExpr
LineFilter *LineFilterExpr
@ -124,21 +125,23 @@ const PATTERN = 57406
const IP = 57407
const ON = 57408
const IGNORING = 57409
const OR = 57410
const AND = 57411
const UNLESS = 57412
const CMP_EQ = 57413
const NEQ = 57414
const LT = 57415
const LTE = 57416
const GT = 57417
const GTE = 57418
const ADD = 57419
const SUB = 57420
const MUL = 57421
const DIV = 57422
const MOD = 57423
const POW = 57424
const GROUP_LEFT = 57410
const GROUP_RIGHT = 57411
const OR = 57412
const AND = 57413
const UNLESS = 57414
const CMP_EQ = 57415
const NEQ = 57416
const LT = 57417
const LTE = 57418
const GT = 57419
const GTE = 57420
const ADD = 57421
const SUB = 57422
const MUL = 57423
const DIV = 57424
const MOD = 57425
const POW = 57426
var exprToknames = [...]string{
"$end",
@ -208,6 +211,8 @@ var exprToknames = [...]string{
"IP",
"ON",
"IGNORING",
"GROUP_LEFT",
"GROUP_RIGHT",
"OR",
"AND",
"UNLESS",
@ -239,130 +244,133 @@ var exprExca = [...]int{
const exprPrivate = 57344
const exprLast = 539
const exprLast = 532
var exprAct = [...]int{
243, 192, 76, 4, 173, 58, 161, 5, 166, 201,
67, 111, 50, 57, 246, 134, 69, 2, 45, 46,
248, 195, 76, 4, 176, 58, 164, 5, 169, 204,
67, 112, 50, 57, 122, 135, 69, 2, 45, 46,
47, 48, 49, 50, 72, 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, 130, 132,
133, 65, 309, 99, 175, 132, 133, 103, 63, 64,
223, 251, 185, 224, 222, 145, 146, 248, 61, 138,
309, 246, 136, 121, 84, 143, 51, 52, 55, 56,
53, 54, 45, 46, 47, 48, 49, 50, 75, 144,
77, 78, 147, 148, 149, 150, 151, 152, 153, 154,
155, 156, 157, 158, 159, 160, 77, 78, 131, 66,
285, 118, 170, 181, 176, 179, 180, 177, 178, 65,
219, 221, 184, 220, 218, 163, 63, 64, 100, 115,
183, 285, 123, 260, 199, 195, 203, 247, 300, 249,
193, 247, 204, 196, 65, 248, 312, 188, 260, 194,
329, 63, 64, 299, 293, 267, 292, 260, 191, 209,
210, 211, 262, 65, 188, 203, 248, 324, 246, 277,
63, 64, 248, 252, 194, 162, 248, 66, 203, 317,
118, 217, 241, 244, 265, 250, 255, 253, 136, 99,
256, 103, 257, 194, 163, 245, 242, 205, 115, 254,
260, 249, 66, 188, 191, 261, 65, 264, 266, 65,
270, 268, 203, 63, 64, 316, 63, 64, 314, 65,
295, 66, 65, 276, 258, 189, 63, 64, 197, 63,
64, 202, 306, 118, 286, 278, 194, 280, 282, 194,
284, 99, 118, 164, 162, 283, 294, 279, 118, 194,
99, 115, 60, 296, 125, 12, 163, 135, 124, 275,
115, 214, 163, 137, 66, 12, 115, 66, 274, 208,
303, 304, 207, 137, 182, 99, 305, 66, 142, 141,
66, 140, 307, 308, 288, 289, 290, 81, 313, 74,
327, 323, 298, 127, 259, 15, 215, 212, 206, 319,
198, 320, 321, 12, 190, 164, 162, 126, 129, 216,
128, 6, 213, 325, 322, 19, 20, 33, 34, 36,
37, 35, 38, 39, 40, 41, 21, 22, 238, 311,
235, 239, 237, 236, 234, 281, 23, 24, 25, 26,
27, 28, 29, 310, 291, 80, 30, 31, 32, 18,
232, 200, 229, 233, 231, 230, 228, 226, 79, 12,
227, 225, 272, 273, 328, 16, 17, 6, 326, 315,
302, 19, 20, 33, 34, 36, 37, 35, 38, 39,
40, 41, 21, 22, 3, 301, 271, 269, 263, 174,
318, 68, 23, 24, 25, 26, 27, 28, 29, 240,
187, 186, 30, 31, 32, 18, 297, 139, 185, 184,
171, 169, 168, 71, 167, 12, 73, 73, 174, 112,
113, 16, 17, 6, 165, 102, 118, 19, 20, 33,
34, 36, 37, 35, 38, 39, 40, 41, 21, 22,
172, 105, 104, 59, 115, 119, 114, 120, 23, 24,
25, 26, 27, 28, 29, 118, 101, 83, 30, 31,
32, 18, 106, 108, 107, 11, 116, 117, 251, 10,
9, 82, 122, 115, 14, 8, 287, 16, 17, 13,
7, 70, 62, 109, 1, 110, 0, 0, 0, 0,
0, 106, 108, 107, 0, 116, 117, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 109, 0, 110, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98,
47, 48, 49, 50, 47, 48, 49, 50, 131, 133,
134, 65, 320, 100, 178, 133, 134, 104, 63, 64,
148, 149, 228, 124, 188, 229, 227, 146, 147, 139,
251, 251, 137, 61, 256, 144, 51, 52, 55, 56,
53, 54, 45, 46, 47, 48, 49, 50, 253, 145,
294, 320, 294, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 323, 119, 85,
132, 66, 340, 173, 335, 184, 179, 182, 183, 180,
181, 328, 166, 226, 191, 253, 116, 253, 317, 77,
78, 186, 265, 101, 265, 202, 198, 311, 191, 310,
254, 196, 206, 207, 199, 65, 286, 252, 75, 65,
77, 78, 63, 64, 194, 302, 63, 64, 327, 65,
260, 275, 214, 215, 216, 254, 63, 64, 325, 257,
65, 194, 252, 65, 165, 197, 65, 63, 64, 197,
63, 64, 253, 63, 64, 246, 249, 301, 255, 197,
258, 137, 100, 261, 104, 262, 265, 304, 250, 247,
197, 309, 259, 197, 285, 66, 197, 253, 263, 66,
269, 271, 274, 276, 119, 279, 277, 65, 82, 66,
206, 265, 251, 119, 63, 64, 308, 284, 166, 206,
66, 295, 116, 66, 191, 119, 66, 166, 200, 273,
287, 116, 289, 291, 126, 293, 100, 60, 272, 166,
292, 303, 288, 116, 219, 100, 192, 224, 305, 187,
225, 223, 86, 87, 88, 89, 90, 91, 92, 93,
94, 95, 96, 97, 98, 99, 206, 66, 125, 314,
315, 297, 298, 299, 100, 316, 119, 283, 167, 165,
206, 318, 319, 265, 265, 270, 206, 324, 267, 266,
167, 165, 213, 136, 116, 119, 15, 212, 12, 208,
330, 12, 331, 332, 12, 205, 138, 211, 222, 138,
210, 185, 6, 116, 336, 143, 19, 20, 33, 34,
36, 37, 35, 38, 39, 40, 41, 21, 22, 142,
141, 107, 109, 108, 81, 117, 118, 23, 24, 25,
26, 27, 28, 29, 74, 338, 334, 30, 31, 32,
18, 203, 110, 307, 111, 264, 220, 217, 209, 12,
201, 193, 130, 221, 218, 333, 322, 6, 16, 17,
128, 19, 20, 33, 34, 36, 37, 35, 38, 39,
40, 41, 21, 22, 127, 243, 321, 129, 244, 242,
80, 300, 23, 24, 25, 26, 27, 28, 29, 290,
281, 282, 30, 31, 32, 18, 140, 240, 79, 237,
241, 239, 238, 236, 12, 234, 339, 231, 235, 233,
232, 230, 6, 16, 17, 119, 19, 20, 33, 34,
36, 37, 35, 38, 39, 40, 41, 21, 22, 3,
337, 326, 313, 116, 312, 278, 68, 23, 24, 25,
26, 27, 28, 29, 268, 245, 190, 30, 31, 32,
18, 107, 109, 108, 189, 117, 118, 256, 280, 188,
187, 177, 113, 174, 172, 171, 329, 71, 16, 17,
73, 306, 110, 170, 111, 73, 177, 114, 168, 103,
175, 106, 105, 59, 120, 115, 121, 102, 84, 83,
11, 10, 9, 123, 14, 8, 296, 13, 7, 70,
62, 1,
}
var exprPact = [...]int{
298, -1000, -43, -1000, -1000, 218, 298, -1000, -1000, -1000,
-1000, -1000, 421, 276, 75, -1000, 361, 348, 274, -1000,
309, -1000, -45, -1000, -1000, 213, 309, -1000, -1000, -1000,
-1000, -1000, 495, 341, 135, -1000, 421, 403, 331, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, 44, 44, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 218, -1000, 47,
460, -1000, 77, -1000, -1000, -1000, -1000, 244, 240, -43,
301, 302, -1000, 46, 260, 410, 268, 266, 265, -1000,
-1000, 298, 298, 9, -1000, 298, 298, 298, 298, 298,
298, 298, 298, 298, 298, 298, 298, 298, 298, -1000,
-1000, -1000, -1000, 185, -1000, -1000, 419, -1000, 416, -1000,
415, -1000, -1000, -1000, -1000, 238, 414, 423, 52, -1000,
-1000, -1000, 261, -1000, -1000, -1000, -1000, -1000, 422, -1000,
413, 412, 405, 404, 211, 295, 205, 250, 214, 291,
354, 217, 183, 289, -29, 259, 256, 15, 15, -25,
-25, -70, -70, -70, -70, -59, -59, -59, -59, -59,
-59, 185, 238, 238, 238, 288, -1000, 310, -1000, -1000,
247, -1000, 287, -1000, 307, 126, 66, 363, 358, 356,
336, 334, 403, -1000, -1000, -1000, -1000, -1000, -1000, 91,
250, 115, 138, 202, 431, 159, 172, 91, 298, 210,
285, 191, -1000, -1000, 148, -1000, 392, 170, 141, 253,
185, 116, 419, 391, -1000, 394, 367, 255, -1000, -1000,
-1000, 246, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, 79, 79, 79, 79, 79, 79, 79, 79,
79, 79, 79, 79, 79, 79, 79, 213, -1000, 47,
310, -1000, 8, -1000, -1000, -1000, -1000, 264, 230, -45,
388, 366, -1000, 46, 306, 419, 327, 326, 312, -1000,
-1000, 309, 309, 11, 2, -1000, 309, 309, 309, 309,
309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
-1000, -1000, -1000, -1000, 228, -1000, -1000, 498, -1000, 489,
-1000, 488, -1000, -1000, -1000, -1000, 291, 487, 501, 52,
-1000, -1000, -1000, 308, -1000, -1000, -1000, -1000, -1000, 500,
-1000, 484, 483, 478, 470, 242, 362, 172, 303, 224,
361, 364, 301, 295, 359, -31, 307, 304, 294, 289,
13, 13, -27, -27, -72, -72, -72, -72, -61, -61,
-61, -61, -61, -61, 228, 291, 291, 291, 358, -1000,
372, -1000, -1000, 240, -1000, 357, -1000, 371, 263, 68,
433, 431, 425, 423, 401, 469, -1000, -1000, -1000, -1000,
-1000, -1000, 114, 303, 169, 148, 166, 440, 155, 146,
114, 309, 194, 356, 285, -1000, -1000, 284, -1000, 468,
281, 234, 225, 147, 219, 228, 113, 498, 459, -1000,
486, 415, 274, -1000, -1000, -1000, 214, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
209, -1000, 155, 215, 33, 215, 337, -49, 238, -49,
111, 239, 345, 142, 140, -1000, -1000, 206, -1000, 298,
411, -1000, -1000, 283, 139, -1000, 124, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, 389, 374, -1000, 91, 33, 215,
33, -1000, -1000, 185, -1000, -49, -1000, 219, -1000, -1000,
-1000, 18, 344, 330, 132, 91, 204, -1000, 373, -1000,
-1000, 201, 165, -1000, 33, -1000, 395, 36, 33, 24,
-49, -49, 315, -1000, -1000, 282, -1000, -1000, 153, 33,
-1000, -1000, -49, 372, -1000, -1000, 281, 368, 136, -1000,
-1000, -1000, -1000, -1000, -1000, 190, -1000, 132, 145, 54,
145, 411, 17, 291, 17, 91, 236, 402, 173, 141,
-1000, -1000, 183, -1000, 309, 496, -1000, -1000, 354, 212,
-1000, 187, -1000, -1000, 125, -1000, 123, -1000, -1000, -1000,
-1000, -1000, -1000, 458, 456, -1000, 114, 54, 145, 54,
-1000, -1000, 228, -1000, 17, -1000, 115, -1000, -1000, -1000,
18, 397, 377, 93, 114, 154, -1000, 455, -1000, -1000,
-1000, -1000, 144, 107, -1000, 54, -1000, 491, 57, 54,
37, 17, 17, 376, -1000, -1000, 347, -1000, -1000, 100,
54, -1000, -1000, 17, 454, -1000, -1000, 346, 430, 98,
-1000,
}
var exprPgo = [...]int{
0, 494, 16, 492, 2, 9, 394, 3, 15, 11,
491, 490, 489, 486, 7, 485, 484, 482, 480, 479,
475, 481, 467, 466, 13, 5, 457, 456, 455, 6,
453, 78, 452, 451, 4, 450, 435, 8, 434, 1,
430, 429, 0,
0, 531, 16, 530, 2, 9, 459, 3, 15, 11,
529, 528, 527, 526, 7, 525, 524, 523, 522, 521,
520, 228, 519, 518, 517, 13, 5, 516, 515, 514,
6, 513, 83, 512, 511, 4, 510, 509, 8, 508,
1, 507, 492, 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,
8, 8, 8, 8, 8, 8, 8, 8, 8, 39,
39, 39, 13, 13, 13, 11, 11, 11, 11, 15,
8, 8, 8, 8, 8, 8, 8, 8, 8, 40,
40, 40, 13, 13, 13, 11, 11, 11, 11, 15,
15, 15, 15, 15, 15, 20, 3, 3, 3, 3,
14, 14, 14, 10, 10, 9, 9, 9, 9, 24,
24, 25, 25, 25, 25, 25, 25, 17, 31, 31,
30, 30, 23, 23, 23, 23, 23, 36, 32, 34,
34, 35, 35, 35, 33, 29, 29, 29, 29, 29,
29, 29, 29, 29, 37, 38, 38, 41, 41, 40,
40, 28, 28, 28, 28, 28, 28, 28, 26, 26,
26, 26, 26, 26, 26, 27, 27, 27, 27, 27,
27, 27, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 21, 21, 21,
21, 21, 22, 22, 19, 19, 19, 16, 16, 16,
16, 16, 16, 16, 16, 16, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
42, 5, 5, 4, 4, 4, 4,
14, 14, 14, 10, 10, 9, 9, 9, 9, 25,
25, 26, 26, 26, 26, 26, 26, 17, 32, 32,
31, 31, 24, 24, 24, 24, 24, 37, 33, 35,
35, 36, 36, 36, 34, 30, 30, 30, 30, 30,
30, 30, 30, 30, 38, 39, 39, 42, 42, 41,
41, 29, 29, 29, 29, 29, 29, 29, 27, 27,
27, 27, 27, 27, 27, 28, 28, 28, 28, 28,
28, 28, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 22, 22, 23,
23, 23, 23, 21, 21, 21, 21, 21, 21, 21,
21, 19, 19, 19, 16, 16, 16, 16, 16, 16,
16, 16, 16, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 43, 5, 5,
4, 4, 4, 4,
}
var exprR2 = [...]int{
@ -380,83 +388,88 @@ var exprR2 = [...]int{
1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 1, 5, 4,
5, 4, 0, 1, 1, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4, 4, 4, 4, 4, 4, 4, 0, 1, 5,
4, 5, 4, 1, 1, 2, 4, 5, 2, 4,
5, 1, 2, 2, 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, 2, 1, 3,
4, 4, 3, 3,
}
var exprChk = [...]int{
-1000, -1, -2, -6, -7, -14, 23, -11, -15, -18,
-19, -20, 15, -12, -16, 7, 77, 78, 61, 27,
-19, -20, 15, -12, -16, 7, 79, 80, 61, 27,
28, 38, 39, 48, 49, 50, 51, 52, 53, 54,
58, 59, 60, 29, 30, 33, 31, 32, 34, 35,
36, 37, 68, 69, 70, 77, 78, 79, 80, 81,
82, 71, 72, 75, 76, 73, 74, -24, -25, -30,
44, -31, -3, 21, 22, 14, 72, -7, -6, -2,
36, 37, 70, 71, 72, 79, 80, 81, 82, 83,
84, 73, 74, 77, 78, 75, 76, -25, -26, -31,
44, -32, -3, 21, 22, 14, 74, -7, -6, -2,
-10, 2, -9, 5, 23, 23, -4, 25, 26, 7,
7, 23, -21, -22, 40, -21, -21, -21, -21, -21,
-21, -21, -21, -21, -21, -21, -21, -21, -21, -25,
-31, -23, -36, -29, -32, -33, 41, 43, 42, 62,
64, -9, -41, -40, -27, 23, 45, 46, 5, -28,
-26, 6, -17, 65, 24, 24, 16, 2, 19, 16,
12, 72, 13, 14, -8, 7, -14, 23, -7, 7,
23, 23, 23, -7, -2, 66, 67, -2, -2, -2,
7, 23, -21, -22, -23, 40, -21, -21, -21, -21,
-21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
-26, -32, -24, -37, -30, -33, -34, 41, 43, 42,
62, 64, -9, -42, -41, -28, 23, 45, 46, 5,
-29, -27, 6, -17, 65, 24, 24, 16, 2, 19,
16, 12, 74, 13, 14, -8, 7, -14, 23, -7,
7, 23, 23, 23, -7, -2, 66, 67, 68, 69,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -29, 69, 19, 68, -38, -37, 5, 6, 6,
-29, 6, -35, -34, 5, 12, 72, 75, 76, 73,
74, 71, 23, -9, 6, 6, 6, 6, 2, 24,
19, 9, -39, -24, 44, -14, -8, 24, 19, -7,
7, -5, 24, 5, -5, 24, 19, 23, 23, -29,
-29, -29, 19, 12, 24, 19, 12, 65, 8, 4,
7, 65, 8, 4, 7, 8, 4, 7, 8, 4,
7, 8, 4, 7, 8, 4, 7, 8, 4, 7,
6, -4, -8, -42, -39, -24, 63, 9, 44, 9,
-39, 47, 24, -39, -24, 24, -4, -7, 24, 19,
19, 24, 24, 6, -5, 24, -5, 24, -37, 6,
-34, 2, 5, 6, 23, 23, 24, 24, -39, -24,
-39, 8, -42, -29, -42, 9, 5, -13, 55, 56,
57, 9, 24, 24, -39, 24, -7, 5, 19, 24,
24, 6, 6, -4, -39, -42, 23, -42, -39, 44,
9, 9, 24, -4, 24, 6, 24, 24, 5, -39,
-42, -42, 9, 19, 24, -42, 6, 19, 6, 24,
-2, -2, -2, -2, -30, 71, 19, 70, -39, -38,
5, 6, 6, -30, 6, -36, -35, 5, 12, 74,
77, 78, 75, 76, 73, 23, -9, 6, 6, 6,
6, 2, 24, 19, 9, -40, -25, 44, -14, -8,
24, 19, -7, 7, -5, 24, 5, -5, 24, 19,
23, 23, 23, 23, -30, -30, -30, 19, 12, 24,
19, 12, 65, 8, 4, 7, 65, 8, 4, 7,
8, 4, 7, 8, 4, 7, 8, 4, 7, 8,
4, 7, 8, 4, 7, 6, -4, -8, -43, -40,
-25, 63, 9, 44, 9, -40, 47, 24, -40, -25,
24, -4, -7, 24, 19, 19, 24, 24, 6, -5,
24, -5, 24, 24, -5, 24, -5, -38, 6, -35,
2, 5, 6, 23, 23, 24, 24, -40, -25, -40,
8, -43, -30, -43, 9, 5, -13, 55, 56, 57,
9, 24, 24, -40, 24, -7, 5, 19, 24, 24,
24, 24, 6, 6, -4, -40, -43, 23, -43, -40,
44, 9, 9, 24, -4, 24, 6, 24, 24, 5,
-40, -43, -43, 9, 19, 24, -43, 6, 19, 6,
24,
}
var exprDef = [...]int{
0, -2, 1, 2, 3, 10, 0, 4, 5, 6,
7, 8, 0, 0, 0, 154, 0, 0, 0, 166,
167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
177, 178, 179, 157, 158, 159, 160, 161, 162, 163,
164, 165, 152, 152, 152, 152, 152, 152, 152, 152,
152, 152, 152, 152, 152, 152, 152, 11, 69, 71,
7, 8, 0, 0, 0, 161, 0, 0, 0, 173,
174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 164, 165, 166, 167, 168, 169, 170,
171, 172, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 11, 69, 71,
0, 80, 0, 56, 57, 58, 59, 3, 2, 0,
0, 0, 63, 0, 0, 0, 0, 0, 0, 155,
156, 0, 0, 147, 153, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 70,
81, 72, 73, 74, 75, 76, 82, 83, 0, 85,
0, 95, 96, 97, 98, 0, 0, 0, 0, 109,
110, 78, 0, 77, 9, 12, 60, 61, 0, 62,
0, 0, 0, 0, 0, 0, 0, 0, 3, 154,
0, 0, 0, 3, 132, 0, 0, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 100, 0, 0, 0, 87, 105, 0, 84, 86,
0, 88, 94, 91, 0, 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,
154, 0, 185, 181, 0, 186, 0, 0, 0, 101,
102, 103, 0, 0, 99, 0, 0, 0, 116, 123,
130, 0, 115, 122, 129, 111, 118, 125, 112, 119,
126, 113, 120, 127, 114, 121, 128, 117, 124, 131,
0, 47, 0, 14, 17, 33, 0, 21, 0, 25,
0, 0, 0, 0, 0, 37, 51, 3, 50, 0,
0, 183, 184, 0, 0, 149, 0, 151, 106, 104,
92, 93, 89, 90, 0, 0, 79, 46, 18, 34,
35, 180, 22, 41, 26, 29, 39, 0, 42, 43,
44, 15, 0, 0, 0, 52, 3, 182, 0, 148,
150, 0, 0, 48, 36, 30, 0, 16, 19, 0,
23, 27, 0, 53, 54, 0, 107, 108, 0, 20,
24, 28, 31, 0, 40, 32, 0, 0, 0, 55,
0, 0, 63, 0, 0, 0, 0, 0, 0, 162,
163, 0, 0, 153, 154, 148, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70, 81, 72, 73, 74, 75, 76, 82, 83, 0,
85, 0, 95, 96, 97, 98, 0, 0, 0, 0,
109, 110, 78, 0, 77, 9, 12, 60, 61, 0,
62, 0, 0, 0, 0, 0, 0, 0, 0, 3,
161, 0, 0, 0, 3, 132, 0, 0, 155, 158,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 100, 0, 0, 0, 87, 105,
0, 84, 86, 0, 88, 94, 91, 0, 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, 161, 0, 192, 188, 0, 193, 0,
0, 0, 0, 0, 101, 102, 103, 0, 0, 99,
0, 0, 0, 116, 123, 130, 0, 115, 122, 129,
111, 118, 125, 112, 119, 126, 113, 120, 127, 114,
121, 128, 117, 124, 131, 0, 47, 0, 14, 17,
33, 0, 21, 0, 25, 0, 0, 0, 0, 0,
37, 51, 3, 50, 0, 0, 190, 191, 0, 0,
150, 0, 152, 156, 0, 159, 0, 106, 104, 92,
93, 89, 90, 0, 0, 79, 46, 18, 34, 35,
187, 22, 41, 26, 29, 39, 0, 42, 43, 44,
15, 0, 0, 0, 52, 3, 189, 0, 149, 151,
157, 160, 0, 0, 48, 36, 30, 0, 16, 19,
0, 23, 27, 0, 53, 54, 0, 107, 108, 0,
20, 24, 28, 31, 0, 40, 32, 0, 0, 0,
55,
}
var exprTok1 = [...]int{
@ -472,7 +485,7 @@ var exprTok2 = [...]int{
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, 77, 78, 79, 80, 81,
82,
82, 83, 84,
}
var exprTok3 = [...]int{
0,
@ -1534,205 +1547,248 @@ exprdefault:
exprVAL.BinOpExpr = mustNewBinOpExpr("<=", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr)
}
case 147:
exprDollar = exprS[exprpt-1 : exprpt+1]
exprDollar = exprS[exprpt-0 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
exprVAL.BoolModifier = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}}
}
case 148:
exprDollar = exprS[exprpt-5 : exprpt+1]
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
exprVAL.BinOpModifier.VectorMatching = &VectorMatching{On: true, Include: exprDollar[4].Labels}
exprVAL.BoolModifier = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}, ReturnBool: true}
}
case 149:
exprDollar = exprS[exprpt-4 : exprpt+1]
exprDollar = exprS[exprpt-5 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
exprVAL.BinOpModifier.VectorMatching = &VectorMatching{On: true, Include: nil}
exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier
exprVAL.OnOrIgnoringModifier.VectorMatching.On = true
exprVAL.OnOrIgnoringModifier.VectorMatching.MatchingLabels = exprDollar[4].Labels
}
case 150:
exprDollar = exprS[exprpt-5 : exprpt+1]
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
exprVAL.BinOpModifier.VectorMatching = &VectorMatching{On: false, Include: exprDollar[4].Labels}
exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier
exprVAL.OnOrIgnoringModifier.VectorMatching.On = true
}
case 151:
exprDollar = exprS[exprpt-4 : exprpt+1]
exprDollar = exprS[exprpt-5 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
exprVAL.BinOpModifier.VectorMatching = &VectorMatching{On: false, Include: nil}
exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier
exprVAL.OnOrIgnoringModifier.VectorMatching.MatchingLabels = exprDollar[4].Labels
}
case 152:
exprDollar = exprS[exprpt-0 : exprpt+1]
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.BoolModifier = &BinOpOptions{}
exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier
}
case 153:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.BoolModifier = &BinOpOptions{ReturnBool: true}
exprVAL.BinOpModifier = exprDollar[1].BoolModifier
}
case 154:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[1].str, false)
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
}
case 155:
exprDollar = exprS[exprpt-2 : exprpt+1]
{
exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[2].str, false)
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne
}
case 156:
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne
}
case 157:
exprDollar = exprS[exprpt-5 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne
exprVAL.BinOpModifier.VectorMatching.Include = exprDollar[4].Labels
}
case 158:
exprDollar = exprS[exprpt-2 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany
}
case 159:
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany
}
case 160:
exprDollar = exprS[exprpt-5 : exprpt+1]
{
exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier
exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany
exprVAL.BinOpModifier.VectorMatching.Include = exprDollar[4].Labels
}
case 161:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[1].str, false)
}
case 162:
exprDollar = exprS[exprpt-2 : exprpt+1]
{
exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[2].str, false)
}
case 163:
exprDollar = exprS[exprpt-2 : exprpt+1]
{
exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[2].str, true)
}
case 157:
case 164:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeSum
}
case 158:
case 165:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeAvg
}
case 159:
case 166:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeCount
}
case 160:
case 167:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeMax
}
case 161:
case 168:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeMin
}
case 162:
case 169:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeStddev
}
case 163:
case 170:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeStdvar
}
case 164:
case 171:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeBottomK
}
case 165:
case 172:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.VectorOp = OpTypeTopK
}
case 166:
case 173:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeCount
}
case 167:
case 174:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeRate
}
case 168:
case 175:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeBytes
}
case 169:
case 176:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeBytesRate
}
case 170:
case 177:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeAvg
}
case 171:
case 178:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeSum
}
case 172:
case 179:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeMin
}
case 173:
case 180:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeMax
}
case 174:
case 181:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeStdvar
}
case 175:
case 182:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeStddev
}
case 176:
case 183:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeQuantile
}
case 177:
case 184:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeFirst
}
case 178:
case 185:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeLast
}
case 179:
case 186:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.RangeOp = OpRangeTypeAbsent
}
case 180:
case 187:
exprDollar = exprS[exprpt-2 : exprpt+1]
{
exprVAL.OffsetExpr = newOffsetExpr(exprDollar[2].duration)
}
case 181:
case 188:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Labels = []string{exprDollar[1].str}
}
case 182:
case 189:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Labels = append(exprDollar[1].Labels, exprDollar[3].str)
}
case 183:
case 190:
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.Grouping = &Grouping{Without: false, Groups: exprDollar[3].Labels}
}
case 184:
case 191:
exprDollar = exprS[exprpt-4 : exprpt+1]
{
exprVAL.Grouping = &Grouping{Without: true, Groups: exprDollar[3].Labels}
}
case 185:
case 192:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Grouping = &Grouping{Without: false, Groups: nil}
}
case 186:
case 193:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Grouping = &Grouping{Without: true, Groups: nil}

@ -38,6 +38,8 @@ var tokens = map[string]int{
OpOffset: OFFSET,
OpOn: ON,
OpIgnoring: IGNORING,
OpGroupLeft: GROUP_LEFT,
OpGroupRight: GROUP_RIGHT,
// binops
OpTypeOr: OR,

@ -938,10 +938,14 @@ func TestParse(t *testing.T) {
`,
exp: mustNewBinOpExpr(
OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewBinOpExpr(
OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
Left: &MatchersExpr{
@ -1001,10 +1005,14 @@ func TestParse(t *testing.T) {
`,
exp: mustNewBinOpExpr(
OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewBinOpExpr(
OpTypePow,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
Left: &MatchersExpr{
@ -1065,7 +1073,9 @@ func TestParse(t *testing.T) {
`,
exp: mustNewBinOpExpr(
OpTypeAdd,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
Left: &MatchersExpr{
@ -1084,7 +1094,9 @@ func TestParse(t *testing.T) {
),
mustNewBinOpExpr(
OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
Left: &MatchersExpr{
@ -1128,7 +1140,9 @@ func TestParse(t *testing.T) {
)`,
exp: mustNewVectorAggregationExpr(
mustNewBinOpExpr(OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
newRangeAggregationExpr(
&LogRange{
Left: newPipelineExpr(
@ -1156,9 +1170,13 @@ func TestParse(t *testing.T) {
/
count_over_time({namespace="tns"}[5m])
) * 100`,
exp: mustNewBinOpExpr(OpTypeMul, &BinOpOptions{}, mustNewVectorAggregationExpr(
exp: mustNewBinOpExpr(OpTypeMul, &BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
}, mustNewVectorAggregationExpr(
mustNewBinOpExpr(OpTypeDiv,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
newRangeAggregationExpr(
&LogRange{
Left: newPipelineExpr(
@ -1187,7 +1205,9 @@ func TestParse(t *testing.T) {
in: `sum(count_over_time({foo="bar"}[5m])) by (foo) + 1 / 2`,
exp: mustNewBinOpExpr(
OpTypeAdd,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
@ -1213,9 +1233,13 @@ func TestParse(t *testing.T) {
in: `1 + -2 / 1`,
exp: mustNewBinOpExpr(
OpTypeAdd,
&BinOpOptions{},
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
&LiteralExpr{value: 1},
mustNewBinOpExpr(OpTypeDiv, &BinOpOptions{}, &LiteralExpr{value: -2}, &LiteralExpr{value: 1}),
mustNewBinOpExpr(OpTypeDiv, &BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
}, &LiteralExpr{value: -2}, &LiteralExpr{value: 1}),
),
},
{
@ -1223,8 +1247,12 @@ func TestParse(t *testing.T) {
in: `1 + 1 - -1`,
exp: mustNewBinOpExpr(
OpTypeSub,
&BinOpOptions{},
mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{}, &LiteralExpr{value: 1}, &LiteralExpr{value: 1}),
&BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne},
}, &LiteralExpr{value: 1}, &LiteralExpr{value: 1}),
&LiteralExpr{value: -1},
),
},
@ -2109,7 +2137,8 @@ func TestParse(t *testing.T) {
) by (namespace,instance)
) by (foo,bar)
`,
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false},
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{
VectorMatching: &VectorMatching{Card: CardOneToOne}, ReturnBool: false},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
@ -2190,7 +2219,7 @@ func TestParse(t *testing.T) {
) by (namespace,instance)
) by (foo)
`,
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false, VectorMatching: &VectorMatching{On: false, Include: []string{"bar"}}},
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false, VectorMatching: &VectorMatching{Card: CardOneToOne, On: false, MatchingLabels: []string{"bar"}}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
@ -2271,7 +2300,88 @@ func TestParse(t *testing.T) {
) by (namespace,instance)
) by (foo)
`,
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false, VectorMatching: &VectorMatching{On: true, Include: []string{"foo"}}},
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false, VectorMatching: &VectorMatching{Card: CardOneToOne, On: true, MatchingLabels: []string{"foo"}}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
MultiStages: MultiStageExpr{
newLineFilterExpr(labels.MatchEqual, "", "bar"),
newLabelParserExpr(OpParserTypeJSON, ""),
&LabelFilterExpr{
LabelFilterer: log.NewOrLabelFilter(
log.NewDurationLabelFilter(log.LabelFilterGreaterThanOrEqual, "latency", 250*time.Millisecond),
log.NewAndLabelFilter(
log.NewNumericLabelFilter(log.LabelFilterLesserThan, "status_code", 500.0),
log.NewNumericLabelFilter(log.LabelFilterGreaterThan, "status_code", 200.0),
),
),
},
newLineFmtExpr("blip{{ .foo }}blop {{.status_code}}"),
newLabelFmtExpr([]log.LabelFmt{
log.NewRenameLabelFmt("foo", "bar"),
log.NewTemplateLabelFmt("status_code", "buzz{{.bar}}"),
}),
},
},
5*time.Minute,
newUnwrapExpr("foo", ""),
nil),
OpRangeTypeQuantile, &Grouping{Without: false, Groups: []string{"namespace", "instance"}}, NewStringLabelFilter("0.99998"),
),
OpTypeSum,
&Grouping{Groups: []string{"foo", "bar"}},
nil,
),
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
MultiStages: MultiStageExpr{
newLineFilterExpr(labels.MatchEqual, "", "bar"),
newLabelParserExpr(OpParserTypeJSON, ""),
&LabelFilterExpr{
LabelFilterer: log.NewOrLabelFilter(
log.NewDurationLabelFilter(log.LabelFilterGreaterThanOrEqual, "latency", 250*time.Millisecond),
log.NewAndLabelFilter(
log.NewNumericLabelFilter(log.LabelFilterLesserThan, "status_code", 500.0),
log.NewNumericLabelFilter(log.LabelFilterGreaterThan, "status_code", 200.0),
),
),
},
newLineFmtExpr("blip{{ .foo }}blop {{.status_code}}"),
newLabelFmtExpr([]log.LabelFmt{
log.NewRenameLabelFmt("foo", "bar"),
log.NewTemplateLabelFmt("status_code", "buzz{{.bar}}"),
}),
},
},
5*time.Minute,
newUnwrapExpr("foo", ""),
nil),
OpRangeTypeAvg, &Grouping{Without: false, Groups: []string{"namespace", "instance"}}, nil,
),
OpTypeAvg,
&Grouping{Groups: []string{"foo"}},
nil,
),
),
},
{
in: `
sum by (foo,bar) (
quantile_over_time(0.99998,{app="foo"} |= "bar" | json | latency >= 250ms or ( status_code < 500 and status_code > 200)
| line_format "blip{{ .foo }}blop {{.status_code}}" | label_format foo=bar,status_code="buzz{{.bar}}" | unwrap foo [5m]
) by (namespace,instance)
)
+ ignoring (bar) group_left (foo)
avg(
avg_over_time({app="foo"} |= "bar" | json | latency >= 250ms or ( status_code < 500 and status_code > 200)
| line_format "blip{{ .foo }}blop {{.status_code}}" | label_format foo=bar,status_code="buzz{{.bar}}" | unwrap foo [5m]
) by (namespace,instance)
) by (foo)
`,
exp: mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false, VectorMatching: &VectorMatching{Card: CardManyToOne, Include: []string{"foo"}, On: false, MatchingLabels: []string{"bar"}}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
@ -2338,6 +2448,68 @@ func TestParse(t *testing.T) {
),
),
},
{
in: `
sum by (app,machine) (count_over_time({app="foo"}[1m])) > bool on () group_right (app) sum by (app) (count_over_time({app="foo"}[1m]))
`,
exp: mustNewBinOpExpr(OpTypeGT, &BinOpOptions{ReturnBool: true, VectorMatching: &VectorMatching{Card: CardOneToMany, Include: []string{"app"}, On: true, MatchingLabels: nil}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
OpRangeTypeCount, nil, nil,
),
OpTypeSum,
&Grouping{Groups: []string{"app", "machine"}},
nil,
),
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
OpRangeTypeCount, nil, nil,
),
OpTypeSum,
&Grouping{Groups: []string{"app"}},
nil,
),
),
},
{
in: `
sum by (app,machine) (count_over_time({app="foo"}[1m])) > bool on () group_right sum by (app) (count_over_time({app="foo"}[1m]))
`,
exp: mustNewBinOpExpr(OpTypeGT, &BinOpOptions{ReturnBool: true, VectorMatching: &VectorMatching{Card: CardOneToMany, Include: nil, On: true, MatchingLabels: nil}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
OpRangeTypeCount, nil, nil,
),
OpTypeSum,
&Grouping{Groups: []string{"app", "machine"}},
nil,
),
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
OpRangeTypeCount, nil, nil,
),
OpTypeSum,
&Grouping{Groups: []string{"app"}},
nil,
),
),
},
{
in: `
label_replace(
@ -2358,7 +2530,7 @@ func TestParse(t *testing.T) {
"(.*)"
)`,
exp: mustNewLabelReplaceExpr(
mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{ReturnBool: false},
mustNewBinOpExpr(OpTypeAdd, &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}, ReturnBool: false},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
newLogRange(&PipelineExpr{
@ -2497,7 +2669,7 @@ func TestParse(t *testing.T) {
Op: OpTypeGT,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
@ -2521,7 +2693,7 @@ func TestParse(t *testing.T) {
Op: OpTypeGT,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
@ -2544,7 +2716,7 @@ func TestParse(t *testing.T) {
Op: OpTypeOr,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
@ -2557,7 +2729,7 @@ func TestParse(t *testing.T) {
Op: OpTypeGT,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{

@ -686,7 +686,7 @@ func TestMapping(t *testing.T) {
Op: OpTypeAdd,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &LiteralExpr{value: 1},
RHS: &VectorAggregationExpr{
@ -864,7 +864,7 @@ func TestMapping(t *testing.T) {
Op: OpTypeDiv,
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: nil,
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &VectorAggregationExpr{
Operation: OpTypeMax,
@ -987,8 +987,8 @@ func TestMapping(t *testing.T) {
Opts: &BinOpOptions{
ReturnBool: false,
VectorMatching: &VectorMatching{
On: false,
Include: []string{"cluster"},
On: false,
MatchingLabels: []string{"cluster"},
},
},
SampleExpr: &VectorAggregationExpr{

Loading…
Cancel
Save