From 36c703dae82615c8d67ca7ca88f1d7e11a5ec4e5 Mon Sep 17 00:00:00 2001 From: Anton Kolesnikov Date: Tue, 2 Apr 2024 14:47:21 +0800 Subject: [PATCH] feat: add pattern match line filter (#12398) --- CHANGELOG.md | 1 + pkg/logql/log/filter.go | 45 ++ pkg/logql/log/parser.go | 2 +- pkg/logql/log/pattern/ast.go | 33 +- pkg/logql/log/pattern/parser.go | 6 +- pkg/logql/log/pattern/pattern.go | 93 ++- pkg/logql/log/pattern/pattern_test.go | 91 ++- pkg/logql/syntax/ast.go | 2 +- pkg/logql/syntax/ast_test.go | 58 +- pkg/logql/syntax/expr.y | 4 +- pkg/logql/syntax/expr.y.go | 915 +++++++++++----------- pkg/logql/syntax/lex.go | 2 + pkg/logql/syntax/linefilter_test.go | 5 +- pkg/storage/bloom/v1/bloom_tester.go | 22 +- pkg/storage/bloom/v1/bloom_tester_test.go | 36 + 15 files changed, 827 insertions(+), 488 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdc5c9c29ed06..289045cf2f6bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ * [11970](https://github.com/grafana/loki/pull/11897) **masslessparticle** Ksonnet: Introduces memory limits to the compactor configuration to avoid unbounded memory usage. * [12318](https://github.com/grafana/loki/pull/12318) **DylanGuedes** Memcached: Add mTLS support. * [12392](https://github.com/grafana/loki/pull/12392) **sandeepsukhani** Detect name of service emitting logs and add it as a label. +* [12398](https://github.com/grafana/loki/pull/12398) **kolesnikovae** LogQL: Introduces pattern match filter operators. ##### Fixes * [11074](https://github.com/grafana/loki/pull/11074) **hainenber** Fix panic in lambda-promtail due to mishandling of empty DROP_LABELS env var. diff --git a/pkg/logql/log/filter.go b/pkg/logql/log/filter.go index 164741f4c8c96..8a9a162828638 100644 --- a/pkg/logql/log/filter.go +++ b/pkg/logql/log/filter.go @@ -11,6 +11,7 @@ import ( "github.com/prometheus/prometheus/model/labels" + "github.com/grafana/loki/pkg/logql/log/pattern" "github.com/grafana/loki/pkg/util" ) @@ -23,6 +24,8 @@ const ( LineMatchNotEqual LineMatchRegexp LineMatchNotRegexp + LineMatchPattern + LineMatchNotPattern ) func (t LineMatchType) String() string { @@ -35,6 +38,10 @@ func (t LineMatchType) String() string { return "|~" case LineMatchNotRegexp: return "!~" + case LineMatchPattern: + return "|>" + case LineMatchNotPattern: + return "!>" default: return "" } @@ -553,6 +560,10 @@ func NewFilter(match string, mt LineMatchType) (Filterer, error) { return newContainsFilter([]byte(match), false), nil case LineMatchNotEqual: return NewNotFilter(newContainsFilter([]byte(match), false)), nil + case LineMatchPattern: + return newPatternFilterer([]byte(match), true) + case LineMatchNotPattern: + return newPatternFilterer([]byte(match), false) default: return nil, fmt.Errorf("unknown matcher: %v", match) } @@ -783,3 +794,37 @@ func (s *RegexSimplifier) simplifyConcatAlternate(reg *syntax.Regexp, literal [] } return nil, false } + +type patternFilter struct { + matcher *pattern.Matcher + pattern []byte +} + +func newPatternFilterer(p []byte, match bool) (MatcherFilterer, error) { + m, err := pattern.ParseLineFilter(p) + if err != nil { + return nil, err + } + filter := &patternFilter{ + matcher: m, + pattern: p, + } + if !match { + return NewNotFilter(filter), nil + } + return filter, nil +} + +func (f *patternFilter) Filter(line []byte) bool { return f.matcher.Test(line) } + +func (f *patternFilter) Matches(test Checker) bool { + return test.Test(f.pattern, false, false) +} + +func (f *patternFilter) ToStage() Stage { + return StageFunc{ + process: func(_ int64, line []byte, _ *LabelsBuilder) ([]byte, bool) { + return line, f.Filter(line) + }, + } +} diff --git a/pkg/logql/log/parser.go b/pkg/logql/log/parser.go index 90d4a4bebf8ab..afdc7f91a4f9d 100644 --- a/pkg/logql/log/parser.go +++ b/pkg/logql/log/parser.go @@ -373,7 +373,7 @@ func (l *LogfmtParser) Process(_ int64, line []byte, lbs *LabelsBuilder) ([]byte func (l *LogfmtParser) RequiredLabelNames() []string { return []string{} } type PatternParser struct { - matcher pattern.Matcher + matcher *pattern.Matcher names []string } diff --git a/pkg/logql/log/pattern/ast.go b/pkg/logql/log/pattern/ast.go index b4cf8e813f968..677db07dcfbef 100644 --- a/pkg/logql/log/pattern/ast.go +++ b/pkg/logql/log/pattern/ast.go @@ -20,6 +20,21 @@ func (e expr) validate() error { return ErrNoCapture } // Consecutive captures are not allowed. + if err := e.validateNoConsecutiveCaptures(); err != nil { + return err + } + caps := e.captures() + uniq := map[string]struct{}{} + for _, c := range caps { + if _, ok := uniq[c]; ok { + return fmt.Errorf("duplicate capture name (%s): %w", c, ErrInvalidExpr) + } + uniq[c] = struct{}{} + } + return nil +} + +func (e expr) validateNoConsecutiveCaptures() error { for i, n := range e { if i+1 >= len(e) { break @@ -30,21 +45,21 @@ func (e expr) validate() error { } } } + return nil +} - caps := e.captures() - uniq := map[string]struct{}{} - for _, c := range caps { - if _, ok := uniq[c]; ok { - return fmt.Errorf("duplicate capture name (%s): %w", c, ErrInvalidExpr) +func (e expr) validateNoNamedCaptures() error { + for i, n := range e { + if c, ok := e[i].(capture); ok && !c.isUnnamed() { + return fmt.Errorf("%w: found '%s'", ErrCaptureNotAllowed, n.String()) } - uniq[c] = struct{}{} } return nil } func (e expr) captures() (captures []string) { for _, n := range e { - if c, ok := n.(capture); ok && !c.isUnamed() { + if c, ok := n.(capture); ok && !c.isUnnamed() { captures = append(captures, c.Name()) } } @@ -65,8 +80,8 @@ func (c capture) Name() string { return string(c) } -func (c capture) isUnamed() bool { - return string(c) == underscore +func (c capture) isUnnamed() bool { + return len(c) == 1 && c[0] == underscore[0] } type literals []byte diff --git a/pkg/logql/log/pattern/parser.go b/pkg/logql/log/pattern/parser.go index d1bc2515c9cb2..b2a868f7af76c 100644 --- a/pkg/logql/log/pattern/parser.go +++ b/pkg/logql/log/pattern/parser.go @@ -19,8 +19,12 @@ func init() { } func parseExpr(input string) (expr, error) { + return parseExprBytes([]byte(input)) +} + +func parseExprBytes(input []byte) (expr, error) { l := newLexer() - l.setData([]byte(input)) + l.setData(input) e := exprNewParser().Parse(l) if e != 0 || len(l.errs) > 0 { return nil, l.errs[0] diff --git a/pkg/logql/log/pattern/pattern.go b/pkg/logql/log/pattern/pattern.go index b08c91b610af9..83dc6a473a165 100644 --- a/pkg/logql/log/pattern/pattern.go +++ b/pkg/logql/log/pattern/pattern.go @@ -6,23 +6,19 @@ import ( ) var ( - ErrNoCapture = errors.New("at least one capture is required") - ErrInvalidExpr = errors.New("invalid expression") + ErrNoCapture = errors.New("at least one capture is required") + ErrCaptureNotAllowed = errors.New("named captures are not allowed") + ErrInvalidExpr = errors.New("invalid expression") ) -type Matcher interface { - Matches(in []byte) [][]byte - Names() []string -} - -type matcher struct { +type Matcher struct { e expr captures [][]byte names []string } -func New(in string) (Matcher, error) { +func New(in string) (*Matcher, error) { e, err := parseExpr(in) if err != nil { return nil, err @@ -30,16 +26,47 @@ func New(in string) (Matcher, error) { if err := e.validate(); err != nil { return nil, err } - return &matcher{ + return &Matcher{ e: e, captures: make([][]byte, 0, e.captureCount()), names: e.captures(), }, nil } +func ParseLineFilter(in []byte) (*Matcher, error) { + if len(in) == 0 { + return new(Matcher), nil + } + e, err := parseExprBytes(in) + if err != nil { + return nil, err + } + if err = e.validateNoConsecutiveCaptures(); err != nil { + return nil, err + } + if err = e.validateNoNamedCaptures(); err != nil { + return nil, err + } + return &Matcher{e: e}, nil +} + +func ParseLiterals(in string) ([][]byte, error) { + e, err := parseExpr(in) + if err != nil { + return nil, err + } + lit := make([][]byte, 0, len(e)) + for _, n := range e { + if l, ok := n.(literals); ok { + lit = append(lit, l) + } + } + return lit, nil +} + // Matches matches the given line with the provided pattern. // Matches invalidates the previous returned captures array. -func (m *matcher) Matches(in []byte) [][]byte { +func (m *Matcher) Matches(in []byte) [][]byte { if len(in) == 0 { return nil } @@ -62,7 +89,7 @@ func (m *matcher) Matches(in []byte) [][]byte { // from now we have capture - literals - capture ... (literals)? for len(expr) != 0 { if len(expr) == 1 { // we're ending on a capture. - if !(expr[0].(capture)).isUnamed() { + if !(expr[0].(capture)).isUnnamed() { captures = append(captures, in) } return captures @@ -73,13 +100,13 @@ func (m *matcher) Matches(in []byte) [][]byte { i := bytes.Index(in, ls) if i == -1 { // if a capture is missed we return up to the end as the capture. - if !capt.isUnamed() { + if !capt.isUnnamed() { captures = append(captures, in) } return captures } - if capt.isUnamed() { + if capt.isUnnamed() { in = in[len(ls)+i:] continue } @@ -90,6 +117,42 @@ func (m *matcher) Matches(in []byte) [][]byte { return captures } -func (m *matcher) Names() []string { +func (m *Matcher) Names() []string { return m.names } + +func (m *Matcher) Test(in []byte) bool { + if len(in) == 0 || len(m.e) == 0 { + // An empty line can only match an empty pattern. + return len(in) == 0 && len(m.e) == 0 + } + var off int + for i := 0; i < len(m.e); i++ { + lit, ok := m.e[i].(literals) + if !ok { + continue + } + j := bytes.Index(in[off:], lit) + if j == -1 { + return false + } + if i != 0 && j == 0 { + // This means we either have repetitive literals, or an empty + // capture. Either way, the line does not match the pattern. + return false + } + off += j + len(lit) + } + // If we end up on a literal, we only consider the test successful if + // the remaining input is empty. Otherwise, if we end up on a capture, + // the remainder (the captured text) must not be empty. + // + // For example, "foo bar baz" does not match "<_> bar", but it matches + // "<_> baz" and "foo <_>". + // + // Empty captures are not allowed as well: " bar " does not match + // "<_> bar <_>", but matches "<_>bar<_>". + _, reqRem := m.e[len(m.e)-1].(capture) + hasRem := off != len(in) + return reqRem == hasRem +} diff --git a/pkg/logql/log/pattern/pattern_test.go b/pkg/logql/log/pattern/pattern_test.go index da0c6a180527f..0d1c47f0bea29 100644 --- a/pkg/logql/log/pattern/pattern_test.go +++ b/pkg/logql/log/pattern/pattern_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -11,97 +12,144 @@ var fixtures = []struct { expr string in string expected []string + matches bool }{ { "foo bar", "foo buzz bar", []string{"buzz"}, + true, }, { "foo bar", "foo buzz bar", []string{"buzz", ""}, + false, + }, + { + "foo bar", + "foo buzz bar", + []string{"", "buzz"}, + false, }, { " bar", " bar", []string{"", ""}, + false, + }, + { + "bar", + " bar ", + []string{" ", " "}, + true, + }, + { + " bar", + " bar ", + []string{"", " "}, + false, + }, + { + "bar ", + " bar ", + []string{" ", ""}, + false, + }, + { + "", + " bar ", + []string{" bar "}, + true, }, { "?<_>", `/api/plugins/versioncheck?slugIn=snuids-trafficlights-panel,input,gel&grafanaVersion=7.0.0-beta1`, []string{"/api/plugins/versioncheck"}, + true, }, { "?<_>", `/api/plugins/status`, []string{"/api/plugins/status"}, + false, }, { // Common Log Format ` [<_>] " <_>" `, `127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326`, []string{"127.0.0.1", "user-identifier", "frank", "GET", "/apache_pb.gif", "200", "2326"}, + true, }, { // Combined Log Format ` - - [<_>] " <_>" `, `35.191.8.106 - - [19/May/2021:07:21:49 +0000] "GET /api/plugins/versioncheck?slugIn=snuids-trafficlights-panel,input,gel&grafanaVersion=7.0.0-beta1 HTTP/1.1" 200 107 "-" "Go-http-client/2.0" "80.153.74.144, 34.120.177.193" "TLSv1.3" "DE" "DEBW"`, []string{"35.191.8.106", "GET", "/api/plugins/versioncheck?slugIn=snuids-trafficlights-panel,input,gel&grafanaVersion=7.0.0-beta1", "200", "107"}, + false, }, { // MySQL `<_> [] [] [] `, `2020-08-06T14:25:02.835618Z 0 [Note] [MY-012487] [InnoDB] DDL log recovery : begin`, []string{"0", "Note", "MY-012487", "InnoDB"}, + false, }, { // MySQL `<_> [] `, `2021-05-19T07:40:12.215792Z 42761518 [Note] Aborted connection 42761518 to db: 'hosted_grafana' user: 'hosted_grafana' host: '10.36.4.122' (Got an error reading communication packets)`, []string{"42761518", "Note"}, + false, }, { // Kubernetes api-server ` <_> <_> ] `, `W0519 07:46:47.647050 1 clientconn.go:1223] grpc: addrConn.createTransport failed to connect to {https://kubernetes-etcd-1.kubernetes-etcd:2379 0 }. Err :connection error: desc = "transport: Error while dialing dial tcp 10.32.85.85:2379: connect: connection refused". Reconnecting...`, []string{"W0519", "clientconn.go:1223"}, + false, }, { // Cassandra ` []<_> in .<_>`, `INFO [Service Thread] 2021-05-19 07:40:12,130 GCInspector.java:284 - ParNew GC in 248ms. CMS Old Gen: 5043436640 -> 5091062064; Par Eden Space: 671088640 -> 0; Par Survivor Space: 70188280 -> 60139760`, []string{"INFO", "Service Thread", "248ms"}, + true, }, { // Cortex & Loki distributor `<_> msg=" () "`, `level=debug ts=2021-05-19T07:54:26.864644382Z caller=logging.go:66 traceID=7fbb92fd0eb9c65d msg="POST /loki/api/v1/push (204) 1.238734ms"`, []string{"POST", "/loki/api/v1/push", "204", "1.238734ms"}, + true, }, { // Etcd `<_> <_> | : <_> peer <_> tcp :<_>`, `2021-05-19 08:16:50.181436 W | rafthttp: health check for peer fd8275e521cfb532 could not connect: dial tcp 10.32.85.85:2380: connect: connection refused`, []string{"W", "rafthttp", "fd8275e521cfb532", "10.32.85.85"}, + true, }, { // Kafka `<_>] [Log partition=, dir=] `, `[2021-05-19 08:35:28,681] INFO [Log partition=p-636-L-fs-117, dir=/data/kafka-logs] Deleting segment 455976081 (kafka.log.Log)`, []string{"INFO", "p-636-L-fs-117", "/data/kafka-logs"}, + false, }, { // Elastic `<_>][][] [] []`, `[2021-05-19T06:54:06,994][INFO ][o.e.c.m.MetaDataMappingService] [1f605d47-8454-4bfb-a67f-49f318bf837a] [usage-stats-2021.05.19/O2Je9IbmR8CqFyUvNpTttA] update_mapping [report]`, []string{"INFO ", "o.e.c.m.MetaDataMappingService", "1f605d47-8454-4bfb-a67f-49f318bf837a", "usage-stats-2021.05.19/O2Je9IbmR8CqFyUvNpTttA"}, + false, }, { // Envoy `<_> " <_>" <_> "" "" <_> <_> ""`, `[2016-04-15T20:17:00.310Z] "POST /api/v1/locations HTTP/2" 204 - 154 0 226 100 "10.0.35.28" "nsq2http" "cc21d9b0-cf5c-432b-8c7e-98aeb7988cd2" "locations" "tcp://10.0.2.1:80"`, []string{"POST", "/api/v1/locations", "204", "154", "0", "226", "100", "10.0.35.28", "nsq2http", "tcp://10.0.2.1:80"}, + true, }, } @@ -112,12 +160,14 @@ func Test_matcher_Matches(t *testing.T) { t.Parallel() m, err := New(tt.expr) require.NoError(t, err) - actual := m.Matches([]byte(tt.in)) + line := []byte(tt.in) + assert.Equal(t, tt.matches, m.Test(line)) + actual := m.Matches(line) var actualStrings []string for _, a := range actual { actualStrings = append(actualStrings, string(a)) } - require.Equal(t, tt.expected, actualStrings) + assert.Equal(t, tt.expected, actualStrings) }) } } @@ -162,3 +212,40 @@ func Test_Error(t *testing.T) { }) } } + +func Test_ParseLineFilter(t *testing.T) { + for _, tt := range []struct { + name string + err error + }{ + {"<_>", nil}, // Meaningless, but valid: matches everything. + {"", nil}, // Empty pattern matches empty lines. + {"foo <_> bar <_>", nil}, + {" bar <_>", fmt.Errorf("%w: found ''", ErrCaptureNotAllowed)}, + {"", fmt.Errorf("%w: found ''", ErrCaptureNotAllowed)}, + } { + t.Run(tt.name, func(t *testing.T) { + _, err := ParseLineFilter([]byte(tt.name)) + require.Equal(t, tt.err, err) + }) + } +} + +func Test_ParseLiterals(t *testing.T) { + for _, tt := range []struct { + pattern string + lit [][]byte + err error + }{ + {"<_>", [][]byte{}, nil}, + {"", nil, newParseError("syntax error: unexpected $end, expecting IDENTIFIER or LITERAL", 1, 1)}, + {"foo <_> bar <_>", [][]byte{[]byte("foo "), []byte(" bar ")}, nil}, + {"", [][]byte{}, nil}, + } { + t.Run(tt.pattern, func(t *testing.T) { + lit, err := ParseLiterals(tt.pattern) + require.Equal(t, tt.err, err) + require.Equal(t, tt.lit, lit) + }) + } +} diff --git a/pkg/logql/syntax/ast.go b/pkg/logql/syntax/ast.go index e1b796c4fbedd..78b6330809e5d 100644 --- a/pkg/logql/syntax/ast.go +++ b/pkg/logql/syntax/ast.go @@ -355,7 +355,7 @@ func newLineFilterExpr(ty log.LineMatchType, op, match string) *LineFilterExpr { func newOrLineFilter(left, right *LineFilterExpr) *LineFilterExpr { right.Ty = left.Ty - if left.Ty == log.LineMatchEqual || left.Ty == log.LineMatchRegexp { + if left.Ty == log.LineMatchEqual || left.Ty == log.LineMatchRegexp || left.Ty == log.LineMatchPattern { left.Or = right right.IsOrChild = true return left diff --git a/pkg/logql/syntax/ast_test.go b/pkg/logql/syntax/ast_test.go index 95f654d2c647f..ce2dca62f9d43 100644 --- a/pkg/logql/syntax/ast_test.go +++ b/pkg/logql/syntax/ast_test.go @@ -24,7 +24,7 @@ func Test_logSelectorExpr_String(t *testing.T) { {`{foo="bar"}`, false}, {`{foo="bar", bar!="baz"}`, false}, {`{foo="bar", bar!="baz"} != "bip" !~ ".+bop"`, true}, - {`{foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap"`, true}, + {`{foo="bar"} |= "baz" |~ "blip" |> "qux" !> "waldo" != "flip" !~ "flap"`, true}, {`{foo="bar", bar!="baz"} |= ""`, false}, {`{foo="bar", bar!="baz"} |= "" |= ip("::1")`, true}, {`{foo="bar", bar!="baz"} |= "" != ip("127.0.0.1")`, true}, @@ -32,7 +32,10 @@ func Test_logSelectorExpr_String(t *testing.T) { {`{foo="bar", bar!="baz"} |~ ".*"`, false}, {`{foo="bar", bar!="baz"} |= "" |= ""`, false}, {`{foo="bar", bar!="baz"} |~ "" |= "" |~ ".*"`, false}, - {`{foo="bar", bar!="baz"} != "bip" !~ ".+bop" | json`, true}, + {`{foo="bar", bar!="baz"} |> ""`, true}, + {`{foo="bar", bar!="baz"} |> "<_>"`, true}, + {`{foo="bar", bar!="baz"} |> "<_>" !> "<_> <_>"`, true}, + {`{foo="bar", bar!="baz"} != "bip" !~ ".+bop" |> "<_> bop <_>" | json`, true}, {`{foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap" | logfmt`, true}, {`{foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap" | logfmt --strict`, true}, {`{foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap" | logfmt --strict --keep-empty`, true}, @@ -275,6 +278,7 @@ func Test_NilFilterDoesntPanic(t *testing.T) { `{namespace="dev", container_name="cart"} |= "bleep" |= "" |= "bloop"`, `{namespace="dev", container_name="cart"} |= "bleep" |= "" |= "bloop"`, `{namespace="dev", container_name="cart"} |= "bleep" |= "bloop" |= ""`, + `{namespace="dev", container_name="cart"} !> ""`, } { t.Run(tc, func(t *testing.T) { expr, err := ParseLogSelector(tc, true) @@ -355,6 +359,20 @@ func Test_FilterMatcher(t *testing.T) { }, []linecheck{{"foo", true}, {"bar", false}, {"foobar", true}}, }, + { + `{app="foo"} |> "foo <_>"`, + []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, "app", "foo"), + }, + []linecheck{{"foo bar", true}, {"foo", false}}, + }, + { + `{app="foo"} !> "foo <_>"`, + []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, "app", "foo"), + }, + []linecheck{{"foo bar", false}, {"foo", true}}, + }, { `{app="foo"} |~ "foo\\.bar\\.baz"`, []*labels.Matcher{ @@ -425,6 +443,20 @@ func Test_FilterMatcher(t *testing.T) { }, []linecheck{{"foo", false}, {"bar", true}, {"127.0.0.2", true}, {"127.0.0.1", false}}, }, + { + `{app="foo"} |> "foo" or "bar"`, + []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, "app", "foo"), + }, + []linecheck{{"foo", true}, {"bar", true}, {"none", false}}, + }, + { + `{app="foo"} !> "foo" or "bar"`, + []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, "app", "foo"), + }, + []linecheck{{"foo", false}, {"bar", false}, {"none", true}}, + }, } { tt := tt t.Run(tt.q, func(t *testing.T) { @@ -455,6 +487,8 @@ func TestOrLineFilterTypes(t *testing.T) { {log.LineMatchNotEqual}, {log.LineMatchRegexp}, {log.LineMatchNotRegexp}, + {log.LineMatchPattern}, + {log.LineMatchNotPattern}, } { t.Run("right inherits left's type", func(t *testing.T) { left := &LineFilterExpr{LineFilter: LineFilter{Ty: tt.ty, Match: "something"}} @@ -523,6 +557,14 @@ func TestStringer(t *testing.T) { in: `{app="foo"} |~ ip("127.0.0.1") or "foo"`, out: `{app="foo"} |~ ip("127.0.0.1") or "foo"`, }, + { + in: `{app="foo"} |> "foo <_> baz" or "foo <_>"`, + out: `{app="foo"} |> "foo <_> baz" or "foo <_>"`, + }, + { + in: `{app="foo"} |> "foo <_> baz" or "foo <_>" |> "foo <_> baz"`, + out: `{app="foo"} |> "foo <_> baz" or "foo <_>" |> "foo <_> baz"`, + }, { // !(A || B) == !A && !B in: `{app="foo"} != "foo" or "bar"`, out: `{app="foo"} != "foo" != "bar"`, @@ -539,6 +581,10 @@ func TestStringer(t *testing.T) { in: `{app="foo"} !~ ip("127.0.0.1") or "foo"`, out: `{app="foo"} !~ ip("127.0.0.1") !~ "foo"`, }, + { + in: `{app="foo"} !> "<_> foo <_>" or "foo <_>" !> "foo <_> baz"`, + out: `{app="foo"} !> "<_> foo <_>" !> "foo <_>" !> "foo <_> baz"`, + }, } { t.Run(tc.in, func(t *testing.T) { expr, err := ParseExpr(tc.in) @@ -563,19 +609,19 @@ func BenchmarkContainsFilter(b *testing.B) { }{ { "AllMatches", - `{app="foo"} |= "foo" |= "hello" |= "world" |= "bar"`, + `{app="foo"} |= "foo" |= "hello" |= "world" |= "bar" |> "<_> world <_>"`, }, { "OneMatches", - `{app="foo"} |= "foo" |= "not" |= "in" |= "there"`, + `{app="foo"} |= "foo" |= "not" |= "in" |= "there" |> "yet"`, }, { "MixedFiltersTrue", - `{app="foo"} |= "foo" != "not" |~ "hello.*bar" != "there" |= "world"`, + `{app="foo"} |= "foo" != "not" |~ "hello.*bar" != "there" |= "world" |> "<_> more than one <_>"`, }, { "MixedFiltersFalse", - `{app="foo"} |= "baz" != "not" |~ "hello.*bar" != "there" |= "world"`, + `{app="foo"} |= "baz" != "not" |~ "hello.*bar" != "there" |= "world" !> "<_> more than one"`, }, { "GreedyRegex", diff --git a/pkg/logql/syntax/expr.y b/pkg/logql/syntax/expr.y index 043642d526ad1..0386406a87f81 100644 --- a/pkg/logql/syntax/expr.y +++ b/pkg/logql/syntax/expr.y @@ -134,7 +134,7 @@ import ( %token BYTES %token IDENTIFIER STRING NUMBER PARSER_FLAG %token DURATION RANGE -%token MATCHERS LABELS EQ RE NRE OPEN_BRACE CLOSE_BRACE OPEN_BRACKET CLOSE_BRACKET COMMA DOT PIPE_MATCH PIPE_EXACT +%token MATCHERS LABELS EQ RE NRE NPA OPEN_BRACE CLOSE_BRACE OPEN_BRACKET CLOSE_BRACKET COMMA DOT PIPE_MATCH PIPE_EXACT PIPE_PATTERN OPEN_PARENTHESIS CLOSE_PARENTHESIS BY WITHOUT COUNT_OVER_TIME RATE RATE_COUNTER SUM SORT SORT_DESC 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 @@ -241,8 +241,10 @@ labelReplaceExpr: filter: PIPE_MATCH { $$ = log.LineMatchRegexp } | PIPE_EXACT { $$ = log.LineMatchEqual } + | PIPE_PATTERN { $$ = log.LineMatchPattern } | NRE { $$ = log.LineMatchNotRegexp } | NEQ { $$ = log.LineMatchNotEqual } + | NPA { $$ = log.LineMatchNotPattern } ; selector: diff --git a/pkg/logql/syntax/expr.y.go b/pkg/logql/syntax/expr.y.go index 41da7466fbc20..48ba393ad5e2a 100644 --- a/pkg/logql/syntax/expr.y.go +++ b/pkg/logql/syntax/expr.y.go @@ -87,83 +87,85 @@ const LABELS = 57354 const EQ = 57355 const RE = 57356 const NRE = 57357 -const OPEN_BRACE = 57358 -const CLOSE_BRACE = 57359 -const OPEN_BRACKET = 57360 -const CLOSE_BRACKET = 57361 -const COMMA = 57362 -const DOT = 57363 -const PIPE_MATCH = 57364 -const PIPE_EXACT = 57365 -const OPEN_PARENTHESIS = 57366 -const CLOSE_PARENTHESIS = 57367 -const BY = 57368 -const WITHOUT = 57369 -const COUNT_OVER_TIME = 57370 -const RATE = 57371 -const RATE_COUNTER = 57372 -const SUM = 57373 -const SORT = 57374 -const SORT_DESC = 57375 -const AVG = 57376 -const MAX = 57377 -const MIN = 57378 -const COUNT = 57379 -const STDDEV = 57380 -const STDVAR = 57381 -const BOTTOMK = 57382 -const TOPK = 57383 -const BYTES_OVER_TIME = 57384 -const BYTES_RATE = 57385 -const BOOL = 57386 -const JSON = 57387 -const REGEXP = 57388 -const LOGFMT = 57389 -const PIPE = 57390 -const LINE_FMT = 57391 -const LABEL_FMT = 57392 -const UNWRAP = 57393 -const AVG_OVER_TIME = 57394 -const SUM_OVER_TIME = 57395 -const MIN_OVER_TIME = 57396 -const MAX_OVER_TIME = 57397 -const STDVAR_OVER_TIME = 57398 -const STDDEV_OVER_TIME = 57399 -const QUANTILE_OVER_TIME = 57400 -const BYTES_CONV = 57401 -const DURATION_CONV = 57402 -const DURATION_SECONDS_CONV = 57403 -const FIRST_OVER_TIME = 57404 -const LAST_OVER_TIME = 57405 -const ABSENT_OVER_TIME = 57406 -const VECTOR = 57407 -const LABEL_REPLACE = 57408 -const UNPACK = 57409 -const OFFSET = 57410 -const PATTERN = 57411 -const IP = 57412 -const ON = 57413 -const IGNORING = 57414 -const GROUP_LEFT = 57415 -const GROUP_RIGHT = 57416 -const DECOLORIZE = 57417 -const DROP = 57418 -const KEEP = 57419 -const OR = 57420 -const AND = 57421 -const UNLESS = 57422 -const CMP_EQ = 57423 -const NEQ = 57424 -const LT = 57425 -const LTE = 57426 -const GT = 57427 -const GTE = 57428 -const ADD = 57429 -const SUB = 57430 -const MUL = 57431 -const DIV = 57432 -const MOD = 57433 -const POW = 57434 +const NPA = 57358 +const OPEN_BRACE = 57359 +const CLOSE_BRACE = 57360 +const OPEN_BRACKET = 57361 +const CLOSE_BRACKET = 57362 +const COMMA = 57363 +const DOT = 57364 +const PIPE_MATCH = 57365 +const PIPE_EXACT = 57366 +const PIPE_PATTERN = 57367 +const OPEN_PARENTHESIS = 57368 +const CLOSE_PARENTHESIS = 57369 +const BY = 57370 +const WITHOUT = 57371 +const COUNT_OVER_TIME = 57372 +const RATE = 57373 +const RATE_COUNTER = 57374 +const SUM = 57375 +const SORT = 57376 +const SORT_DESC = 57377 +const AVG = 57378 +const MAX = 57379 +const MIN = 57380 +const COUNT = 57381 +const STDDEV = 57382 +const STDVAR = 57383 +const BOTTOMK = 57384 +const TOPK = 57385 +const BYTES_OVER_TIME = 57386 +const BYTES_RATE = 57387 +const BOOL = 57388 +const JSON = 57389 +const REGEXP = 57390 +const LOGFMT = 57391 +const PIPE = 57392 +const LINE_FMT = 57393 +const LABEL_FMT = 57394 +const UNWRAP = 57395 +const AVG_OVER_TIME = 57396 +const SUM_OVER_TIME = 57397 +const MIN_OVER_TIME = 57398 +const MAX_OVER_TIME = 57399 +const STDVAR_OVER_TIME = 57400 +const STDDEV_OVER_TIME = 57401 +const QUANTILE_OVER_TIME = 57402 +const BYTES_CONV = 57403 +const DURATION_CONV = 57404 +const DURATION_SECONDS_CONV = 57405 +const FIRST_OVER_TIME = 57406 +const LAST_OVER_TIME = 57407 +const ABSENT_OVER_TIME = 57408 +const VECTOR = 57409 +const LABEL_REPLACE = 57410 +const UNPACK = 57411 +const OFFSET = 57412 +const PATTERN = 57413 +const IP = 57414 +const ON = 57415 +const IGNORING = 57416 +const GROUP_LEFT = 57417 +const GROUP_RIGHT = 57418 +const DECOLORIZE = 57419 +const DROP = 57420 +const KEEP = 57421 +const OR = 57422 +const AND = 57423 +const UNLESS = 57424 +const CMP_EQ = 57425 +const NEQ = 57426 +const LT = 57427 +const LTE = 57428 +const GT = 57429 +const GTE = 57430 +const ADD = 57431 +const SUB = 57432 +const MUL = 57433 +const DIV = 57434 +const MOD = 57435 +const POW = 57436 var exprToknames = [...]string{ "$end", @@ -181,6 +183,7 @@ var exprToknames = [...]string{ "EQ", "RE", "NRE", + "NPA", "OPEN_BRACE", "CLOSE_BRACE", "OPEN_BRACKET", @@ -189,6 +192,7 @@ var exprToknames = [...]string{ "DOT", "PIPE_MATCH", "PIPE_EXACT", + "PIPE_PATTERN", "OPEN_PARENTHESIS", "CLOSE_PARENTHESIS", "BY", @@ -273,121 +277,122 @@ var exprExca = [...]int{ const exprPrivate = 57344 -const exprLast = 592 +const exprLast = 608 var exprAct = [...]int{ - 287, 226, 82, 4, 212, 64, 180, 124, 202, 187, - 73, 198, 195, 63, 235, 5, 150, 185, 75, 2, - 56, 78, 48, 49, 50, 57, 58, 61, 62, 59, + 289, 228, 84, 4, 214, 64, 182, 126, 204, 189, + 75, 200, 197, 63, 237, 5, 152, 187, 77, 2, + 56, 80, 48, 49, 50, 57, 58, 61, 62, 59, 60, 51, 52, 53, 54, 55, 56, 49, 50, 57, 58, 61, 62, 59, 60, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 59, 60, 51, 52, 53, - 54, 55, 56, 51, 52, 53, 54, 55, 56, 107, - 146, 148, 149, 113, 53, 54, 55, 56, 205, 148, - 149, 281, 215, 137, 290, 154, 164, 165, 213, 293, - 138, 159, 67, 293, 71, 214, 152, 295, 71, 162, - 163, 69, 70, 292, 345, 69, 70, 364, 161, 364, - 92, 384, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 71, 228, 379, 290, - 337, 228, 304, 69, 70, 192, 134, 354, 189, 147, - 200, 204, 83, 84, 372, 367, 211, 206, 209, 210, - 207, 208, 140, 217, 140, 128, 134, 291, 108, 228, - 233, 72, 371, 337, 139, 72, 227, 291, 292, 229, - 230, 182, 344, 238, 222, 128, 120, 121, 119, 225, - 129, 131, 295, 81, 71, 83, 84, 369, 246, 247, - 248, 69, 70, 72, 296, 292, 222, 329, 122, 225, - 123, 292, 250, 357, 71, 292, 130, 132, 133, 347, - 304, 69, 70, 304, 71, 353, 71, 228, 352, 299, - 283, 69, 70, 69, 70, 134, 285, 288, 328, 294, - 181, 297, 237, 107, 300, 113, 301, 228, 71, 289, - 152, 286, 237, 298, 128, 69, 70, 66, 304, 228, - 222, 72, 314, 351, 302, 134, 237, 308, 310, 313, - 315, 316, 312, 241, 200, 204, 323, 318, 322, 290, - 182, 72, 231, 223, 128, 253, 311, 134, 134, 304, - 338, 72, 237, 72, 306, 304, 326, 142, 141, 330, - 305, 332, 334, 182, 336, 107, 128, 128, 361, 335, - 346, 331, 309, 237, 107, 72, 264, 348, 219, 265, - 237, 263, 134, 325, 324, 282, 13, 120, 121, 119, - 245, 129, 131, 239, 153, 244, 382, 182, 183, 181, - 236, 128, 358, 359, 340, 341, 342, 107, 360, 122, - 243, 123, 242, 216, 362, 363, 158, 130, 132, 133, - 368, 183, 181, 151, 157, 260, 156, 218, 261, 16, - 259, 88, 13, 87, 374, 80, 375, 376, 13, 378, - 153, 255, 262, 350, 251, 303, 6, 257, 380, 256, - 21, 22, 23, 36, 45, 46, 37, 39, 40, 38, - 41, 42, 43, 44, 24, 25, 254, 240, 232, 224, - 252, 79, 234, 377, 26, 27, 28, 29, 30, 31, - 32, 13, 366, 77, 33, 34, 35, 47, 19, 6, - 365, 258, 343, 21, 22, 23, 36, 45, 46, 37, - 39, 40, 38, 41, 42, 43, 44, 24, 25, 17, - 18, 279, 333, 160, 280, 155, 278, 26, 27, 28, - 29, 30, 31, 32, 13, 89, 86, 33, 34, 35, - 47, 19, 6, 320, 321, 383, 21, 22, 23, 36, - 45, 46, 37, 39, 40, 38, 41, 42, 43, 44, - 24, 25, 17, 18, 276, 85, 373, 277, 381, 275, - 26, 27, 28, 29, 30, 31, 32, 370, 356, 355, - 33, 34, 35, 47, 19, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 144, - 188, 125, 327, 249, 273, 17, 18, 274, 270, 272, - 349, 271, 317, 269, 143, 267, 3, 145, 268, 188, - 266, 319, 186, 74, 196, 126, 307, 284, 221, 220, - 219, 218, 193, 191, 190, 203, 199, 188, 79, 196, - 111, 112, 194, 116, 201, 118, 197, 117, 115, 114, - 184, 65, 135, 127, 136, 109, 110, 91, 90, 11, - 10, 9, 20, 12, 15, 8, 339, 14, 7, 76, - 68, 1, + 54, 55, 56, 51, 52, 53, 54, 55, 56, 109, + 148, 150, 151, 115, 53, 54, 55, 56, 207, 150, + 151, 283, 217, 139, 166, 167, 292, 156, 215, 295, + 216, 72, 74, 161, 72, 74, 164, 165, 154, 69, + 70, 71, 69, 70, 71, 297, 347, 140, 67, 294, + 163, 366, 136, 366, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 184, 230, + 339, 292, 94, 130, 255, 136, 339, 194, 85, 86, + 191, 149, 202, 206, 293, 136, 386, 369, 213, 208, + 211, 212, 209, 210, 142, 219, 130, 363, 306, 141, + 73, 184, 235, 73, 356, 381, 130, 239, 229, 374, + 294, 231, 232, 142, 110, 240, 294, 122, 123, 121, + 227, 131, 133, 297, 294, 72, 74, 185, 183, 316, + 248, 249, 250, 69, 70, 71, 373, 298, 371, 124, + 295, 125, 136, 359, 252, 72, 74, 132, 134, 135, + 293, 349, 239, 69, 70, 71, 72, 74, 184, 224, + 230, 183, 285, 130, 69, 70, 71, 346, 287, 290, + 330, 296, 136, 299, 314, 109, 302, 115, 303, 304, + 230, 291, 154, 288, 331, 300, 306, 72, 74, 243, + 294, 230, 355, 130, 73, 69, 70, 71, 306, 310, + 312, 315, 317, 318, 354, 233, 202, 206, 325, 320, + 324, 292, 340, 83, 73, 85, 86, 185, 183, 136, + 144, 266, 230, 221, 267, 73, 265, 262, 328, 220, + 263, 332, 261, 334, 336, 184, 338, 109, 239, 306, + 130, 337, 348, 333, 239, 353, 109, 224, 227, 350, + 327, 306, 306, 72, 74, 239, 73, 308, 307, 239, + 313, 69, 70, 71, 13, 224, 311, 143, 342, 343, + 344, 379, 301, 155, 360, 361, 384, 241, 326, 109, + 362, 238, 284, 153, 247, 246, 364, 365, 230, 264, + 225, 245, 370, 13, 244, 260, 218, 160, 159, 158, + 16, 90, 155, 89, 72, 74, 376, 82, 377, 378, + 13, 380, 69, 70, 71, 352, 253, 305, 259, 6, + 382, 258, 73, 21, 22, 23, 36, 45, 46, 37, + 39, 40, 38, 41, 42, 43, 44, 24, 25, 66, + 256, 242, 234, 226, 257, 254, 368, 26, 27, 28, + 29, 30, 31, 32, 81, 146, 367, 33, 34, 35, + 47, 19, 236, 281, 345, 335, 282, 79, 280, 322, + 323, 145, 13, 73, 147, 278, 162, 88, 279, 87, + 277, 6, 17, 18, 385, 21, 22, 23, 36, 45, + 46, 37, 39, 40, 38, 41, 42, 43, 44, 24, + 25, 275, 272, 127, 276, 273, 274, 271, 383, 26, + 27, 28, 29, 30, 31, 32, 372, 358, 357, 33, + 34, 35, 47, 19, 157, 269, 329, 375, 270, 190, + 268, 3, 251, 190, 13, 319, 188, 321, 76, 309, + 198, 128, 286, 6, 17, 18, 136, 21, 22, 23, + 36, 45, 46, 37, 39, 40, 38, 41, 42, 43, + 44, 24, 25, 223, 222, 221, 220, 130, 195, 193, + 192, 26, 27, 28, 29, 30, 31, 32, 91, 351, + 205, 33, 34, 35, 47, 19, 201, 190, 122, 123, + 121, 81, 131, 133, 198, 113, 114, 196, 118, 203, + 120, 199, 119, 117, 116, 186, 17, 18, 65, 137, + 124, 129, 125, 138, 111, 112, 93, 92, 132, 134, + 135, 11, 10, 9, 20, 12, 15, 8, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 341, 14, 7, 78, 68, 1, } var exprPact = [...]int{ - 352, -1000, -56, -1000, -1000, 199, 352, -1000, -1000, -1000, - -1000, -1000, -1000, 396, 341, 159, -1000, 478, 449, 339, - 337, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 353, -1000, -58, -1000, -1000, 349, 353, -1000, -1000, -1000, + -1000, -1000, -1000, 409, 341, 247, -1000, 432, 430, 337, + 335, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 199, -1000, 223, 272, 5, 84, -1000, - -1000, -1000, -1000, 263, 262, -56, 517, -1000, -1000, 57, - 346, 438, 332, 330, 322, -1000, -1000, 352, 436, 352, - 28, 13, -1000, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, -1000, -1000, -1000, - -1000, -1000, -1000, 273, -1000, -1000, -1000, -1000, -1000, 534, - 552, 548, -1000, 547, -1000, -1000, -1000, -1000, 220, 546, - -1000, 554, 551, 550, 65, -1000, -1000, 82, 4, 319, - -1000, -1000, -1000, -1000, -1000, 553, 545, 544, 543, 542, - 248, 379, 189, 300, 247, 378, 395, 305, 298, 377, - 238, -42, 318, 316, 301, 296, -30, -30, -15, -15, - -72, -72, -72, -72, -24, -24, -24, -24, -24, -24, - 273, 220, 220, 220, 515, 354, -1000, -1000, 387, 354, - -1000, -1000, 250, -1000, 376, -1000, 358, 359, -1000, 57, - -1000, 357, -1000, 57, -1000, 351, 302, 531, 524, 520, - 480, 437, -1000, 3, 291, 82, 541, -1000, -1000, -1000, - -1000, -1000, -1000, 116, 300, 201, 157, 83, 131, 169, - 194, 116, 352, 229, 355, 265, -1000, -1000, 259, -1000, - 540, -1000, 277, 251, 237, 227, 307, 273, 151, -1000, - 354, 552, 526, -1000, 539, 458, 551, 550, 290, -1000, - -1000, -1000, 289, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 349, -1000, 76, 501, 3, 101, -1000, + -1000, -1000, -1000, -1000, -1000, 300, 253, -58, 413, -1000, + -1000, 57, 336, 477, 333, 332, 331, -1000, -1000, 353, + 429, 353, 23, 9, -1000, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, -1000, + -1000, -1000, -1000, -1000, -1000, 197, -1000, -1000, -1000, -1000, + -1000, 488, 542, 524, -1000, 523, -1000, -1000, -1000, -1000, + 227, 522, -1000, 549, 541, 535, 65, -1000, -1000, 82, + 2, 330, -1000, -1000, -1000, -1000, -1000, 546, 520, 519, + 518, 517, 323, 382, 298, 307, 238, 381, 415, 314, + 310, 380, 222, -44, 328, 325, 319, 318, -32, -32, + -17, -17, -74, -74, -74, -74, -26, -26, -26, -26, + -26, -26, 197, 227, 227, 227, 484, 355, -1000, -1000, + 392, 355, -1000, -1000, 107, -1000, 379, -1000, 391, 360, + -1000, 57, -1000, 357, -1000, 57, -1000, 283, 277, 481, + 458, 457, 431, 419, -1000, 1, 316, 82, 496, -1000, + -1000, -1000, -1000, -1000, -1000, 110, 307, 201, 134, 190, + 130, 170, 305, 110, 353, 212, 356, 291, -1000, -1000, + 290, -1000, 493, -1000, 299, 293, 207, 162, 274, 197, + 140, -1000, 355, 542, 489, -1000, 495, 424, 541, 535, + 312, -1000, -1000, -1000, 284, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 82, 516, -1000, 203, -1000, 172, 111, 55, 111, - 433, 16, 220, 16, 153, 275, 412, 147, 79, -1000, - -1000, 184, -1000, 352, 525, -1000, -1000, 353, 228, -1000, - 193, -1000, -1000, 190, -1000, 112, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 493, 492, -1000, 178, -1000, 116, - 55, 111, 55, -1000, -1000, 273, -1000, 16, -1000, 274, - -1000, -1000, -1000, 61, 410, 402, 120, 116, 162, -1000, - 491, -1000, -1000, -1000, -1000, 137, 119, -1000, -1000, 55, - -1000, 481, 59, 55, 46, 16, 16, 393, -1000, -1000, - 349, -1000, -1000, 103, 55, -1000, -1000, 16, 482, -1000, - -1000, 306, 459, 86, -1000, + -1000, -1000, -1000, 82, 480, -1000, 203, -1000, 217, 232, + 59, 232, 416, 16, 227, 16, 126, 267, 414, 200, + 79, -1000, -1000, 184, -1000, 353, 534, -1000, -1000, 354, + 278, -1000, 237, -1000, -1000, 225, -1000, 137, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 472, 471, -1000, 176, + -1000, 110, 59, 232, 59, -1000, -1000, 197, -1000, 16, + -1000, 131, -1000, -1000, -1000, 61, 406, 396, 120, 110, + 171, -1000, 470, -1000, -1000, -1000, -1000, 169, 142, -1000, + -1000, 59, -1000, 482, 63, 59, 52, 16, 16, 321, + -1000, -1000, 350, -1000, -1000, 138, 59, -1000, -1000, 16, + 462, -1000, -1000, 315, 438, 119, -1000, } var exprPgo = [...]int{ - 0, 591, 18, 590, 2, 14, 536, 3, 16, 7, - 589, 588, 587, 586, 15, 585, 584, 583, 582, 95, - 581, 580, 579, 455, 578, 577, 576, 575, 13, 5, - 574, 573, 572, 6, 571, 92, 4, 570, 569, 568, - 567, 566, 11, 565, 564, 8, 563, 12, 562, 9, - 17, 561, 560, 1, 545, 521, 0, + 0, 607, 18, 606, 2, 14, 491, 3, 16, 7, + 605, 604, 603, 602, 15, 587, 586, 585, 584, 90, + 583, 582, 581, 538, 577, 576, 575, 574, 13, 5, + 573, 571, 569, 6, 568, 108, 4, 565, 564, 563, + 562, 561, 11, 560, 559, 8, 558, 12, 557, 9, + 17, 556, 555, 1, 501, 463, 0, } var exprR1 = [...]int{ @@ -397,23 +402,23 @@ var exprR1 = [...]int{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 53, 53, 53, 13, 13, 13, 11, 11, 11, 11, 15, 15, 15, 15, 15, 15, 22, 3, 3, 3, - 3, 14, 14, 14, 10, 10, 9, 9, 9, 9, - 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 19, 36, 36, 36, 35, 35, 35, - 34, 34, 34, 37, 37, 27, 27, 26, 26, 26, - 26, 52, 51, 51, 38, 39, 47, 47, 48, 48, - 48, 46, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 49, 49, 50, 50, 55, 55, 54, 54, 32, - 32, 32, 32, 32, 32, 32, 30, 30, 30, 30, - 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, - 42, 42, 41, 41, 40, 45, 45, 44, 44, 43, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 24, 24, 25, 25, 25, - 25, 23, 23, 23, 23, 23, 23, 23, 23, 21, - 21, 21, 17, 18, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, + 3, 3, 3, 14, 14, 14, 10, 10, 9, 9, + 9, 9, 28, 28, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 19, 36, 36, 36, 35, + 35, 35, 34, 34, 34, 37, 37, 27, 27, 26, + 26, 26, 26, 52, 51, 51, 38, 39, 47, 47, + 48, 48, 48, 46, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 49, 49, 50, 50, 55, 55, 54, + 54, 32, 32, 32, 32, 32, 32, 32, 30, 30, + 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, + 31, 31, 42, 42, 41, 41, 40, 45, 45, 44, + 44, 43, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 24, 24, 25, + 25, 25, 25, 23, 23, 23, 23, 23, 23, 23, + 23, 21, 21, 21, 17, 18, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 56, 5, 5, 4, 4, 4, 4, + 12, 12, 56, 5, 5, 4, 4, 4, 4, } var exprR2 = [...]int{ @@ -423,107 +428,107 @@ var exprR2 = [...]int{ 4, 5, 6, 7, 3, 4, 4, 5, 3, 2, 3, 6, 3, 1, 1, 1, 4, 6, 5, 7, 4, 5, 5, 6, 7, 7, 12, 1, 1, 1, - 1, 3, 3, 2, 1, 3, 3, 3, 3, 3, - 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 1, 4, 3, 2, 5, 4, - 1, 3, 2, 1, 2, 1, 2, 1, 2, 1, - 2, 2, 3, 2, 2, 1, 3, 3, 1, 3, - 3, 2, 1, 1, 1, 1, 3, 2, 3, 3, - 3, 3, 1, 1, 3, 6, 6, 1, 1, 3, + 1, 1, 1, 3, 3, 2, 1, 3, 3, 3, + 3, 3, 1, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 4, 3, 2, + 5, 4, 1, 3, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 2, 3, 2, 2, 1, 3, 3, + 1, 3, 3, 2, 1, 1, 1, 1, 3, 2, + 3, 3, 3, 3, 1, 1, 3, 6, 6, 1, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 1, 1, 1, 3, 2, 1, 1, 1, 3, 2, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 1, 5, 4, 5, - 4, 1, 1, 2, 4, 5, 2, 4, 5, 1, - 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 1, 1, 1, 3, 2, 1, 1, 1, + 3, 2, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 1, 5, + 4, 5, 4, 1, 1, 2, 4, 5, 2, 4, + 5, 1, 2, 2, 4, 1, 1, 1, 1, 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, 2, 1, 3, 4, 4, 3, 3, } var exprChk = [...]int{ - -1000, -1, -2, -6, -7, -14, 24, -11, -15, -20, - -21, -22, -17, 16, -12, -16, 7, 87, 88, 66, - -18, 28, 29, 30, 42, 43, 52, 53, 54, 55, - 56, 57, 58, 62, 63, 64, 31, 34, 37, 35, - 36, 38, 39, 40, 41, 32, 33, 65, 78, 79, - 80, 87, 88, 89, 90, 91, 92, 81, 82, 85, - 86, 83, 84, -28, -29, -34, 48, -35, -3, 22, - 23, 15, 82, -7, -6, -2, -10, 17, -9, 5, - 24, 24, -4, 26, 27, 7, 7, 24, 24, -23, - -24, -25, 44, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, -23, -23, -23, -23, -29, -35, -27, - -26, -52, -51, -33, -38, -39, -46, -40, -43, 47, - 45, 46, 67, 69, -9, -55, -54, -31, 24, 49, - 75, 50, 76, 77, 5, -32, -30, 78, 6, -19, - 70, 25, 25, 17, 2, 20, 13, 82, 14, 15, - -8, 7, -14, 24, -7, 7, 24, 24, 24, -7, - 7, -2, 71, 72, 73, 74, -2, -2, -2, -2, + -1000, -1, -2, -6, -7, -14, 26, -11, -15, -20, + -21, -22, -17, 17, -12, -16, 7, 89, 90, 68, + -18, 30, 31, 32, 44, 45, 54, 55, 56, 57, + 58, 59, 60, 64, 65, 66, 33, 36, 39, 37, + 38, 40, 41, 42, 43, 34, 35, 67, 80, 81, + 82, 89, 90, 91, 92, 93, 94, 83, 84, 87, + 88, 85, 86, -28, -29, -34, 50, -35, -3, 23, + 24, 25, 15, 84, 16, -7, -6, -2, -10, 18, + -9, 5, 26, 26, -4, 28, 29, 7, 7, 26, + 26, -23, -24, -25, 46, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23, -23, -23, -29, + -35, -27, -26, -52, -51, -33, -38, -39, -46, -40, + -43, 49, 47, 48, 69, 71, -9, -55, -54, -31, + 26, 51, 77, 52, 78, 79, 5, -32, -30, 80, + 6, -19, 72, 27, 27, 18, 2, 21, 13, 84, + 14, 15, -8, 7, -14, 26, -7, 7, 26, 26, + 26, -7, 7, -2, 73, 74, 75, 76, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -33, 79, 20, 78, -37, -50, 8, -49, 5, -50, - 6, 6, -33, 6, -48, -47, 5, -41, -42, 5, - -9, -44, -45, 5, -9, 13, 82, 85, 86, 83, - 84, 81, -36, 6, -19, 78, 24, -9, 6, 6, - 6, 6, 2, 25, 20, 10, -53, -28, 48, -14, - -8, 25, 20, -7, 7, -5, 25, 5, -5, 25, - 20, 25, 24, 24, 24, 24, -33, -33, -33, 8, - -50, 20, 13, 25, 20, 13, 20, 20, 70, 9, - 4, 7, 70, 9, 4, 7, 9, 4, 7, 9, - 4, 7, 9, 4, 7, 9, 4, 7, 9, 4, - 7, 78, 24, -36, 6, -4, -8, -56, -53, -28, - 68, 10, 48, 10, -53, 51, 25, -53, -28, 25, - -4, -7, 25, 20, 20, 25, 25, 6, -5, 25, - -5, 25, 25, -5, 25, -5, -49, 6, -47, 2, - 5, 6, -42, -45, 24, 24, -36, 6, 25, 25, - -53, -28, -53, 9, -56, -33, -56, 10, 5, -13, - 59, 60, 61, 10, 25, 25, -53, 25, -7, 5, - 20, 25, 25, 25, 25, 6, 6, 25, -4, -53, - -56, 24, -56, -53, 48, 10, 10, 25, -4, 25, - 6, 25, 25, 5, -53, -56, -56, 10, 20, 25, - -56, 6, 20, 6, 25, + -2, -2, -33, 81, 21, 80, -37, -50, 8, -49, + 5, -50, 6, 6, -33, 6, -48, -47, 5, -41, + -42, 5, -9, -44, -45, 5, -9, 13, 84, 87, + 88, 85, 86, 83, -36, 6, -19, 80, 26, -9, + 6, 6, 6, 6, 2, 27, 21, 10, -53, -28, + 50, -14, -8, 27, 21, -7, 7, -5, 27, 5, + -5, 27, 21, 27, 26, 26, 26, 26, -33, -33, + -33, 8, -50, 21, 13, 27, 21, 13, 21, 21, + 72, 9, 4, 7, 72, 9, 4, 7, 9, 4, + 7, 9, 4, 7, 9, 4, 7, 9, 4, 7, + 9, 4, 7, 80, 26, -36, 6, -4, -8, -56, + -53, -28, 70, 10, 50, 10, -53, 53, 27, -53, + -28, 27, -4, -7, 27, 21, 21, 27, 27, 6, + -5, 27, -5, 27, 27, -5, 27, -5, -49, 6, + -47, 2, 5, 6, -42, -45, 26, 26, -36, 6, + 27, 27, -53, -28, -53, 9, -56, -33, -56, 10, + 5, -13, 61, 62, 63, 10, 27, 27, -53, 27, + -7, 5, 21, 27, 27, 27, 27, 6, 6, 27, + -4, -53, -56, 26, -56, -53, 50, 10, 10, 27, + -4, 27, 6, 27, 27, 5, -53, -56, -56, 10, + 21, 27, -56, 6, 21, 6, 27, } var exprDef = [...]int{ 0, -2, 1, 2, 3, 11, 0, 4, 5, 6, - 7, 8, 9, 0, 0, 0, 189, 0, 0, 0, - 0, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 193, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, - 175, 175, 175, 12, 70, 72, 0, 90, 0, 57, - 58, 59, 60, 3, 2, 0, 0, 63, 64, 0, - 0, 0, 0, 0, 0, 190, 191, 0, 0, 0, - 181, 182, 176, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 71, 92, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 95, - 97, 0, 99, 0, 112, 113, 114, 115, 0, 0, - 105, 0, 0, 0, 0, 127, 128, 0, 87, 0, - 83, 10, 13, 61, 62, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 189, 0, 0, 0, 3, - 0, 160, 0, 0, 183, 186, 161, 162, 163, 164, + 7, 8, 9, 0, 0, 0, 191, 0, 0, 0, + 0, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 195, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 12, 72, 74, 0, 92, 0, 57, + 58, 59, 60, 61, 62, 3, 2, 0, 0, 65, + 66, 0, 0, 0, 0, 0, 0, 192, 193, 0, + 0, 0, 183, 184, 178, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, + 94, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 97, 99, 0, 101, 0, 114, 115, 116, 117, + 0, 0, 107, 0, 0, 0, 0, 129, 130, 0, + 89, 0, 85, 10, 13, 63, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 191, 0, 0, + 0, 3, 0, 162, 0, 0, 185, 188, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 117, 0, 0, 0, 96, 103, 93, 123, 122, 101, - 98, 100, 0, 104, 111, 108, 0, 154, 152, 150, - 151, 159, 157, 155, 156, 0, 0, 0, 0, 0, - 0, 0, 91, 84, 0, 0, 0, 65, 66, 67, - 68, 69, 39, 46, 0, 14, 0, 0, 0, 0, - 0, 50, 0, 3, 189, 0, 225, 221, 0, 226, - 0, 192, 0, 0, 0, 0, 118, 119, 120, 94, - 102, 0, 0, 116, 0, 0, 0, 0, 0, 134, - 141, 148, 0, 133, 140, 147, 129, 136, 143, 130, - 137, 144, 131, 138, 145, 132, 139, 146, 135, 142, - 149, 0, 0, 89, 0, 48, 0, 15, 18, 34, - 0, 22, 0, 26, 0, 0, 0, 0, 0, 38, - 52, 3, 51, 0, 0, 223, 224, 0, 0, 178, - 0, 180, 184, 0, 187, 0, 124, 121, 109, 110, - 106, 107, 153, 158, 0, 0, 86, 0, 88, 47, - 19, 35, 36, 220, 23, 42, 27, 30, 40, 0, - 43, 44, 45, 16, 0, 0, 0, 53, 3, 222, - 0, 177, 179, 185, 188, 0, 0, 85, 49, 37, - 31, 0, 17, 20, 0, 24, 28, 0, 54, 55, - 0, 125, 126, 0, 21, 25, 29, 32, 0, 41, - 33, 0, 0, 0, 56, + 175, 176, 119, 0, 0, 0, 98, 105, 95, 125, + 124, 103, 100, 102, 0, 106, 113, 110, 0, 156, + 154, 152, 153, 161, 159, 157, 158, 0, 0, 0, + 0, 0, 0, 0, 93, 86, 0, 0, 0, 67, + 68, 69, 70, 71, 39, 46, 0, 14, 0, 0, + 0, 0, 0, 50, 0, 3, 191, 0, 227, 223, + 0, 228, 0, 194, 0, 0, 0, 0, 120, 121, + 122, 96, 104, 0, 0, 118, 0, 0, 0, 0, + 0, 136, 143, 150, 0, 135, 142, 149, 131, 138, + 145, 132, 139, 146, 133, 140, 147, 134, 141, 148, + 137, 144, 151, 0, 0, 91, 0, 48, 0, 15, + 18, 34, 0, 22, 0, 26, 0, 0, 0, 0, + 0, 38, 52, 3, 51, 0, 0, 225, 226, 0, + 0, 180, 0, 182, 186, 0, 189, 0, 126, 123, + 111, 112, 108, 109, 155, 160, 0, 0, 88, 0, + 90, 47, 19, 35, 36, 222, 23, 42, 27, 30, + 40, 0, 43, 44, 45, 16, 0, 0, 0, 53, + 3, 224, 0, 179, 181, 187, 190, 0, 0, 87, + 49, 37, 31, 0, 17, 20, 0, 24, 28, 0, + 54, 55, 0, 127, 128, 0, 21, 25, 29, 32, + 0, 41, 33, 0, 0, 0, 56, } var exprTok1 = [...]int{ @@ -540,7 +545,7 @@ var exprTok2 = [...]int{ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, + 92, 93, 94, } var exprTok3 = [...]int{ 0, @@ -1169,845 +1174,855 @@ exprdefault: case 59: exprDollar = exprS[exprpt-1 : exprpt+1] { - exprVAL.Filter = log.LineMatchNotRegexp + exprVAL.Filter = log.LineMatchPattern } case 60: exprDollar = exprS[exprpt-1 : exprpt+1] { - exprVAL.Filter = log.LineMatchNotEqual + exprVAL.Filter = log.LineMatchNotRegexp } case 61: + exprDollar = exprS[exprpt-1 : exprpt+1] + { + exprVAL.Filter = log.LineMatchNotEqual + } + case 62: + exprDollar = exprS[exprpt-1 : exprpt+1] + { + exprVAL.Filter = log.LineMatchNotPattern + } + case 63: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Selector = exprDollar[2].Matchers } - case 62: + case 64: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Selector = exprDollar[2].Matchers } - case 63: + case 65: exprDollar = exprS[exprpt-2 : exprpt+1] { } - case 64: + case 66: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.Matchers = []*labels.Matcher{exprDollar[1].Matcher} } - case 65: + case 67: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Matchers = append(exprDollar[1].Matchers, exprDollar[3].Matcher) } - case 66: + case 68: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Matcher = mustNewMatcher(labels.MatchEqual, exprDollar[1].str, exprDollar[3].str) } - case 67: + case 69: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Matcher = mustNewMatcher(labels.MatchNotEqual, exprDollar[1].str, exprDollar[3].str) } - case 68: + case 70: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Matcher = mustNewMatcher(labels.MatchRegexp, exprDollar[1].str, exprDollar[3].str) } - case 69: + case 71: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Matcher = mustNewMatcher(labels.MatchNotRegexp, exprDollar[1].str, exprDollar[3].str) } - case 70: + case 72: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.PipelineExpr = MultiStageExpr{exprDollar[1].PipelineStage} } - case 71: + case 73: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineExpr = append(exprDollar[1].PipelineExpr, exprDollar[2].PipelineStage) } - case 72: + case 74: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.PipelineStage = exprDollar[1].LineFilters } - case 73: + case 75: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].LogfmtParser } - case 74: + case 76: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].LabelParser } - case 75: + case 77: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].JSONExpressionParser } - case 76: + case 78: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].LogfmtExpressionParser } - case 77: + case 79: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = &LabelFilterExpr{LabelFilterer: exprDollar[2].LabelFilter} } - case 78: + case 80: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].LineFormatExpr } - case 79: + case 81: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].DecolorizeExpr } - case 80: + case 82: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].LabelFormatExpr } - case 81: + case 83: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].DropLabelsExpr } - case 82: + case 84: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.PipelineStage = exprDollar[2].KeepLabelsExpr } - case 83: + case 85: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.FilterOp = OpFilterIP } - case 84: + case 86: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.OrFilter = newLineFilterExpr(log.LineMatchEqual, "", exprDollar[1].str) } - case 85: + case 87: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.OrFilter = newLineFilterExpr(log.LineMatchEqual, exprDollar[1].FilterOp, exprDollar[3].str) } - case 86: + case 88: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.OrFilter = newOrLineFilter(newLineFilterExpr(log.LineMatchEqual, "", exprDollar[1].str), exprDollar[3].OrFilter) } - case 87: + case 89: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LineFilter = newLineFilterExpr(exprDollar[1].Filter, "", exprDollar[2].str) } - case 88: + case 90: exprDollar = exprS[exprpt-5 : exprpt+1] { exprVAL.LineFilter = newLineFilterExpr(exprDollar[1].Filter, exprDollar[2].FilterOp, exprDollar[4].str) } - case 89: + case 91: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.LineFilter = newOrLineFilter(newLineFilterExpr(exprDollar[1].Filter, "", exprDollar[2].str), exprDollar[4].OrFilter) } - case 90: + case 92: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LineFilters = exprDollar[1].LineFilter } - case 91: + case 93: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LineFilters = newOrLineFilter(exprDollar[1].LineFilter, exprDollar[3].OrFilter) } - case 92: + case 94: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LineFilters = newNestedLineFilterExpr(exprDollar[1].LineFilters, exprDollar[2].LineFilter) } - case 93: + case 95: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.ParserFlags = []string{exprDollar[1].str} } - case 94: + case 96: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.ParserFlags = append(exprDollar[1].ParserFlags, exprDollar[2].str) } - case 95: + case 97: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LogfmtParser = newLogfmtParserExpr(nil) } - case 96: + case 98: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LogfmtParser = newLogfmtParserExpr(exprDollar[2].ParserFlags) } - case 97: + case 99: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelParser = newLabelParserExpr(OpParserTypeJSON, "") } - case 98: + case 100: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LabelParser = newLabelParserExpr(OpParserTypeRegexp, exprDollar[2].str) } - case 99: + case 101: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelParser = newLabelParserExpr(OpParserTypeUnpack, "") } - case 100: + case 102: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LabelParser = newLabelParserExpr(OpParserTypePattern, exprDollar[2].str) } - case 101: + case 103: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.JSONExpressionParser = newJSONExpressionParser(exprDollar[2].LabelExtractionExpressionList) } - case 102: + case 104: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LogfmtExpressionParser = newLogfmtExpressionParser(exprDollar[3].LabelExtractionExpressionList, exprDollar[2].ParserFlags) } - case 103: + case 105: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LogfmtExpressionParser = newLogfmtExpressionParser(exprDollar[2].LabelExtractionExpressionList, nil) } - case 104: + case 106: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LineFormatExpr = newLineFmtExpr(exprDollar[2].str) } - case 105: + case 107: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.DecolorizeExpr = newDecolorizeExpr() } - case 106: + case 108: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFormat = log.NewRenameLabelFmt(exprDollar[1].str, exprDollar[3].str) } - case 107: + case 109: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFormat = log.NewTemplateLabelFmt(exprDollar[1].str, exprDollar[3].str) } - case 108: + case 110: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelsFormat = []log.LabelFmt{exprDollar[1].LabelFormat} } - case 109: + case 111: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelsFormat = append(exprDollar[1].LabelsFormat, exprDollar[3].LabelFormat) } - case 111: + case 113: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LabelFormatExpr = newLabelFmtExpr(exprDollar[2].LabelsFormat) } - case 112: + case 114: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelFilter = log.NewStringLabelFilter(exprDollar[1].Matcher) } - case 113: + case 115: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelFilter = exprDollar[1].IPLabelFilter } - case 114: + case 116: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelFilter = exprDollar[1].UnitFilter } - case 115: + case 117: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelFilter = exprDollar[1].NumberFilter } - case 116: + case 118: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFilter = exprDollar[2].LabelFilter } - case 117: + case 119: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LabelFilter = log.NewAndLabelFilter(exprDollar[1].LabelFilter, exprDollar[2].LabelFilter) } - case 118: + case 120: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFilter = log.NewAndLabelFilter(exprDollar[1].LabelFilter, exprDollar[3].LabelFilter) } - case 119: + case 121: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFilter = log.NewAndLabelFilter(exprDollar[1].LabelFilter, exprDollar[3].LabelFilter) } - case 120: + case 122: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelFilter = log.NewOrLabelFilter(exprDollar[1].LabelFilter, exprDollar[3].LabelFilter) } - case 121: + case 123: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelExtractionExpression = log.NewLabelExtractionExpr(exprDollar[1].str, exprDollar[3].str) } - case 122: + case 124: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelExtractionExpression = log.NewLabelExtractionExpr(exprDollar[1].str, exprDollar[1].str) } - case 123: + case 125: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LabelExtractionExpressionList = []log.LabelExtractionExpr{exprDollar[1].LabelExtractionExpression} } - case 124: + case 126: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.LabelExtractionExpressionList = append(exprDollar[1].LabelExtractionExpressionList, exprDollar[3].LabelExtractionExpression) } - case 125: + case 127: exprDollar = exprS[exprpt-6 : exprpt+1] { exprVAL.IPLabelFilter = log.NewIPLabelFilter(exprDollar[5].str, exprDollar[1].str, log.LabelFilterEqual) } - case 126: + case 128: exprDollar = exprS[exprpt-6 : exprpt+1] { exprVAL.IPLabelFilter = log.NewIPLabelFilter(exprDollar[5].str, exprDollar[1].str, log.LabelFilterNotEqual) } - case 127: + case 129: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.UnitFilter = exprDollar[1].DurationFilter } - case 128: + case 130: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.UnitFilter = exprDollar[1].BytesFilter } - case 129: + case 131: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterGreaterThan, exprDollar[1].str, exprDollar[3].duration) } - case 130: + case 132: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterGreaterThanOrEqual, exprDollar[1].str, exprDollar[3].duration) } - case 131: + case 133: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterLesserThan, exprDollar[1].str, exprDollar[3].duration) } - case 132: + case 134: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterLesserThanOrEqual, exprDollar[1].str, exprDollar[3].duration) } - case 133: + case 135: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterNotEqual, exprDollar[1].str, exprDollar[3].duration) } - case 134: + case 136: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterEqual, exprDollar[1].str, exprDollar[3].duration) } - case 135: + case 137: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DurationFilter = log.NewDurationLabelFilter(log.LabelFilterEqual, exprDollar[1].str, exprDollar[3].duration) } - case 136: + case 138: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterGreaterThan, exprDollar[1].str, exprDollar[3].bytes) } - case 137: + case 139: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterGreaterThanOrEqual, exprDollar[1].str, exprDollar[3].bytes) } - case 138: + case 140: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterLesserThan, exprDollar[1].str, exprDollar[3].bytes) } - case 139: + case 141: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterLesserThanOrEqual, exprDollar[1].str, exprDollar[3].bytes) } - case 140: + case 142: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterNotEqual, exprDollar[1].str, exprDollar[3].bytes) } - case 141: + case 143: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterEqual, exprDollar[1].str, exprDollar[3].bytes) } - case 142: + case 144: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.BytesFilter = log.NewBytesLabelFilter(log.LabelFilterEqual, exprDollar[1].str, exprDollar[3].bytes) } - case 143: + case 145: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterGreaterThan, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 144: + case 146: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterGreaterThanOrEqual, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 145: + case 147: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterLesserThan, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 146: + case 148: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterLesserThanOrEqual, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 147: + case 149: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterNotEqual, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 148: + case 150: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterEqual, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 149: + case 151: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.NumberFilter = log.NewNumericLabelFilter(log.LabelFilterEqual, exprDollar[1].str, mustNewFloat(exprDollar[3].str)) } - case 150: + case 152: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.DropLabel = log.NewDropLabel(nil, exprDollar[1].str) } - case 151: + case 153: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.DropLabel = log.NewDropLabel(exprDollar[1].Matcher, "") } - case 152: + case 154: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.DropLabels = []log.DropLabel{exprDollar[1].DropLabel} } - case 153: + case 155: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.DropLabels = append(exprDollar[1].DropLabels, exprDollar[3].DropLabel) } - case 154: + case 156: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.DropLabelsExpr = newDropLabelsExpr(exprDollar[2].DropLabels) } - case 155: + case 157: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.KeepLabel = log.NewKeepLabel(nil, exprDollar[1].str) } - case 156: + case 158: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.KeepLabel = log.NewKeepLabel(exprDollar[1].Matcher, "") } - case 157: + case 159: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.KeepLabels = []log.KeepLabel{exprDollar[1].KeepLabel} } - case 158: + case 160: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.KeepLabels = append(exprDollar[1].KeepLabels, exprDollar[3].KeepLabel) } - case 159: + case 161: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.KeepLabelsExpr = newKeepLabelsExpr(exprDollar[2].KeepLabels) } - case 160: + case 162: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("or", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 161: + case 163: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("and", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 162: + case 164: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("unless", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 163: + case 165: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("+", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 164: + case 166: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("-", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 165: + case 167: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("*", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 166: + case 168: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("/", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 167: + case 169: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("%", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 168: + case 170: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("^", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 169: + case 171: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("==", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 170: + case 172: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("!=", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 171: + case 173: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr(">", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 172: + case 174: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr(">=", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 173: + case 175: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("<", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 174: + case 176: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpExpr = mustNewBinOpExpr("<=", exprDollar[3].BinOpModifier, exprDollar[1].Expr, exprDollar[4].Expr) } - case 175: + case 177: exprDollar = exprS[exprpt-0 : exprpt+1] { exprVAL.BoolModifier = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}} } - case 176: + case 178: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.BoolModifier = &BinOpOptions{VectorMatching: &VectorMatching{Card: CardOneToOne}, ReturnBool: true} } - case 177: + case 179: exprDollar = exprS[exprpt-5 : exprpt+1] { exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier exprVAL.OnOrIgnoringModifier.VectorMatching.On = true exprVAL.OnOrIgnoringModifier.VectorMatching.MatchingLabels = exprDollar[4].Labels } - case 178: + case 180: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier exprVAL.OnOrIgnoringModifier.VectorMatching.On = true } - case 179: + case 181: exprDollar = exprS[exprpt-5 : exprpt+1] { exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier exprVAL.OnOrIgnoringModifier.VectorMatching.MatchingLabels = exprDollar[4].Labels } - case 180: + case 182: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.OnOrIgnoringModifier = exprDollar[1].BoolModifier } - case 181: + case 183: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].BoolModifier } - case 182: + case 184: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier } - case 183: + case 185: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne } - case 184: + case 186: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne } - case 185: + case 187: exprDollar = exprS[exprpt-5 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardManyToOne exprVAL.BinOpModifier.VectorMatching.Include = exprDollar[4].Labels } - case 186: + case 188: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany } - case 187: + case 189: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany } - case 188: + case 190: exprDollar = exprS[exprpt-5 : exprpt+1] { exprVAL.BinOpModifier = exprDollar[1].OnOrIgnoringModifier exprVAL.BinOpModifier.VectorMatching.Card = CardOneToMany exprVAL.BinOpModifier.VectorMatching.Include = exprDollar[4].Labels } - case 189: + case 191: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[1].str, false) } - case 190: + case 192: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[2].str, false) } - case 191: + case 193: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.LiteralExpr = mustNewLiteralExpr(exprDollar[2].str, true) } - case 192: + case 194: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.VectorExpr = NewVectorExpr(exprDollar[3].str) } - case 193: + case 195: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.Vector = OpTypeVector } - case 194: + case 196: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeSum } - case 195: + case 197: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeAvg } - case 196: + case 198: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeCount } - case 197: + case 199: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeMax } - case 198: + case 200: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeMin } - case 199: + case 201: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeStddev } - case 200: + case 202: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeStdvar } - case 201: + case 203: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeBottomK } - case 202: + case 204: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeTopK } - case 203: + case 205: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeSort } - case 204: + case 206: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.VectorOp = OpTypeSortDesc } - case 205: + case 207: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeCount } - case 206: + case 208: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeRate } - case 207: + case 209: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeRateCounter } - case 208: + case 210: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeBytes } - case 209: + case 211: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeBytesRate } - case 210: + case 212: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeAvg } - case 211: + case 213: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeSum } - case 212: + case 214: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeMin } - case 213: + case 215: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeMax } - case 214: + case 216: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeStdvar } - case 215: + case 217: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeStddev } - case 216: + case 218: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeQuantile } - case 217: + case 219: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeFirst } - case 218: + case 220: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeLast } - case 219: + case 221: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.RangeOp = OpRangeTypeAbsent } - case 220: + case 222: exprDollar = exprS[exprpt-2 : exprpt+1] { exprVAL.OffsetExpr = newOffsetExpr(exprDollar[2].duration) } - case 221: + case 223: exprDollar = exprS[exprpt-1 : exprpt+1] { exprVAL.Labels = []string{exprDollar[1].str} } - case 222: + case 224: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Labels = append(exprDollar[1].Labels, exprDollar[3].str) } - case 223: + case 225: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.Grouping = &Grouping{Without: false, Groups: exprDollar[3].Labels} } - case 224: + case 226: exprDollar = exprS[exprpt-4 : exprpt+1] { exprVAL.Grouping = &Grouping{Without: true, Groups: exprDollar[3].Labels} } - case 225: + case 227: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Grouping = &Grouping{Without: false, Groups: nil} } - case 226: + case 228: exprDollar = exprS[exprpt-3 : exprpt+1] { exprVAL.Grouping = &Grouping{Without: true, Groups: nil} diff --git a/pkg/logql/syntax/lex.go b/pkg/logql/syntax/lex.go index 14db797e248f1..dc806c921090e 100644 --- a/pkg/logql/syntax/lex.go +++ b/pkg/logql/syntax/lex.go @@ -23,8 +23,10 @@ var tokens = map[string]int{ OpTypeNEQ: NEQ, "=~": RE, "!~": NRE, + "!>": NPA, "|=": PIPE_EXACT, "|~": PIPE_MATCH, + "|>": PIPE_PATTERN, OpPipe: PIPE, OpUnwrap: UNWRAP, "(": OPEN_PARENTHESIS, diff --git a/pkg/logql/syntax/linefilter_test.go b/pkg/logql/syntax/linefilter_test.go index d0cc700ce4601..55fc0fc39179c 100644 --- a/pkg/logql/syntax/linefilter_test.go +++ b/pkg/logql/syntax/linefilter_test.go @@ -16,7 +16,10 @@ func TestLineFilterSerialization(t *testing.T) { {Ty: log.LineMatchEqual, Match: "match", Op: "OR"}, {Ty: log.LineMatchNotEqual, Match: "not match"}, {Ty: log.LineMatchNotEqual, Match: "not match", Op: "OR"}, - {Ty: log.LineMatchRegexp, Op: "OR"}, + {Ty: log.LineMatchPattern, Match: "match"}, + {Ty: log.LineMatchPattern, Match: "match", Op: "OR"}, + {Ty: log.LineMatchNotPattern, Match: "not match"}, + {Ty: log.LineMatchNotPattern, Match: "not match", Op: "OR"}, } { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { b := make([]byte, orig.Size()) diff --git a/pkg/storage/bloom/v1/bloom_tester.go b/pkg/storage/bloom/v1/bloom_tester.go index 5aa688bfc2657..f60166788e4d6 100644 --- a/pkg/storage/bloom/v1/bloom_tester.go +++ b/pkg/storage/bloom/v1/bloom_tester.go @@ -5,6 +5,7 @@ import ( regexpsyntax "github.com/grafana/regexp/syntax" "github.com/grafana/loki/pkg/logql/log" + "github.com/grafana/loki/pkg/logql/log/pattern" "github.com/grafana/loki/pkg/logql/syntax" "github.com/grafana/loki/pkg/storage/bloom/v1/filter" ) @@ -89,7 +90,7 @@ func FiltersToBloomTest(b NGramBuilder, filters ...syntax.LineFilterExpr) BloomT func simpleFilterToBloomTest(b NGramBuilder, filter syntax.LineFilter) BloomTest { switch filter.Ty { - case log.LineMatchNotEqual, log.LineMatchNotRegexp: + case log.LineMatchNotEqual, log.LineMatchNotRegexp, log.LineMatchNotPattern: // We cannot test _negated_ filters with a bloom filter since blooms are probabilistic // filters that can only tell us if a string _might_ exist. // For example, for `!= "foo"`, the bloom filter might tell us that the string "foo" might exist @@ -114,6 +115,8 @@ func simpleFilterToBloomTest(b NGramBuilder, filter syntax.LineFilter) BloomTest } return matcherFilterWrapper{filter: matcher} + case log.LineMatchPattern: + return newPatternTest(b, filter.Match) default: return MatchAll } @@ -275,3 +278,20 @@ func (o orTest) Matches(bloom filter.Checker) bool { func (o orTest) MatchesWithPrefixBuf(bloom filter.Checker, buf []byte, prefixLen int) bool { return o.left.MatchesWithPrefixBuf(bloom, buf, prefixLen) || o.right.MatchesWithPrefixBuf(bloom, buf, prefixLen) } + +func newPatternTest(b NGramBuilder, match string) BloomTest { + lit, err := pattern.ParseLiterals(match) + if err != nil { + return MatchAll + } + var test stringTest + for _, l := range lit { + it := b.Tokens(string(l)) + for it.Next() { + ngram := make([]byte, len(it.At())) + copy(ngram, it.At()) + test.ngrams = append(test.ngrams, ngram) + } + } + return test +} diff --git a/pkg/storage/bloom/v1/bloom_tester_test.go b/pkg/storage/bloom/v1/bloom_tester_test.go index 991ac092dee39..085d56c590063 100644 --- a/pkg/storage/bloom/v1/bloom_tester_test.go +++ b/pkg/storage/bloom/v1/bloom_tester_test.go @@ -166,6 +166,42 @@ func TestFiltersToBloomTests(t *testing.T) { bloom: fakeBloom{"foo"}, expectMatch: true, }, + { + name: "pattern match exists", + query: `{app="fake"} |> "<_>foo"`, + bloom: fakeBloom{"foo", "bar"}, + expectMatch: true, + }, + { + name: "pattern match does not exist", + query: `{app="fake"} |> "<_>foo"`, + bloom: fakeBloom{"bar", "baz"}, + expectMatch: false, + }, + { + name: "pattern not match exists", + query: `{app="fake"} !> "<_>foo"`, + bloom: fakeBloom{"foo", "bar"}, + expectMatch: true, + }, + { + name: "pattern not match does not exist", + query: `{app="fake"} !> "<_>foo"`, + bloom: fakeBloom{"bar", "baz"}, + expectMatch: true, + }, + { + name: "pattern all", + query: `{app="fake"} |> "<_>"`, + bloom: fakeBloom{"bar", "baz"}, + expectMatch: true, + }, + { + name: "pattern empty", + query: `{app="fake"} |> ""`, + bloom: fakeBloom{"bar", "baz"}, + expectMatch: true, + }, } { t.Run(tc.name, func(t *testing.T) { expr, err := syntax.ParseExpr(tc.query)