chore: LogQL syntax and AST simplification and cosistency (#16028)

This PR aims for making the grammar file (syntax.y) for the LogQL syntax more readable and the AST and its expressions more consistent in naming. You could say these are cosmetics, and yes they are, but if they can help developers better and faster understand the code it's a win. Personally I found the grammar yacc file intimidating until I understood that it was way more complicated that it needed to be. I hope it enables future additions to the syntax to be easier to implement.

Signed-off-by: Christian Haudum <christian.haudum@gmail.com>
pull/16100/head
Christian Haudum 3 months ago committed by GitHub
parent 9a36eca5e0
commit 1187a73667
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      Makefile
  2. 6
      pkg/logql/downstream_test.go
  3. 2
      pkg/logql/engine.go
  4. 24
      pkg/logql/log/drop_labels.go
  5. 12
      pkg/logql/log/drop_labels_test.go
  6. 24
      pkg/logql/log/keep_labels.go
  7. 10
      pkg/logql/log/keep_labels_test.go
  8. 10
      pkg/logql/log/pipeline_test.go
  9. 6
      pkg/logql/optimize.go
  10. 2
      pkg/logql/range_vector_test.go
  11. 2
      pkg/logql/rangemapper.go
  12. 88
      pkg/logql/shardmapper_test.go
  13. 297
      pkg/logql/syntax/ast.go
  14. 8
      pkg/logql/syntax/ast_test.go
  15. 26
      pkg/logql/syntax/clone.go
  16. 2046
      pkg/logql/syntax/expr.y.go
  17. 10
      pkg/logql/syntax/lex.go
  18. 12
      pkg/logql/syntax/lex_test.go
  19. 8
      pkg/logql/syntax/parser.go
  20. 120
      pkg/logql/syntax/parser_test.go
  21. 8
      pkg/logql/syntax/prettier.go
  22. 28
      pkg/logql/syntax/serialize.go
  23. 275
      pkg/logql/syntax/syntax.y
  24. 1989
      pkg/logql/syntax/syntax.y.go
  25. 2
      pkg/logql/syntax/test_utils.go
  26. 24
      pkg/logql/syntax/visit.go
  27. 4
      pkg/logql/syntax/visit_test.go
  28. 2
      pkg/querier/queryrange/split_by_interval.go

@ -424,9 +424,7 @@ yacc: $(YACC_GOS)
ifeq ($(BUILD_IN_CONTAINER),true)
$(run_in_container)
else
goyacc -p $(basename $(notdir $<)) -o $@ $<
sed -i.back '/^\/\/line/ d' $@
rm ${@}.back
goyacc -l -p $(basename $(notdir $<)) -o $@ $<
endif
#########

@ -838,7 +838,7 @@ func TestFormat_ShardedExpr(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -854,7 +854,7 @@ func TestFormat_ShardedExpr(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -870,7 +870,7 @@ func TestFormat_ShardedExpr(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},

@ -489,7 +489,7 @@ func (q *query) checkIntervalLimit(expr syntax.SampleExpr, limit time.Duration)
var err error
expr.Walk(func(e syntax.Expr) {
switch e := e.(type) {
case *syntax.LogRange:
case *syntax.LogRangeExpr:
if e.Interval > limit {
err = fmt.Errorf("%w: [%s] > [%s]", logqlmodel.ErrIntervalLimit, model.Duration(e.Interval), model.Duration(limit))
}

@ -6,28 +6,28 @@ import (
"github.com/grafana/loki/v3/pkg/logqlmodel"
)
type DropLabels struct {
dropLabels []DropLabel
}
type DropLabel struct {
type NamedLabelMatcher struct {
Matcher *labels.Matcher
Name string
}
func NewDropLabel(matcher *labels.Matcher, name string) DropLabel {
return DropLabel{
Matcher: matcher,
Name: name,
func NewNamedLabelMatcher(m *labels.Matcher, n string) NamedLabelMatcher {
return NamedLabelMatcher{
Matcher: m,
Name: n,
}
}
func NewDropLabels(dl []DropLabel) *DropLabels {
return &DropLabels{dropLabels: dl}
type DropLabels struct {
labels []NamedLabelMatcher
}
func NewDropLabels(labels []NamedLabelMatcher) *DropLabels {
return &DropLabels{labels: labels}
}
func (dl *DropLabels) Process(_ int64, line []byte, lbls *LabelsBuilder) ([]byte, bool) {
for _, dropLabel := range dl.dropLabels {
for _, dropLabel := range dl.labels {
if dropLabel.Matcher != nil {
dropLabelMatches(dropLabel.Matcher, lbls)
continue

@ -12,7 +12,7 @@ import (
func Test_DropLabels(t *testing.T) {
tests := []struct {
Name string
dropLabels []DropLabel
dropLabels []NamedLabelMatcher
err string
errDetails string
lbs labels.Labels
@ -20,7 +20,7 @@ func Test_DropLabels(t *testing.T) {
}{
{
"drop by name",
[]DropLabel{
[]NamedLabelMatcher{
{
nil,
"app",
@ -40,7 +40,7 @@ func Test_DropLabels(t *testing.T) {
},
{
"drop by __error__",
[]DropLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, logqlmodel.ErrorLabel, errJSON),
"",
@ -63,7 +63,7 @@ func Test_DropLabels(t *testing.T) {
},
{
"drop with wrong __error__ value",
[]DropLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, logqlmodel.ErrorLabel, errLogfmt),
"",
@ -84,7 +84,7 @@ func Test_DropLabels(t *testing.T) {
},
{
"drop by __error_details__",
[]DropLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchRegexp, logqlmodel.ErrorDetailsLabel, "expecting json.*"),
"",
@ -107,7 +107,7 @@ func Test_DropLabels(t *testing.T) {
},
{
"drop labels with names and matcher",
[]DropLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, logqlmodel.ErrorLabel, errJSON),
"",

@ -1,33 +1,19 @@
package log
import (
"github.com/prometheus/prometheus/model/labels"
"github.com/grafana/loki/v3/pkg/logqlmodel"
)
type KeepLabels struct {
keepLabels []KeepLabel
}
type KeepLabel struct {
Matcher *labels.Matcher
Name string
}
func NewKeepLabel(matcher *labels.Matcher, name string) KeepLabel {
return KeepLabel{
Matcher: matcher,
Name: name,
}
labels []NamedLabelMatcher
}
func NewKeepLabels(kl []KeepLabel) *KeepLabels {
return &KeepLabels{keepLabels: kl}
func NewKeepLabels(labels []NamedLabelMatcher) *KeepLabels {
return &KeepLabels{labels: labels}
}
func (kl *KeepLabels) Process(_ int64, line []byte, lbls *LabelsBuilder) ([]byte, bool) {
if len(kl.keepLabels) == 0 {
if len(kl.labels) == 0 {
return line, true
}
@ -38,7 +24,7 @@ func (kl *KeepLabels) Process(_ int64, line []byte, lbls *LabelsBuilder) ([]byte
}
var keep bool
for _, keepLabel := range kl.keepLabels {
for _, keepLabel := range kl.labels {
if keepLabel.Matcher != nil && keepLabel.Matcher.Name == lb.Name && keepLabel.Matcher.Matches(lb.Value) {
keep = true
break

@ -12,14 +12,14 @@ import (
func Test_KeepLabels(t *testing.T) {
for _, tc := range []struct {
Name string
keepLabels []KeepLabel
keepLabels []NamedLabelMatcher
lbs labels.Labels
want labels.Labels
}{
{
"keep all",
[]KeepLabel{},
[]NamedLabelMatcher{},
labels.FromStrings(
"app", "foo",
"namespace", "prod",
@ -35,7 +35,7 @@ func Test_KeepLabels(t *testing.T) {
},
{
"keep by name",
[]KeepLabel{
[]NamedLabelMatcher{
{
nil,
"app",
@ -58,7 +58,7 @@ func Test_KeepLabels(t *testing.T) {
},
{
"keep labels with names and matcher",
[]KeepLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, "namespace", "prod"),
"",
@ -85,7 +85,7 @@ func Test_KeepLabels(t *testing.T) {
},
{
"preserve special labels",
[]KeepLabel{
[]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, "namespace", "prod"),
"",

@ -328,7 +328,7 @@ func TestDropLabelsPipeline(t *testing.T) {
[]Stage{
NewLogfmtParser(true, false),
NewJSONParser(),
NewDropLabels([]DropLabel{
NewDropLabels([]NamedLabelMatcher{
{
nil,
"__error__",
@ -365,7 +365,7 @@ func TestDropLabelsPipeline(t *testing.T) {
[]Stage{
NewLogfmtParser(true, false),
NewJSONParser(),
NewDropLabels([]DropLabel{
NewDropLabels([]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, logqlmodel.ErrorLabel, errLogfmt),
"",
@ -431,7 +431,7 @@ func TestKeepLabelsPipeline(t *testing.T) {
name: "keep all",
stages: []Stage{
NewLogfmtParser(false, false),
NewKeepLabels([]KeepLabel{}),
NewKeepLabels([]NamedLabelMatcher{}),
},
lines: [][]byte{
[]byte(`level=info ts=2020-10-18T18:04:22.147378997Z caller=metrics.go:81 status=200`),
@ -467,7 +467,7 @@ func TestKeepLabelsPipeline(t *testing.T) {
name: "keep by name",
stages: []Stage{
NewLogfmtParser(false, false),
NewKeepLabels([]KeepLabel{
NewKeepLabels([]NamedLabelMatcher{
{
nil,
"level",
@ -498,7 +498,7 @@ func TestKeepLabelsPipeline(t *testing.T) {
name: "keep by matcher",
stages: []Stage{
NewLogfmtParser(false, false),
NewKeepLabels([]KeepLabel{
NewKeepLabels([]NamedLabelMatcher{
{
labels.MustNewMatcher(labels.MatchEqual, "level", "info"),
"",

@ -55,7 +55,7 @@ func removeLineformat(expr syntax.SampleExpr) {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LabelParserExpr); ok {
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LineParserExpr); ok {
found = true
break
}
@ -63,11 +63,11 @@ func removeLineformat(expr syntax.SampleExpr) {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.JSONExpressionParser); ok {
if _, ok := pipelineExpr.MultiStages[j].(*syntax.JSONExpressionParserExpr); ok {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LogfmtExpressionParser); ok {
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LogfmtExpressionParserExpr); ok {
found = true
break
}

@ -541,7 +541,7 @@ func Test_InstantQueryRangeVectorAggregations(t *testing.T) {
for _, tt := range tests {
t.Run(fmt.Sprintf("testing aggregation %s", tt.name), func(t *testing.T) {
it, err := newRangeVectorIterator(sampleIter(tt.negative),
&syntax.RangeAggregationExpr{Left: &syntax.LogRange{Interval: 2}, Params: proto.Float64(0.99), Operation: tt.op},
&syntax.RangeAggregationExpr{Left: &syntax.LogRangeExpr{Interval: 2}, Params: proto.Float64(0.99), Operation: tt.op},
3, 1, start, end, 0)
require.NoError(t, err)

@ -208,7 +208,7 @@ func hasLabelExtractionStage(expr syntax.SampleExpr) bool {
switch concrete := e.(type) {
case *syntax.LogfmtParserExpr:
found = true
case *syntax.LabelParserExpr:
case *syntax.LineParserExpr:
// It will **not** return true for `regexp`, `unpack` and `pattern`, since these label extraction
// stages can control how many labels, and therefore the resulting amount of series, are extracted.
if concrete.Op == syntax.OpParserTypeJSON {

@ -62,7 +62,7 @@ func TestMapSampleExpr(t *testing.T) {
{
in: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -77,7 +77,7 @@ func TestMapSampleExpr(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -93,7 +93,7 @@ func TestMapSampleExpr(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -624,7 +624,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -640,7 +640,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -662,7 +662,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeCount,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -678,7 +678,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeCount,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -706,7 +706,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -726,7 +726,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -754,7 +754,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -770,7 +770,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -800,7 +800,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCountMinSketch,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -819,7 +819,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCountMinSketch,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -849,7 +849,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -869,7 +869,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -901,7 +901,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -921,7 +921,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -948,7 +948,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -968,7 +968,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1010,7 +1010,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1032,7 +1032,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1070,7 +1070,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1090,7 +1090,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1125,7 +1125,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1145,7 +1145,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1189,7 +1189,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1211,7 +1211,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1239,7 +1239,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1259,7 +1259,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1303,7 +1303,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1325,7 +1325,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1352,7 +1352,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1372,7 +1372,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeCount,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeRate,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1409,7 +1409,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeSum,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1434,7 +1434,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeSum,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1468,7 +1468,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeCount,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1490,7 +1490,7 @@ func TestMapping(t *testing.T) {
Operation: syntax.OpTypeSum,
Left: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeCount,
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1510,7 +1510,7 @@ func TestMapping(t *testing.T) {
expr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeQuantile,
Params: float64p(0.8),
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1526,7 +1526,7 @@ func TestMapping(t *testing.T) {
expr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeQuantile,
Params: float64p(0.8),
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")},
},
@ -1551,7 +1551,7 @@ func TestMapping(t *testing.T) {
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeQuantile,
Params: float64p(0.99),
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "a", "foo")},
},
@ -1574,7 +1574,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.VectorAggregationExpr{
Left: &syntax.RangeAggregationExpr{
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "a", "bar")},
},
@ -1597,7 +1597,7 @@ func TestMapping(t *testing.T) {
}).Bind(nil),
SampleExpr: &syntax.VectorAggregationExpr{
Left: &syntax.RangeAggregationExpr{
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "a", "bar")},
},
@ -1634,7 +1634,7 @@ func TestMapping(t *testing.T) {
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeQuantile,
Params: float64p(0.99),
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "a", "foo")},
},
@ -1668,7 +1668,7 @@ func TestMapping(t *testing.T) {
SampleExpr: &syntax.RangeAggregationExpr{
Operation: syntax.OpRangeTypeQuantile,
Params: float64p(0.99),
Left: &syntax.LogRange{
Left: &syntax.LogRangeExpr{
Left: &syntax.MatchersExpr{
Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "a", "foo")},
},

@ -21,20 +21,107 @@ import (
"github.com/grafana/loki/v3/pkg/logqlmodel"
)
// Type alias for backward compatibility
type (
Pipeline = log.Pipeline
SampleExtractor = log.SampleExtractor
)
// Expr is the root expression which can be a SampleExpr or LogSelectorExpr
//
//sumtype:decl
type Expr interface {
logQLExpr() // ensure it's not implemented accidentally
Shardable(topLevel bool) bool // A recursive check on the AST to see if it's shardable.
// Shardable performs a recursive check on the expression and its children to see whether it is shardable.
Shardable(topLevel bool) bool
// Accepts a walk function to recursively visit the AST
// Works on expressions that are represented in the LogQL syntax as well as expressions from the "execution plan".
Walkable
fmt.Stringer
// Accepts a visitor to recursively visit the AST.
// Only works on expressions that are represented in the LogQL syntax.
AcceptVisitor
// Pretty prettyfies any LogQL expression at given `level` of the whole LogQL query.
// Returns the string representation of the expression.
fmt.Stringer
// Pretty returns a nicely formatted string representation of the expression at given level.
Pretty(level int) string
// isExpr ensures that the interface is not implemented accidentally.
isExpr()
}
func (MatchersExpr) isExpr() {}
func (PipelineExpr) isExpr() {}
func (RangeAggregationExpr) isExpr() {}
func (VectorAggregationExpr) isExpr() {}
func (LiteralExpr) isExpr() {}
func (VectorExpr) isExpr() {}
func (LabelReplaceExpr) isExpr() {}
func (LineParserExpr) isExpr() {}
func (LogfmtParserExpr) isExpr() {}
func (LineFilterExpr) isExpr() {}
func (LabelFilterExpr) isExpr() {}
func (DecolorizeExpr) isExpr() {}
func (DropLabelsExpr) isExpr() {}
func (KeepLabelsExpr) isExpr() {}
func (LineFmtExpr) isExpr() {}
func (LabelFmtExpr) isExpr() {}
func (JSONExpressionParserExpr) isExpr() {}
func (LogfmtExpressionParserExpr) isExpr() {}
func (LogRangeExpr) isExpr() {}
func (OffsetExpr) isExpr() {}
func (UnwrapExpr) isExpr() {}
// LogSelectorExpr is a expression filtering and returning logs.
type LogSelectorExpr interface {
Matchers() []*labels.Matcher
Pipeline() (Pipeline, error)
HasFilter() bool
Expr
// isLogSelectorExpr ensures that the interface is not implemented accidentally.
isLogSelectorExpr()
}
func (MatchersExpr) isLogSelectorExpr() {}
func (PipelineExpr) isLogSelectorExpr() {}
func (MultiStageExpr) isLogSelectorExpr() {}
func (LiteralExpr) isLogSelectorExpr() {}
func (VectorExpr) isLogSelectorExpr() {}
// SampleExpr is a LogQL expression filtering logs and returning metric samples
type SampleExpr interface {
Selector() (LogSelectorExpr, error)
Extractor() (SampleExtractor, error)
MatcherGroups() ([]MatcherRange, error)
Expr
// isSampleExpr ensures that the interface is not implemented accidentally.
isSampleExpr()
}
func (RangeAggregationExpr) isSampleExpr() {}
func (VectorAggregationExpr) isSampleExpr() {}
func (LiteralExpr) isSampleExpr() {}
func (VectorExpr) isSampleExpr() {}
func (LabelReplaceExpr) isSampleExpr() {}
// StageExpr is an expression defining a single step into a log pipeline
type StageExpr interface {
Stage() (log.Stage, error)
Expr
// isStageExpr ensures that the interface is not implemented accidentally.
isStageExpr()
}
func (LineParserExpr) isStageExpr() {}
func (LogfmtParserExpr) isStageExpr() {}
func (LineFilterExpr) isStageExpr() {}
func (LabelFilterExpr) isStageExpr() {}
func (DecolorizeExpr) isStageExpr() {}
func (DropLabelsExpr) isStageExpr() {}
func (KeepLabelsExpr) isStageExpr() {}
func (LineFmtExpr) isStageExpr() {}
func (LabelFmtExpr) isStageExpr() {}
func (JSONExpressionParserExpr) isStageExpr() {}
func (LogfmtExpressionParserExpr) isStageExpr() {}
func Clone[T Expr](e T) (T, error) {
var empty T
v := &cloneVisitor{}
@ -95,9 +182,9 @@ func ExtractLabelFiltersBeforeParser(e Expr) []*LabelFilterExpr {
// misbehave.
VisitLogfmtParserFn: func(_ RootVisitor, _ *LogfmtParserExpr) { foundParseStage = true },
VisitLabelParserFn: func(_ RootVisitor, _ *LabelParserExpr) { foundParseStage = true },
VisitJSONExpressionParserFn: func(_ RootVisitor, _ *JSONExpressionParser) { foundParseStage = true },
VisitLogfmtExpressionParserFn: func(_ RootVisitor, _ *LogfmtExpressionParser) { foundParseStage = true },
VisitLabelParserFn: func(_ RootVisitor, _ *LineParserExpr) { foundParseStage = true },
VisitJSONExpressionParserFn: func(_ RootVisitor, _ *JSONExpressionParserExpr) { foundParseStage = true },
VisitLogfmtExpressionParserFn: func(_ RootVisitor, _ *LogfmtExpressionParserExpr) { foundParseStage = true },
VisitLabelFmtFn: func(_ RootVisitor, _ *LabelFmtExpr) { foundParseStage = true },
VisitKeepLabelFn: func(_ RootVisitor, _ *KeepLabelsExpr) { foundParseStage = true },
VisitDropLabelsFn: func(_ RootVisitor, _ *DropLabelsExpr) { foundParseStage = true },
@ -119,39 +206,6 @@ func IsMatchEqualFilterer(filterer log.LabelFilterer) bool {
}
}
// implicit holds default implementations
type implicit struct{}
func (implicit) logQLExpr() {}
// LogSelectorExpr is a LogQL expression filtering and returning logs.
//
//sumtype:decl
type LogSelectorExpr interface {
Matchers() []*labels.Matcher
Pipeline() (Pipeline, error)
HasFilter() bool
Expr
isLogSelectorExpr()
}
// Type alias for backward compatibility
type (
Pipeline = log.Pipeline
SampleExtractor = log.SampleExtractor
)
// StageExpr is an expression defining a single step into a log pipeline
//
//sumtype:decl
type StageExpr interface {
Stage() (log.Stage, error)
Expr
isStageExpr()
}
// MultiStageExpr is multiple stages which implements a LogSelectorExpr.
type MultiStageExpr []StageExpr
@ -213,7 +267,7 @@ func (m MultiStageExpr) reorderStages() []StageExpr {
notLineFilters = append(notLineFilters, f)
combineFilters()
case *LabelParserExpr:
case *LineParserExpr:
notLineFilters = append(notLineFilters, f)
// unpack modifies the contents of the line so any line filter
@ -270,15 +324,12 @@ func (MultiStageExpr) logQLExpr() {} // nolint:unused
type MatchersExpr struct {
Mts []*labels.Matcher
implicit
}
func newMatcherExpr(matchers []*labels.Matcher) *MatchersExpr {
return &MatchersExpr{Mts: matchers}
}
func (e *MatchersExpr) isLogSelectorExpr() {}
func (e *MatchersExpr) Matchers() []*labels.Matcher {
return e.Mts
}
@ -317,7 +368,6 @@ func (e *MatchersExpr) HasFilter() bool {
type PipelineExpr struct {
MultiStages MultiStageExpr
Left *MatchersExpr
implicit
}
func newPipelineExpr(left *MatchersExpr, pipeline MultiStageExpr) LogSelectorExpr {
@ -327,8 +377,6 @@ func newPipelineExpr(left *MatchersExpr, pipeline MultiStageExpr) LogSelectorExp
}
}
func (e *PipelineExpr) isLogSelectorExpr() {}
func (e *PipelineExpr) Shardable(topLevel bool) bool {
for _, p := range e.MultiStages {
if !p.Shardable(topLevel) {
@ -407,7 +455,6 @@ type LineFilterExpr struct {
// See LineFilterExpr tests for more examples.
Or *LineFilterExpr
IsOrChild bool
implicit
}
func newLineFilterExpr(ty log.LineMatchType, op, match string) *LineFilterExpr {
@ -420,7 +467,7 @@ func newLineFilterExpr(ty log.LineMatchType, op, match string) *LineFilterExpr {
}
}
func newOrLineFilter(left, right *LineFilterExpr) *LineFilterExpr {
func newOrLineFilterExpr(left, right *LineFilterExpr) *LineFilterExpr {
right.Ty = left.Ty
// NOTE: Consider, we have chain of "or", != "foo" or "bar" or "baz"
@ -493,8 +540,6 @@ func newNestedLineFilterExpr(left *LineFilterExpr, right *LineFilterExpr) *LineF
}
}
func (*LineFilterExpr) isStageExpr() {}
func (e *LineFilterExpr) Walk(f WalkFn) {
f(e)
if e.Left != nil {
@ -626,8 +671,6 @@ func (e *LineFilterExpr) Stage() (log.Stage, error) {
type LogfmtParserExpr struct {
Strict bool
KeepEmpty bool
implicit
}
func newLogfmtParserExpr(flags []string) *LogfmtParserExpr {
@ -644,8 +687,6 @@ func newLogfmtParserExpr(flags []string) *LogfmtParserExpr {
return &e
}
func (*LogfmtParserExpr) isStageExpr() {}
func (e *LogfmtParserExpr) Shardable(_ bool) bool { return true }
func (e *LogfmtParserExpr) Walk(f WalkFn) { f(e) }
@ -675,13 +716,12 @@ func (e *LogfmtParserExpr) String() string {
return sb.String()
}
type LabelParserExpr struct {
type LineParserExpr struct {
Op string
Param string
implicit
}
func newLabelParserExpr(op, param string) *LabelParserExpr {
func newLabelParserExpr(op, param string) *LineParserExpr {
if op == OpParserTypeRegexp {
_, err := log.NewRegexpParser(param)
if err != nil {
@ -695,21 +735,19 @@ func newLabelParserExpr(op, param string) *LabelParserExpr {
}
}
return &LabelParserExpr{
return &LineParserExpr{
Op: op,
Param: param,
}
}
func (*LabelParserExpr) isStageExpr() {}
func (e *LineParserExpr) Shardable(_ bool) bool { return true }
func (e *LabelParserExpr) Shardable(_ bool) bool { return true }
func (e *LineParserExpr) Walk(f WalkFn) { f(e) }
func (e *LabelParserExpr) Walk(f WalkFn) { f(e) }
func (e *LineParserExpr) Accept(v RootVisitor) { v.VisitLabelParser(e) }
func (e *LabelParserExpr) Accept(v RootVisitor) { v.VisitLabelParser(e) }
func (e *LabelParserExpr) Stage() (log.Stage, error) {
func (e *LineParserExpr) Stage() (log.Stage, error) {
switch e.Op {
case OpParserTypeJSON:
return log.NewJSONParser(), nil
@ -724,7 +762,7 @@ func (e *LabelParserExpr) Stage() (log.Stage, error) {
}
}
func (e *LabelParserExpr) String() string {
func (e *LineParserExpr) String() string {
var sb strings.Builder
sb.WriteString(OpPipe)
sb.WriteString(" ")
@ -741,7 +779,6 @@ func (e *LabelParserExpr) String() string {
type LabelFilterExpr struct {
log.LabelFilterer
implicit
}
func newLabelFilterExpr(filterer log.LabelFilterer) *LabelFilterExpr {
@ -750,8 +787,6 @@ func newLabelFilterExpr(filterer log.LabelFilterer) *LabelFilterExpr {
}
}
func (*LabelFilterExpr) isStageExpr() {}
func (e *LabelFilterExpr) Shardable(_ bool) bool { return true }
func (e *LabelFilterExpr) Walk(f WalkFn) { f(e) }
@ -774,7 +809,6 @@ func (e *LabelFilterExpr) String() string {
type LineFmtExpr struct {
Value string
implicit
}
func newLineFmtExpr(value string) *LineFmtExpr {
@ -784,15 +818,12 @@ func newLineFmtExpr(value string) *LineFmtExpr {
}
type DecolorizeExpr struct {
implicit
}
func newDecolorizeExpr() *DecolorizeExpr {
return &DecolorizeExpr{}
}
func (*DecolorizeExpr) isStageExpr() {}
func (e *DecolorizeExpr) Shardable(_ bool) bool { return true }
func (e *DecolorizeExpr) Stage() (log.Stage, error) {
@ -807,16 +838,13 @@ func (e *DecolorizeExpr) Walk(f WalkFn) { f(e) }
func (e *DecolorizeExpr) Accept(v RootVisitor) { v.VisitDecolorize(e) }
type DropLabelsExpr struct {
dropLabels []log.DropLabel
implicit
dropLabels []log.NamedLabelMatcher
}
func newDropLabelsExpr(dropLabels []log.DropLabel) *DropLabelsExpr {
func newDropLabelsExpr(dropLabels []log.NamedLabelMatcher) *DropLabelsExpr {
return &DropLabelsExpr{dropLabels: dropLabels}
}
func (*DropLabelsExpr) isStageExpr() {}
func (e *DropLabelsExpr) Shardable(_ bool) bool { return true }
func (e *DropLabelsExpr) Stage() (log.Stage, error) {
@ -850,16 +878,13 @@ func (e *DropLabelsExpr) Walk(f WalkFn) { f(e) }
func (e *DropLabelsExpr) Accept(v RootVisitor) { v.VisitDropLabels(e) }
type KeepLabelsExpr struct {
keepLabels []log.KeepLabel
implicit
keepLabels []log.NamedLabelMatcher
}
func newKeepLabelsExpr(keepLabels []log.KeepLabel) *KeepLabelsExpr {
func newKeepLabelsExpr(keepLabels []log.NamedLabelMatcher) *KeepLabelsExpr {
return &KeepLabelsExpr{keepLabels: keepLabels}
}
func (*KeepLabelsExpr) isStageExpr() {}
func (e *KeepLabelsExpr) Shardable(_ bool) bool { return true }
func (e *KeepLabelsExpr) Stage() (log.Stage, error) {
@ -893,8 +918,6 @@ func (e *KeepLabelsExpr) Walk(f WalkFn) { f(e) }
func (e *KeepLabelsExpr) Accept(v RootVisitor) { v.VisitKeepLabel(e) }
func (*LineFmtExpr) isStageExpr() {}
func (e *LineFmtExpr) Shardable(_ bool) bool { return true }
func (e *LineFmtExpr) Walk(f WalkFn) { f(e) }
@ -911,7 +934,6 @@ func (e *LineFmtExpr) String() string {
type LabelFmtExpr struct {
Formats []log.LabelFmt
implicit
}
func newLabelFmtExpr(fmts []log.LabelFmt) *LabelFmtExpr {
@ -920,8 +942,6 @@ func newLabelFmtExpr(fmts []log.LabelFmt) *LabelFmtExpr {
}
}
func (*LabelFmtExpr) isStageExpr() {}
func (e *LabelFmtExpr) Shardable(_ bool) bool {
// While LabelFmt is shardable in certain cases, it is not always,
// but this is left to the shardmapper to determine
@ -956,31 +976,27 @@ func (e *LabelFmtExpr) String() string {
return sb.String()
}
type JSONExpressionParser struct {
type JSONExpressionParserExpr struct {
Expressions []log.LabelExtractionExpr
implicit
}
func newJSONExpressionParser(expressions []log.LabelExtractionExpr) *JSONExpressionParser {
return &JSONExpressionParser{
func newJSONExpressionParser(expressions []log.LabelExtractionExpr) *JSONExpressionParserExpr {
return &JSONExpressionParserExpr{
Expressions: expressions,
}
}
func (*JSONExpressionParser) isStageExpr() {}
func (j *JSONExpressionParser) Shardable(_ bool) bool { return true }
func (j *JSONExpressionParserExpr) Shardable(_ bool) bool { return true }
func (j *JSONExpressionParser) Walk(f WalkFn) { f(j) }
func (j *JSONExpressionParserExpr) Walk(f WalkFn) { f(j) }
func (j *JSONExpressionParser) Accept(v RootVisitor) { v.VisitJSONExpressionParser(j) }
func (j *JSONExpressionParserExpr) Accept(v RootVisitor) { v.VisitJSONExpressionParser(j) }
func (j *JSONExpressionParser) Stage() (log.Stage, error) {
func (j *JSONExpressionParserExpr) Stage() (log.Stage, error) {
return log.NewJSONExpressionParser(j.Expressions)
}
func (j *JSONExpressionParser) String() string {
func (j *JSONExpressionParserExpr) String() string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s %s ", OpPipe, OpParserTypeJSON))
for i, exp := range j.Expressions {
@ -1000,15 +1016,13 @@ type internedStringSet map[string]struct {
ok bool
}
type LogfmtExpressionParser struct {
type LogfmtExpressionParserExpr struct {
Expressions []log.LabelExtractionExpr
Strict, KeepEmpty bool
implicit
}
func newLogfmtExpressionParser(expressions []log.LabelExtractionExpr, flags []string) *LogfmtExpressionParser {
e := LogfmtExpressionParser{
func newLogfmtExpressionParser(expressions []log.LabelExtractionExpr, flags []string) *LogfmtExpressionParserExpr {
e := LogfmtExpressionParserExpr{
Expressions: expressions,
}
@ -1024,19 +1038,17 @@ func newLogfmtExpressionParser(expressions []log.LabelExtractionExpr, flags []st
return &e
}
func (*LogfmtExpressionParser) isStageExpr() {}
func (l *LogfmtExpressionParser) Shardable(_ bool) bool { return true }
func (l *LogfmtExpressionParserExpr) Shardable(_ bool) bool { return true }
func (l *LogfmtExpressionParser) Walk(f WalkFn) { f(l) }
func (l *LogfmtExpressionParserExpr) Walk(f WalkFn) { f(l) }
func (l *LogfmtExpressionParser) Accept(v RootVisitor) { v.VisitLogfmtExpressionParser(l) }
func (l *LogfmtExpressionParserExpr) Accept(v RootVisitor) { v.VisitLogfmtExpressionParser(l) }
func (l *LogfmtExpressionParser) Stage() (log.Stage, error) {
func (l *LogfmtExpressionParserExpr) Stage() (log.Stage, error) {
return log.NewLogfmtExpressionParser(l.Expressions, l.Strict)
}
func (l *LogfmtExpressionParser) String() string {
func (l *LogfmtExpressionParserExpr) String() string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s %s ", OpPipe, OpParserTypeLogfmt))
if l.Strict {
@ -1122,18 +1134,15 @@ func newUnwrapExpr(id string, operation string) *UnwrapExpr {
return &UnwrapExpr{Identifier: id, Operation: operation}
}
type LogRange struct {
type LogRangeExpr struct {
Left LogSelectorExpr
Interval time.Duration
Offset time.Duration
Unwrap *UnwrapExpr
implicit
Unwrap *UnwrapExpr
}
// impls Stringer
func (r LogRange) String() string {
func (r LogRangeExpr) String() string {
var sb strings.Builder
sb.WriteString(r.Left.String())
if r.Unwrap != nil {
@ -1147,38 +1156,38 @@ func (r LogRange) String() string {
return sb.String()
}
func (r *LogRange) Shardable(topLevel bool) bool { return r.Left.Shardable(topLevel) }
func (r *LogRangeExpr) Shardable(topLevel bool) bool { return r.Left.Shardable(topLevel) }
func (r *LogRange) Walk(f WalkFn) {
func (r *LogRangeExpr) Walk(f WalkFn) {
f(r)
if r.Left != nil {
r.Left.Walk(f)
}
}
func (r *LogRange) Accept(v RootVisitor) {
func (r *LogRangeExpr) Accept(v RootVisitor) {
v.VisitLogRange(r)
}
// WithoutUnwrap returns a copy of the log range without the unwrap statement.
func (r *LogRange) WithoutUnwrap() (*LogRange, error) {
func (r *LogRangeExpr) WithoutUnwrap() (*LogRangeExpr, error) {
left, err := Clone(r.Left)
if err != nil {
return nil, err
}
return &LogRange{
return &LogRangeExpr{
Left: left,
Interval: r.Interval,
Offset: r.Offset,
}, nil
}
func newLogRange(left LogSelectorExpr, interval time.Duration, u *UnwrapExpr, o *OffsetExpr) *LogRange {
func newLogRange(left LogSelectorExpr, interval time.Duration, u *UnwrapExpr, o *OffsetExpr) *LogRangeExpr {
var offset time.Duration
if o != nil {
offset = o.Offset
}
return &LogRange{
return &LogRangeExpr{
Left: left,
Interval: interval,
Unwrap: u,
@ -1330,31 +1339,18 @@ func IsLogicalBinOp(op string) bool {
}
}
// SampleExpr is a LogQL expression filtering logs and returning metric samples.
//
//sumtype:decl
type SampleExpr interface {
// Selector is the LogQL selector to apply when retrieving logs.
Selector() (LogSelectorExpr, error)
Extractor() (SampleExtractor, error)
MatcherGroups() ([]MatcherRange, error)
Expr
isSampleExpr()
}
// RangeAggregationExpr not all range vector aggregation expressions support grouping by/without label(s),
// therefore the Grouping struct can be nil.
type RangeAggregationExpr struct {
Left *LogRange
Left *LogRangeExpr
Operation string
Params *float64
Grouping *Grouping
err error
implicit
}
func newRangeAggregationExpr(left *LogRange, operation string, gr *Grouping, stringParams *string) SampleExpr {
func newRangeAggregationExpr(left *LogRangeExpr, operation string, gr *Grouping, stringParams *string) SampleExpr {
var params *float64
if stringParams != nil {
if operation != OpRangeTypeQuantile && operation != OpRangeTypeQuantileSketch {
@ -1383,7 +1379,6 @@ func newRangeAggregationExpr(left *LogRange, operation string, gr *Grouping, str
}
return e
}
func (e *RangeAggregationExpr) isSampleExpr() {}
func (e *RangeAggregationExpr) Selector() (LogSelectorExpr, error) {
if e.err != nil {
@ -1529,7 +1524,6 @@ type VectorAggregationExpr struct {
Params int `json:"params"`
Operation string `json:"operation"`
err error
implicit
}
func mustNewVectorAggregationExpr(left SampleExpr, operation string, gr *Grouping, params *string) SampleExpr {
@ -1567,8 +1561,6 @@ func mustNewVectorAggregationExpr(left SampleExpr, operation string, gr *Groupin
}
}
func (e *VectorAggregationExpr) isSampleExpr() {}
func (e *VectorAggregationExpr) MatcherGroups() ([]MatcherRange, error) {
if e.err != nil {
return nil, e.err
@ -2113,7 +2105,6 @@ func MergeBinOp(op string, left, right *promql.Sample, swap, filter, isVectorCom
type LiteralExpr struct {
Val float64 `json:"val"`
err error
implicit
}
func mustNewLiteralExpr(s string, invert bool) *LiteralExpr {
@ -2139,8 +2130,6 @@ func (e *LiteralExpr) String() string {
// literlExpr impls SampleExpr & LogSelectorExpr mainly to reduce the need for more complicated typings
// to facilitate sum types. We'll be type switching when evaluating them anyways
// and they will only be present in binary operation legs.
func (e *LiteralExpr) isSampleExpr() {}
func (e *LiteralExpr) isLogSelectorExpr() {}
func (e *LiteralExpr) Selector() (LogSelectorExpr, error) { return e, e.err }
func (e *LiteralExpr) HasFilter() bool { return false }
func (e *LiteralExpr) Shardable(_ bool) bool { return true }
@ -2186,8 +2175,6 @@ type LabelReplaceExpr struct {
Regex string
Re *regexp.Regexp
err error
implicit
}
func mustNewLabelReplaceExpr(left SampleExpr, dst, replacement, src, regex string) *LabelReplaceExpr {
@ -2207,8 +2194,6 @@ func mustNewLabelReplaceExpr(left SampleExpr, dst, replacement, src, regex strin
}
}
func (e *LabelReplaceExpr) isSampleExpr() {}
func (e *LabelReplaceExpr) Selector() (LogSelectorExpr, error) {
if e.err != nil {
return nil, e.err
@ -2334,7 +2319,6 @@ func MatcherGroups(expr Expr) ([]MatcherRange, error) {
type VectorExpr struct {
Val float64
err error
implicit
}
func NewVectorExpr(scalar string) *VectorExpr {
@ -2348,9 +2332,6 @@ func NewVectorExpr(scalar string) *VectorExpr {
}
}
func (e *VectorExpr) isSampleExpr() {}
func (e *VectorExpr) isLogSelectorExpr() {}
func (e *VectorExpr) Err() error {
return e.err
}

@ -636,7 +636,7 @@ func TestOrLineFilterTypes(t *testing.T) {
left := &LineFilterExpr{LineFilter: LineFilter{Ty: tt.ty, Match: "something"}}
right := &LineFilterExpr{LineFilter: LineFilter{Ty: log.LineMatchEqual, Match: "something"}}
_ = newOrLineFilter(left, right)
_ = newOrLineFilterExpr(left, right)
require.Equal(t, tt.ty, right.Ty)
require.Equal(t, tt.ty, left.Ty)
})
@ -646,7 +646,7 @@ func TestOrLineFilterTypes(t *testing.T) {
f2 := &LineFilterExpr{LineFilter: LineFilter{Ty: log.LineMatchEqual, Match: "something"}}
f3 := &LineFilterExpr{LineFilter: LineFilter{Ty: log.LineMatchEqual, Match: "something"}}
_ = newOrLineFilter(f1, newOrLineFilter(f2, f3))
_ = newOrLineFilterExpr(f1, newOrLineFilterExpr(f2, f3))
require.Equal(t, tt.ty, f1.Ty)
require.Equal(t, tt.ty, f2.Ty)
require.Equal(t, tt.ty, f3.Ty)
@ -887,7 +887,7 @@ func Test_parserExpr_Parser(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var e *LabelParserExpr
var e *LineParserExpr
if tt.wantPanic {
require.Panics(t, func() { e = newLabelParserExpr(tt.op, tt.param) })
return
@ -923,7 +923,7 @@ func Test_parserExpr_String(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := LabelParserExpr{
l := LineParserExpr{
Op: tt.op,
Param: tt.param,
}

@ -66,7 +66,7 @@ func (v *cloneVisitor) VisitVectorAggregation(e *VectorAggregationExpr) {
func (v *cloneVisitor) VisitRangeAggregation(e *RangeAggregationExpr) {
copied := &RangeAggregationExpr{
Left: MustClone[*LogRange](e.Left),
Left: MustClone[*LogRangeExpr](e.Left),
Operation: e.Operation,
}
@ -95,8 +95,8 @@ func (v *cloneVisitor) VisitVector(e *VectorExpr) {
v.cloned = &VectorExpr{Val: e.Val}
}
func (v *cloneVisitor) VisitLogRange(e *LogRange) {
copied := &LogRange{
func (v *cloneVisitor) VisitLogRange(e *LogRangeExpr) {
copied := &LogRangeExpr{
Left: MustClone[LogSelectorExpr](e.Left),
Interval: e.Interval,
Offset: e.Offset,
@ -146,21 +146,21 @@ func (v *cloneVisitor) VisitDecolorize(*DecolorizeExpr) {
func (v *cloneVisitor) VisitDropLabels(e *DropLabelsExpr) {
copied := &DropLabelsExpr{
dropLabels: make([]log.DropLabel, len(e.dropLabels)),
dropLabels: make([]log.NamedLabelMatcher, len(e.dropLabels)),
}
for i, l := range e.dropLabels {
var matcher *labels.Matcher
if l.Matcher != nil {
matcher = labels.MustNewMatcher(l.Matcher.Type, l.Matcher.Name, l.Matcher.Value)
}
copied.dropLabels[i] = log.NewDropLabel(matcher, l.Name)
copied.dropLabels[i] = log.NewNamedLabelMatcher(matcher, l.Name)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitJSONExpressionParser(e *JSONExpressionParser) {
copied := &JSONExpressionParser{
func (v *cloneVisitor) VisitJSONExpressionParser(e *JSONExpressionParserExpr) {
copied := &JSONExpressionParserExpr{
Expressions: make([]log.LabelExtractionExpr, len(e.Expressions)),
}
copy(copied.Expressions, e.Expressions)
@ -170,10 +170,10 @@ func (v *cloneVisitor) VisitJSONExpressionParser(e *JSONExpressionParser) {
func (v *cloneVisitor) VisitKeepLabel(e *KeepLabelsExpr) {
copied := &KeepLabelsExpr{
keepLabels: make([]log.KeepLabel, len(e.keepLabels)),
keepLabels: make([]log.NamedLabelMatcher, len(e.keepLabels)),
}
for i, k := range e.keepLabels {
copied.keepLabels[i] = log.KeepLabel{
copied.keepLabels[i] = log.NamedLabelMatcher{
Name: k.Name,
}
if k.Matcher != nil {
@ -251,8 +251,8 @@ func (v *cloneVisitor) VisitLabelFmt(e *LabelFmtExpr) {
v.cloned = copied
}
func (v *cloneVisitor) VisitLabelParser(e *LabelParserExpr) {
v.cloned = &LabelParserExpr{
func (v *cloneVisitor) VisitLabelParser(e *LineParserExpr) {
v.cloned = &LineParserExpr{
Op: e.Op,
Param: e.Param,
}
@ -283,8 +283,8 @@ func (v *cloneVisitor) VisitLineFmt(e *LineFmtExpr) {
v.cloned = &LineFmtExpr{Value: e.Value}
}
func (v *cloneVisitor) VisitLogfmtExpressionParser(e *LogfmtExpressionParser) {
copied := &LogfmtExpressionParser{
func (v *cloneVisitor) VisitLogfmtExpressionParser(e *LogfmtExpressionParserExpr) {
copied := &LogfmtExpressionParserExpr{
Expressions: make([]log.LabelExtractionExpr, len(e.Expressions)),
Strict: e.Strict,
KeepEmpty: e.KeepEmpty,

File diff suppressed because it is too large Load Diff

@ -138,7 +138,7 @@ type lexer struct {
builder strings.Builder
}
func (l *lexer) Lex(lval *exprSymType) int {
func (l *lexer) Lex(lval *syntaxSymType) int {
r := l.Scan()
switch r {
@ -158,7 +158,7 @@ func (l *lexer) Lex(lval *exprSymType) int {
duration, ok := tryScanDuration(numberText, &l.Scanner)
if ok {
lval.duration = duration
lval.dur = duration
return DURATION
}
@ -174,13 +174,13 @@ func (l *lexer) Lex(lval *exprSymType) int {
if l.Peek() == '-' {
if flag, ok := tryScanFlag(&l.Scanner); ok {
lval.str = flag
return PARSER_FLAG
return FUNCTION_FLAG
}
}
tokenText := l.TokenText()
if duration, ok := tryScanDuration(tokenText, &l.Scanner); ok {
lval.duration = duration
lval.dur = duration
return DURATION
}
@ -209,7 +209,7 @@ func (l *lexer) Lex(lval *exprSymType) int {
l.Error(err.Error())
return 0
}
lval.duration = time.Duration(i)
lval.dur = time.Duration(i)
return RANGE
}
_, _ = l.builder.WriteRune(r)

@ -77,13 +77,13 @@ func TestLex(t *testing.T) {
{`{foo="bar"} #|~ "\\w+"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE}},
{`#{foo="bar"} |~ "\\w+"`, []int{}},
{`{foo="#"}`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE}},
{`{foo="bar"}|logfmt --strict"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PARSER_FLAG}},
{`{foo="bar"}|LOGFMT --strict"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PARSER_FLAG}},
{`{foo="bar"}|logfmt --strict"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, FUNCTION_FLAG}},
{`{foo="bar"}|LOGFMT --strict"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, FUNCTION_FLAG}},
{`{foo="bar"}|logfmt|ip="b"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PIPE, IDENTIFIER, EQ, STRING}},
{`{foo="bar"}|logfmt|rate="b"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PIPE, IDENTIFIER, EQ, STRING}},
{`{foo="bar"}|logfmt|b=ip("b")`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PIPE, IDENTIFIER, EQ, IP, OPEN_PARENTHESIS, STRING, CLOSE_PARENTHESIS}},
{`{foo="bar"}|logfmt|=ip("b")`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PIPE_EXACT, IP, OPEN_PARENTHESIS, STRING, CLOSE_PARENTHESIS}},
{`{foo="bar"}|logfmt --strict --keep-empty|=ip("b")`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PARSER_FLAG, PARSER_FLAG, PIPE_EXACT, IP, OPEN_PARENTHESIS, STRING, CLOSE_PARENTHESIS}},
{`{foo="bar"}|logfmt --strict --keep-empty|=ip("b")`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, FUNCTION_FLAG, FUNCTION_FLAG, PIPE_EXACT, IP, OPEN_PARENTHESIS, STRING, CLOSE_PARENTHESIS}},
{`ip`, []int{IDENTIFIER}},
{`rate`, []int{IDENTIFIER}},
{`{foo="bar"} | json | baz="#"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, JSON, PIPE, IDENTIFIER, EQ, STRING}},
@ -92,8 +92,8 @@ func TestLex(t *testing.T) {
| json`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, JSON}},
{`{foo="bar"} | json code="response.code", param="request.params[0]"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, JSON, IDENTIFIER, EQ, STRING, COMMA, IDENTIFIER, EQ, STRING}},
{`{foo="bar"} | logfmt code="response.code", IPAddress="host"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, IDENTIFIER, EQ, STRING, COMMA, IDENTIFIER, EQ, STRING}},
{`{foo="bar"} | logfmt --strict code"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PARSER_FLAG, IDENTIFIER}},
{`{foo="bar"} | logfmt --keep-empty --strict code="response.code", IPAddress="host"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, PARSER_FLAG, PARSER_FLAG, IDENTIFIER, EQ, STRING, COMMA, IDENTIFIER, EQ, STRING}},
{`{foo="bar"} | logfmt --strict code"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, FUNCTION_FLAG, IDENTIFIER}},
{`{foo="bar"} | logfmt --keep-empty --strict code="response.code", IPAddress="host"`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE, PIPE, LOGFMT, FUNCTION_FLAG, FUNCTION_FLAG, IDENTIFIER, EQ, STRING, COMMA, IDENTIFIER, EQ, STRING}},
{`decolorize`, []int{DECOLORIZE}},
{`123`, []int{NUMBER}},
{`-123`, []int{SUB, NUMBER}},
@ -121,7 +121,7 @@ func TestLex(t *testing.T) {
},
}
l.Init(strings.NewReader(tc.input))
var lval exprSymType
var lval syntaxSymType
for {
tok := l.Lex(&lval)
if tok == 0 {

@ -23,7 +23,7 @@ const (
var parserPool = sync.Pool{
New: func() interface{} {
p := &parser{
p: &exprParserImpl{},
p: &syntaxParserImpl{},
Reader: strings.NewReader(""),
lexer: &lexer{},
}
@ -41,16 +41,16 @@ const maxInputSize = 131072
func init() {
// Improve the error messages coming out of yacc.
exprErrorVerbose = true
syntaxErrorVerbose = true
// uncomment when you need to understand yacc rule tree.
// exprDebug = 3
for str, tok := range tokens {
exprToknames[tok-exprPrivate+1] = str
syntaxToknames[tok-syntaxPrivate+1] = str
}
}
type parser struct {
p *exprParserImpl
p *syntaxParserImpl
*lexer
expr Expr
*strings.Reader

@ -26,7 +26,7 @@ var ParseTestCases = []struct {
in: "count_over_time({foo=~`bar\\w+`}[12h] |~ `error\\`)",
exp: &RangeAggregationExpr{
Operation: "count_over_time",
Left: &LogRange{
Left: &LogRangeExpr{
Left: &PipelineExpr{
MultiStages: MultiStageExpr{
newLineFilterExpr(log.LineMatchRegexp, "", "error\\"),
@ -55,7 +55,7 @@ var ParseTestCases = []struct {
in: `count_over_time({foo="bar"}[12h] |= "error")`,
exp: &RangeAggregationExpr{
Operation: "count_over_time",
Left: &LogRange{
Left: &LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "foo", Value: "bar"}}),
MultiStageExpr{
@ -71,7 +71,7 @@ var ParseTestCases = []struct {
in: `count_over_time({foo="bar"} |= "error" [12h])`,
exp: &RangeAggregationExpr{
Operation: "count_over_time",
Left: &LogRange{
Left: &LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "foo", Value: "bar"}}),
MultiStageExpr{newLineFilterExpr(log.LineMatchEqual, "", "error")},
@ -109,7 +109,7 @@ var ParseTestCases = []struct {
{
in: `count_over_time({ foo = "bar" }[12m])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -119,7 +119,7 @@ var ParseTestCases = []struct {
{
in: `bytes_over_time({ foo = "bar" }[12m])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -129,7 +129,7 @@ var ParseTestCases = []struct {
{
in: `bytes_rate({ foo = "bar" }[12m])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -139,7 +139,7 @@ var ParseTestCases = []struct {
{
in: `rate({ foo = "bar" }[5h])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -188,7 +188,7 @@ var ParseTestCases = []struct {
{
in: `rate({ foo = "bar" }[5d])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * 24 * time.Hour,
},
@ -198,7 +198,7 @@ var ParseTestCases = []struct {
{
in: `count_over_time({ foo = "bar" }[1w])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 7 * 24 * time.Hour,
},
@ -208,7 +208,7 @@ var ParseTestCases = []struct {
{
in: `absent_over_time({ foo = "bar" }[1w])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 7 * 24 * time.Hour,
},
@ -218,7 +218,7 @@ var ParseTestCases = []struct {
{
in: `sum(rate({ foo = "bar" }[5h]))`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -228,7 +228,7 @@ var ParseTestCases = []struct {
{
in: `sum(rate({ foo ="bar" }[1y]))`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 365 * 24 * time.Hour,
},
@ -238,7 +238,7 @@ var ParseTestCases = []struct {
{
in: `avg(count_over_time({ foo = "bar" }[5h])) by (bar,foo)`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -261,7 +261,7 @@ var ParseTestCases = []struct {
exp: mustNewVectorAggregationExpr(
mustNewLabelReplaceExpr(
&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -277,7 +277,7 @@ var ParseTestCases = []struct {
{
in: `avg(count_over_time({ foo = "bar" }[5h])) by ()`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -290,7 +290,7 @@ var ParseTestCases = []struct {
{
in: `max without (bar) (count_over_time({ foo = "bar" }[5h]))`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -303,7 +303,7 @@ var ParseTestCases = []struct {
{
in: `max without () (count_over_time({ foo = "bar" }[5h]))`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -316,7 +316,7 @@ var ParseTestCases = []struct {
{
in: `topk(10,count_over_time({ foo = "bar" }[5h])) without (bar)`,
exp: mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -329,7 +329,7 @@ var ParseTestCases = []struct {
{
in: `bottomk(30 ,sum(rate({ foo = "bar" }[5h])) by (foo))`,
exp: mustNewVectorAggregationExpr(mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -343,7 +343,7 @@ var ParseTestCases = []struct {
{
in: `max( sum(count_over_time({ foo = "bar" }[5h])) without (foo,bar) ) by (foo)`,
exp: mustNewVectorAggregationExpr(mustNewVectorAggregationExpr(&RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 5 * time.Hour,
},
@ -689,7 +689,7 @@ var ParseTestCases = []struct {
{
in: `count_over_time(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap")[5m])`,
exp: newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -711,7 +711,7 @@ var ParseTestCases = []struct {
{
in: `bytes_over_time(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap")[5m])`,
exp: newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -733,7 +733,7 @@ var ParseTestCases = []struct {
{
in: `bytes_over_time(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap" | unpack)[5m])`,
exp: newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -765,7 +765,7 @@ var ParseTestCases = []struct {
`,
exp: mustNewLabelReplaceExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -792,7 +792,7 @@ var ParseTestCases = []struct {
{
in: `sum(count_over_time(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap")[5m])) by (foo)`,
exp: mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -820,7 +820,7 @@ var ParseTestCases = []struct {
{
in: `sum(bytes_rate(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap")[5m])) by (foo)`,
exp: mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -848,7 +848,7 @@ var ParseTestCases = []struct {
{
in: `topk(5,count_over_time(({foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap")[5m])) without (foo)`,
exp: mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -878,7 +878,7 @@ var ParseTestCases = []struct {
exp: mustNewVectorAggregationExpr(
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -909,7 +909,7 @@ var ParseTestCases = []struct {
{
in: `count_over_time({foo="bar"}[5m] |= "baz" |~ "blip" != "flip" !~ "flap")`,
exp: newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -931,7 +931,7 @@ var ParseTestCases = []struct {
{
in: `sum(count_over_time({foo="bar"}[5m] |= "baz" |~ "blip" != "flip" !~ "flap")) by (foo)`,
exp: mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -959,7 +959,7 @@ var ParseTestCases = []struct {
{
in: `topk(5,count_over_time({foo="bar"}[5m] |= "baz" |~ "blip" != "flip" !~ "flap")) without (foo)`,
exp: mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -989,7 +989,7 @@ var ParseTestCases = []struct {
exp: mustNewVectorAggregationExpr(
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}),
MultiStageExpr{
@ -1057,7 +1057,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1073,7 +1073,7 @@ var ParseTestCases = []struct {
nil,
),
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1090,7 +1090,7 @@ var ParseTestCases = []struct {
),
),
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1124,7 +1124,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1140,7 +1140,7 @@ var ParseTestCases = []struct {
nil,
),
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1157,7 +1157,7 @@ var ParseTestCases = []struct {
),
),
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1187,7 +1187,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1208,7 +1208,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1224,7 +1224,7 @@ var ParseTestCases = []struct {
nil,
),
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -1254,7 +1254,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "namespace", "tns"),
@ -1265,7 +1265,7 @@ var ParseTestCases = []struct {
Interval: 5 * time.Minute,
}, OpRangeTypeCount, nil, nil),
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "namespace", "tns"),
@ -1288,7 +1288,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newPipelineExpr(
newMatcherExpr([]*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "namespace", "tns"),
@ -1299,7 +1299,7 @@ var ParseTestCases = []struct {
Interval: 5 * time.Minute,
}, OpRangeTypeCount, nil, nil),
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "namespace", "tns"),
@ -1320,7 +1320,7 @@ var ParseTestCases = []struct {
},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -2577,7 +2577,7 @@ var ParseTestCases = []struct {
exp: mustNewBinOpExpr(OpTypeGT, &BinOpOptions{ReturnBool: true, VectorMatching: &VectorMatching{Card: CardOneToMany, Include: []string{"app"}, On: true, MatchingLabels: nil}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
@ -2589,7 +2589,7 @@ var ParseTestCases = []struct {
),
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
@ -2608,7 +2608,7 @@ var ParseTestCases = []struct {
exp: mustNewBinOpExpr(OpTypeGT, &BinOpOptions{ReturnBool: true, VectorMatching: &VectorMatching{Card: CardOneToMany, Include: nil, On: true, MatchingLabels: nil}},
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
@ -2620,7 +2620,7 @@ var ParseTestCases = []struct {
),
mustNewVectorAggregationExpr(
newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: newMatcherExpr([]*labels.Matcher{{Type: labels.MatchEqual, Name: "app", Value: "foo"}}),
Interval: 1 * time.Minute,
},
@ -2794,14 +2794,14 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
Operation: "count_over_time",
},
RHS: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -2818,7 +2818,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -2841,7 +2841,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -2854,7 +2854,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
SampleExpr: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &MatchersExpr{Mts: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
Interval: 12 * time.Minute,
},
@ -3031,7 +3031,7 @@ var ParseTestCases = []struct {
{
in: `count_over_time({ foo ="bar" } | json layer7_something_specific="layer7_something_specific" [12m])`,
exp: &RangeAggregationExpr{
Left: &LogRange{
Left: &LogRangeExpr{
Left: &PipelineExpr{
MultiStages: MultiStageExpr{
newJSONExpressionParser([]log.LabelExtractionExpr{
@ -3057,7 +3057,7 @@ var ParseTestCases = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
mustNewVectorAggregationExpr(newRangeAggregationExpr(
&LogRange{
&LogRangeExpr{
Left: &MatchersExpr{
Mts: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
@ -3147,7 +3147,7 @@ var ParseTestCases = []struct {
Left: newMatcherExpr([]*labels.Matcher{mustNewMatcher(labels.MatchEqual, "app", "foo")}),
MultiStages: MultiStageExpr{
&LineFilterExpr{
Left: newOrLineFilter(
Left: newOrLineFilterExpr(
&LineFilterExpr{
LineFilter: LineFilter{
Ty: log.LineMatchEqual,
@ -3186,7 +3186,7 @@ var ParseTestCases = []struct {
Ty: log.LineMatchEqual,
Match: "foo",
},
Or: newOrLineFilter(
Or: newOrLineFilterExpr(
&LineFilterExpr{
LineFilter: LineFilter{
Ty: log.LineMatchEqual,
@ -3216,7 +3216,7 @@ var ParseTestCases = []struct {
Ty: log.LineMatchPattern,
Match: "foo",
},
Or: newOrLineFilter(
Or: newOrLineFilterExpr(
&LineFilterExpr{
LineFilter: LineFilter{
Ty: log.LineMatchPattern,

@ -109,7 +109,7 @@ func (e *LogfmtParserExpr) Pretty(level int) string {
// `| regexp`
// `| pattern`
// `| unpack`
func (e *LabelParserExpr) Pretty(level int) string {
func (e *LineParserExpr) Pretty(level int) string {
return commonPrefixIndent(level, e)
}
@ -142,12 +142,12 @@ func (e *LabelFmtExpr) Pretty(level int) string {
}
// e.g: | json label="expression", another="expression"
func (e *JSONExpressionParser) Pretty(level int) string {
func (e *JSONExpressionParserExpr) Pretty(level int) string {
return commonPrefixIndent(level, e)
}
// e.g: | logfmt label="expression", another="expression"
func (e *LogfmtExpressionParser) Pretty(level int) string {
func (e *LogfmtExpressionParserExpr) Pretty(level int) string {
return commonPrefixIndent(level, e)
}
@ -168,7 +168,7 @@ func (e *UnwrapExpr) Pretty(level int) string {
// e.g: `{foo="bar"}|logfmt[5m]`
// TODO(kavi): Rename `LogRange` -> `LogRangeExpr` (to be consistent with other expressions?)
func (e *LogRange) Pretty(level int) string {
func (e *LogRangeExpr) Pretty(level int) string {
s := e.Left.Pretty(level)
if e.Unwrap != nil {

@ -204,7 +204,7 @@ func (v *JSONSerializer) VisitRangeAggregation(e *RangeAggregationExpr) {
v.Flush()
}
func (v *JSONSerializer) VisitLogRange(e *LogRange) {
func (v *JSONSerializer) VisitLogRange(e *LogRangeExpr) {
v.WriteObjectStart()
v.WriteObjectField(IntervalNanos)
@ -306,17 +306,17 @@ func (v *JSONSerializer) VisitPipeline(e *PipelineExpr) {
// Below are StageExpr visitors that we are skipping since a pipeline is
// serialized as a string.
func (*JSONSerializer) VisitDecolorize(*DecolorizeExpr) {}
func (*JSONSerializer) VisitDropLabels(*DropLabelsExpr) {}
func (*JSONSerializer) VisitJSONExpressionParser(*JSONExpressionParser) {}
func (*JSONSerializer) VisitKeepLabel(*KeepLabelsExpr) {}
func (*JSONSerializer) VisitLabelFilter(*LabelFilterExpr) {}
func (*JSONSerializer) VisitLabelFmt(*LabelFmtExpr) {}
func (*JSONSerializer) VisitLabelParser(*LabelParserExpr) {}
func (*JSONSerializer) VisitLineFilter(*LineFilterExpr) {}
func (*JSONSerializer) VisitLineFmt(*LineFmtExpr) {}
func (*JSONSerializer) VisitLogfmtExpressionParser(*LogfmtExpressionParser) {}
func (*JSONSerializer) VisitLogfmtParser(*LogfmtParserExpr) {}
func (*JSONSerializer) VisitDecolorize(*DecolorizeExpr) {}
func (*JSONSerializer) VisitDropLabels(*DropLabelsExpr) {}
func (*JSONSerializer) VisitJSONExpressionParser(*JSONExpressionParserExpr) {}
func (*JSONSerializer) VisitKeepLabel(*KeepLabelsExpr) {}
func (*JSONSerializer) VisitLabelFilter(*LabelFilterExpr) {}
func (*JSONSerializer) VisitLabelFmt(*LabelFmtExpr) {}
func (*JSONSerializer) VisitLabelParser(*LineParserExpr) {}
func (*JSONSerializer) VisitLineFilter(*LineFilterExpr) {}
func (*JSONSerializer) VisitLineFmt(*LineFmtExpr) {}
func (*JSONSerializer) VisitLogfmtExpressionParser(*LogfmtExpressionParserExpr) {}
func (*JSONSerializer) VisitLogfmtParser(*LogfmtParserExpr) {}
func encodeGrouping(s *jsoniter.Stream, g *Grouping) {
s.WriteObjectStart()
@ -858,8 +858,8 @@ func decodeRangeAgg(iter *jsoniter.Iterator) (*RangeAggregationExpr, error) {
return expr, err
}
func decodeLogRange(iter *jsoniter.Iterator) (*LogRange, error) {
expr := &LogRange{}
func decodeLogRange(iter *jsoniter.Iterator) (*LogRangeExpr, error) {
expr := &LogRangeExpr{}
var err error
for f := iter.ReadObject(); f != ""; f = iter.ReadObject() {

@ -5,142 +5,82 @@ import (
"time"
"github.com/prometheus/prometheus/model/labels"
"github.com/grafana/loki/v3/pkg/logql/log"
)
%}
%union{
Expr Expr
Filter log.LineMatchType
Grouping *Grouping
Labels []string
LogExpr LogSelectorExpr
LogRangeExpr *LogRange
Matcher *labels.Matcher
Matchers []*labels.Matcher
RangeAggregationExpr SampleExpr
RangeOp string
ConvOp string
Selector []*labels.Matcher
VectorAggregationExpr SampleExpr
VectorExpr *VectorExpr
Vector string
MetricExpr SampleExpr
VectorOp string
FilterOp string
BinOpExpr SampleExpr
LabelReplaceExpr SampleExpr
binOp string
bytes uint64
str string
duration time.Duration
LiteralExpr *LiteralExpr
BinOpModifier *BinOpOptions
BoolModifier *BinOpOptions
OnOrIgnoringModifier *BinOpOptions
LabelParser *LabelParserExpr
LogfmtParser *LogfmtParserExpr
LineFilters *LineFilterExpr
LineFilter *LineFilterExpr
OrFilter *LineFilterExpr
ParserFlags []string
PipelineExpr MultiStageExpr
PipelineStage StageExpr
BytesFilter log.LabelFilterer
NumberFilter log.LabelFilterer
DurationFilter log.LabelFilterer
LabelFilter log.LabelFilterer
UnitFilter log.LabelFilterer
IPLabelFilter log.LabelFilterer
LineFormatExpr *LineFmtExpr
LabelFormatExpr *LabelFmtExpr
LabelFormat log.LabelFmt
LabelsFormat []log.LabelFmt
LabelExtractionExpression log.LabelExtractionExpr
LabelExtractionExpressionList []log.LabelExtractionExpr
JSONExpressionParser *JSONExpressionParser
LogfmtExpressionParser *LogfmtExpressionParser
UnwrapExpr *UnwrapExpr
DecolorizeExpr *DecolorizeExpr
OffsetExpr *OffsetExpr
DropLabel log.DropLabel
DropLabels []log.DropLabel
DropLabelsExpr *DropLabelsExpr
KeepLabel log.KeepLabel
KeepLabels []log.KeepLabel
KeepLabelsExpr *KeepLabelsExpr
val interface{}
bytes uint64
dur time.Duration
op string
binOp string
str string
strs []string
expr Expr
logExpr LogSelectorExpr
metricExpr SampleExpr
matcher *labels.Matcher
matchers []*labels.Matcher
stage StageExpr
stages MultiStageExpr
filterer log.LabelFilterer
filter log.LineMatchType
lineFilterExpr *LineFilterExpr
binOpts *BinOpOptions
namedMatcher log.NamedLabelMatcher
namedMatchers []log.NamedLabelMatcher
labelFormat log.LabelFmt
labelsFormat []log.LabelFmt
grouping *Grouping
logRangeExpr *LogRangeExpr
literalExpr *LiteralExpr
labelFormatExpr *LabelFmtExpr
labelExtractionExpression log.LabelExtractionExpr
labelExtractionExpressionList []log.LabelExtractionExpr
unwrapExpr *UnwrapExpr
offsetExpr *OffsetExpr
}
%start root
%type <Expr> expr
%type <Filter> filter
%type <Grouping> grouping
%type <Labels> labels
%type <LogExpr> logExpr
%type <MetricExpr> metricExpr
%type <LogRangeExpr> logRangeExpr
%type <Matcher> matcher
%type <Matchers> matchers
%type <RangeAggregationExpr> rangeAggregationExpr
%type <RangeOp> rangeOp
%type <ConvOp> convOp
%type <Selector> selector
%type <VectorAggregationExpr> vectorAggregationExpr
%type <VectorOp> vectorOp
%type <VectorExpr> vectorExpr
%type <Vector> vector
%type <FilterOp> filterOp
%type <BinOpExpr> binOpExpr
%type <LiteralExpr> literalExpr
%type <LabelReplaceExpr> labelReplaceExpr
%type <BinOpModifier> binOpModifier
%type <BoolModifier> boolModifier
%type <OnOrIgnoringModifier> onOrIgnoringModifier
%type <LabelParser> labelParser
%type <LogfmtParser> logfmtParser
%type <PipelineExpr> pipelineExpr
%type <PipelineStage> pipelineStage
%type <BytesFilter> bytesFilter
%type <NumberFilter> numberFilter
%type <DurationFilter> durationFilter
%type <LabelFilter> labelFilter
%type <LineFilters> lineFilters
%type <LineFilter> lineFilter
%type <OrFilter> orFilter
%type <ParserFlags> parserFlags
%type <LineFormatExpr> lineFormatExpr
%type <DecolorizeExpr> decolorizeExpr
%type <DropLabelsExpr> dropLabelsExpr
%type <DropLabels> dropLabels
%type <DropLabel> dropLabel
%type <KeepLabelsExpr> keepLabelsExpr
%type <KeepLabels> keepLabels
%type <KeepLabel> keepLabel
%type <LabelFormatExpr> labelFormatExpr
%type <LabelFormat> labelFormat
%type <LabelsFormat> labelsFormat
%type <LabelExtractionExpression> labelExtractionExpression
%type <LabelExtractionExpressionList> labelExtractionExpressionList
%type <LogfmtExpressionParser> logfmtExpressionParser
%type <JSONExpressionParser> jsonExpressionParser
%type <UnwrapExpr> unwrapExpr
%type <UnitFilter> unitFilter
%type <IPLabelFilter> ipLabelFilter
%type <OffsetExpr> offsetExpr
%type <expr> expr
%type <logExpr> logExpr
%type <metricExpr> metricExpr rangeAggregationExpr vectorAggregationExpr binOpExpr labelReplaceExpr vectorExpr
%type <stage> pipelineStage logfmtParser labelParser jsonExpressionParser logfmtExpressionParser lineFormatExpr decolorizeExpr labelFormatExpr dropLabelsExpr keepLabelsExpr
%type <stages> pipelineExpr
%type <lineFilterExpr> lineFilter lineFilters orFilter
%type <op> rangeOp convOp vectorOp filterOp
%type <filterer> bytesFilter numberFilter durationFilter labelFilter unitFilter ipLabelFilter
%type <filter> filter
%type <matcher> matcher
%type <matchers> matchers selector
%type <str> vector
%type <strs> labels parserFlags
%type <binOpts> binOpModifier boolModifier onOrIgnoringModifier
%type <namedMatcher> namedMatcher
%type <namedMatchers> namedMatchers
%type <labelFormat> labelFormat
%type <labelsFormat> labelsFormat
%type <grouping> grouping
%type <logRangeExpr> logRangeExpr
%type <literalExpr> literalExpr
%type <labelExtractionExpression> labelExtractionExpression
%type <labelExtractionExpressionList> labelExtractionExpressionList
%type <unwrapExpr> unwrapExpr
%type <offsetExpr> offsetExpr
%token <bytes> BYTES
%token <str> IDENTIFIER STRING NUMBER PARSER_FLAG
%token <duration> DURATION RANGE
%token <val> 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 APPROX_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 VECTOR LABEL_REPLACE UNPACK OFFSET PATTERN IP ON IGNORING GROUP_LEFT GROUP_RIGHT
DECOLORIZE DROP KEEP
%token <str> IDENTIFIER STRING NUMBER FUNCTION_FLAG
%token <dur> DURATION RANGE
%token <val> 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 APPROX_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 VECTOR LABEL_REPLACE UNPACK OFFSET PATTERN IP ON IGNORING GROUP_LEFT GROUP_RIGHT
DECOLORIZE DROP KEEP
// Operators are listed with increasing precedence.
%left <binOp> OR
@ -152,11 +92,18 @@ import (
%%
root: expr { exprlex.(*parser).expr = $1 };
root:
expr { syntaxlex.(*parser).expr = $1 };
expr:
logExpr { $$ = $1 }
| metricExpr { $$ = $1 }
logExpr { $$ = $1 }
| metricExpr { $$ = $1 }
;
logExpr:
selector { $$ = newMatcherExpr($1)}
| selector pipelineExpr { $$ = newPipelineExpr(newMatcherExpr($1), $2)}
| OPEN_PARENTHESIS logExpr CLOSE_PARENTHESIS { $$ = $2 }
;
metricExpr:
@ -169,12 +116,6 @@ metricExpr:
| OPEN_PARENTHESIS metricExpr CLOSE_PARENTHESIS { $$ = $2 }
;
logExpr:
selector { $$ = newMatcherExpr($1)}
| selector pipelineExpr { $$ = newPipelineExpr(newMatcherExpr($1), $2)}
| OPEN_PARENTHESIS logExpr CLOSE_PARENTHESIS { $$ = $2 }
;
logRangeExpr:
selector RANGE { $$ = newLogRange(newMatcherExpr($1), $2, nil, nil ) }
| selector RANGE offsetExpr { $$ = newLogRange(newMatcherExpr($1), $2, nil, $3 ) }
@ -239,15 +180,6 @@ labelReplaceExpr:
{ $$ = mustNewLabelReplaceExpr($3, $5, $7, $9, $11)}
;
filter:
PIPE_MATCH { $$ = log.LineMatchRegexp }
| PIPE_EXACT { $$ = log.LineMatchEqual }
| PIPE_PATTERN { $$ = log.LineMatchPattern }
| NRE { $$ = log.LineMatchNotRegexp }
| NEQ { $$ = log.LineMatchNotEqual }
| NPA { $$ = log.LineMatchNotPattern }
;
selector:
OPEN_BRACE matchers CLOSE_BRACE { $$ = $2 }
| OPEN_BRACE matchers error { $$ = $2 }
@ -285,31 +217,39 @@ pipelineStage:
| PIPE keepLabelsExpr { $$ = $2 }
;
filter:
PIPE_MATCH { $$ = log.LineMatchRegexp }
| PIPE_EXACT { $$ = log.LineMatchEqual }
| PIPE_PATTERN { $$ = log.LineMatchPattern }
| NRE { $$ = log.LineMatchNotRegexp }
| NEQ { $$ = log.LineMatchNotEqual }
| NPA { $$ = log.LineMatchNotPattern }
;
filterOp:
IP { $$ = OpFilterIP }
;
orFilter:
STRING { $$ = newLineFilterExpr(log.LineMatchEqual, "", $1) }
| filterOp OPEN_PARENTHESIS STRING CLOSE_PARENTHESIS { $$ = newLineFilterExpr(log.LineMatchEqual, $1, $3) }
| STRING OR orFilter { $$ = newOrLineFilter(newLineFilterExpr(log.LineMatchEqual, "", $1), $3) }
STRING { $$ = newLineFilterExpr(log.LineMatchEqual, "", $1) }
| STRING OR orFilter { $$ = newOrLineFilterExpr(newLineFilterExpr(log.LineMatchEqual, "", $1), $3) }
| filterOp OPEN_PARENTHESIS STRING CLOSE_PARENTHESIS { $$ = newLineFilterExpr(log.LineMatchEqual, $1, $3) }
;
lineFilter:
filter STRING { $$ = newLineFilterExpr($1, "", $2) }
| filter filterOp OPEN_PARENTHESIS STRING CLOSE_PARENTHESIS { $$ = newLineFilterExpr($1, $2, $4) }
| filter STRING OR orFilter { $$ = newOrLineFilter(newLineFilterExpr($1, "", $2), $4) }
filter STRING { $$ = newLineFilterExpr($1, "", $2) }
| filter filterOp OPEN_PARENTHESIS STRING CLOSE_PARENTHESIS { $$ = newLineFilterExpr($1, $2, $4) }
| lineFilter OR orFilter { $$ = newOrLineFilterExpr($1, $3) }
;
lineFilters:
lineFilter { $$ = $1 }
| lineFilter OR orFilter { $$ = newOrLineFilter($1, $3)}
| lineFilters lineFilter { $$ = newNestedLineFilterExpr($1, $2) }
lineFilter { $$ = $1 }
| lineFilters lineFilter { $$ = newNestedLineFilterExpr($1, $2) }
;
parserFlags:
PARSER_FLAG { $$ = []string{ $1 } }
| parserFlags PARSER_FLAG { $$ = append($1, $2) }
FUNCTION_FLAG { $$ = []string{ $1 } }
| parserFlags FUNCTION_FLAG { $$ = append($1, $2) }
;
logfmtParser:
@ -410,27 +350,18 @@ numberFilter:
| IDENTIFIER CMP_EQ literalExpr { $$ = log.NewNumericLabelFilter(log.LabelFilterEqual, $1, $3.Val)}
;
dropLabel:
IDENTIFIER { $$ = log.NewDropLabel(nil, $1) }
| matcher { $$ = log.NewDropLabel($1, "") }
namedMatcher:
IDENTIFIER { $$ = log.NewNamedLabelMatcher(nil, $1) }
| matcher { $$ = log.NewNamedLabelMatcher($1, "") }
dropLabels:
dropLabel { $$ = []log.DropLabel{$1}}
| dropLabels COMMA dropLabel { $$ = append($1, $3) }
namedMatchers:
namedMatcher { $$ = []log.NamedLabelMatcher{$1} }
| namedMatchers COMMA namedMatcher { $$ = append($1, $3) }
;
dropLabelsExpr: DROP dropLabels { $$ = newDropLabelsExpr($2) }
keepLabel:
IDENTIFIER { $$ = log.NewKeepLabel(nil, $1) }
| matcher { $$ = log.NewKeepLabel($1, "") }
keepLabels:
keepLabel { $$ = []log.KeepLabel{$1}}
| keepLabels COMMA keepLabel { $$ = append($1, $3) }
;
dropLabelsExpr: DROP namedMatchers { $$ = newDropLabelsExpr($2) }
keepLabelsExpr: KEEP keepLabels { $$ = newKeepLabelsExpr($2) }
keepLabelsExpr: KEEP namedMatchers { $$ = newKeepLabelsExpr($2) }
// Operator precedence only works if each of these is listed separately.
binOpExpr:

File diff suppressed because it is too large Load Diff

@ -44,7 +44,7 @@ func removeFastRegexMatcherFromExpr(expr Expr) Expr {
typed.Mts = RemoveFastRegexMatchers(typed.Mts)
case *LabelFilterExpr:
typed.LabelFilterer = removeFastRegexMatcherFromLabelFilterer(typed.LabelFilterer)
case *LogRange:
case *LogRangeExpr:
if typed.Unwrap == nil {
return
}

@ -9,7 +9,7 @@ type RootVisitor interface {
LogSelectorExprVisitor
StageExprVisitor
VisitLogRange(*LogRange)
VisitLogRange(*LogRangeExpr)
}
type SampleExprVisitor interface {
@ -31,14 +31,14 @@ type LogSelectorExprVisitor interface {
type StageExprVisitor interface {
VisitDecolorize(*DecolorizeExpr)
VisitDropLabels(*DropLabelsExpr)
VisitJSONExpressionParser(*JSONExpressionParser)
VisitJSONExpressionParser(*JSONExpressionParserExpr)
VisitKeepLabel(*KeepLabelsExpr)
VisitLabelFilter(*LabelFilterExpr)
VisitLabelFmt(*LabelFmtExpr)
VisitLabelParser(*LabelParserExpr)
VisitLabelParser(*LineParserExpr)
VisitLineFilter(*LineFilterExpr)
VisitLineFmt(*LineFmtExpr)
VisitLogfmtExpressionParser(*LogfmtExpressionParser)
VisitLogfmtExpressionParser(*LogfmtExpressionParserExpr)
VisitLogfmtParser(*LogfmtParserExpr)
}
@ -48,17 +48,17 @@ type DepthFirstTraversal struct {
VisitBinOpFn func(v RootVisitor, e *BinOpExpr)
VisitDecolorizeFn func(v RootVisitor, e *DecolorizeExpr)
VisitDropLabelsFn func(v RootVisitor, e *DropLabelsExpr)
VisitJSONExpressionParserFn func(v RootVisitor, e *JSONExpressionParser)
VisitJSONExpressionParserFn func(v RootVisitor, e *JSONExpressionParserExpr)
VisitKeepLabelFn func(v RootVisitor, e *KeepLabelsExpr)
VisitLabelFilterFn func(v RootVisitor, e *LabelFilterExpr)
VisitLabelFmtFn func(v RootVisitor, e *LabelFmtExpr)
VisitLabelParserFn func(v RootVisitor, e *LabelParserExpr)
VisitLabelParserFn func(v RootVisitor, e *LineParserExpr)
VisitLabelReplaceFn func(v RootVisitor, e *LabelReplaceExpr)
VisitLineFilterFn func(v RootVisitor, e *LineFilterExpr)
VisitLineFmtFn func(v RootVisitor, e *LineFmtExpr)
VisitLiteralFn func(v RootVisitor, e *LiteralExpr)
VisitLogRangeFn func(v RootVisitor, e *LogRange)
VisitLogfmtExpressionParserFn func(v RootVisitor, e *LogfmtExpressionParser)
VisitLogRangeFn func(v RootVisitor, e *LogRangeExpr)
VisitLogfmtExpressionParserFn func(v RootVisitor, e *LogfmtExpressionParserExpr)
VisitLogfmtParserFn func(v RootVisitor, e *LogfmtParserExpr)
VisitMatchersFn func(v RootVisitor, e *MatchersExpr)
VisitPipelineFn func(v RootVisitor, e *PipelineExpr)
@ -101,7 +101,7 @@ func (v *DepthFirstTraversal) VisitDropLabels(e *DropLabelsExpr) {
}
// VisitJSONExpressionParser implements RootVisitor.
func (v *DepthFirstTraversal) VisitJSONExpressionParser(e *JSONExpressionParser) {
func (v *DepthFirstTraversal) VisitJSONExpressionParser(e *JSONExpressionParserExpr) {
if e == nil {
return
}
@ -141,7 +141,7 @@ func (v *DepthFirstTraversal) VisitLabelFmt(e *LabelFmtExpr) {
}
// VisitLabelParser implements RootVisitor.
func (v *DepthFirstTraversal) VisitLabelParser(e *LabelParserExpr) {
func (v *DepthFirstTraversal) VisitLabelParser(e *LineParserExpr) {
if e == nil {
return
}
@ -198,7 +198,7 @@ func (v *DepthFirstTraversal) VisitLiteral(e *LiteralExpr) {
}
// VisitLogRange implements RootVisitor.
func (v *DepthFirstTraversal) VisitLogRange(e *LogRange) {
func (v *DepthFirstTraversal) VisitLogRange(e *LogRangeExpr) {
if e == nil {
return
}
@ -210,7 +210,7 @@ func (v *DepthFirstTraversal) VisitLogRange(e *LogRange) {
}
// VisitLogfmtExpressionParser implements RootVisitor.
func (v *DepthFirstTraversal) VisitLogfmtExpressionParser(e *LogfmtExpressionParser) {
func (v *DepthFirstTraversal) VisitLogfmtExpressionParser(e *LogfmtExpressionParserExpr) {
if e == nil {
return
}

@ -12,7 +12,7 @@ func TestDepthFirstTraversalVisitor(t *testing.T) {
visited := [][2]string{}
visitor := &DepthFirstTraversal{
VisitLabelParserFn: func(_ RootVisitor, e *LabelParserExpr) {
VisitLabelParserFn: func(_ RootVisitor, e *LineParserExpr) {
visited = append(visited, [2]string{fmt.Sprintf("%T", e), e.String()})
},
VisitLineFilterFn: func(_ RootVisitor, e *LineFilterExpr) {
@ -33,7 +33,7 @@ func TestDepthFirstTraversalVisitor(t *testing.T) {
{"*syntax.LogfmtParserExpr", `| logfmt`},
{"*syntax.MatchersExpr", `{env="dev"}`},
{"*syntax.LineFilterExpr", `|~ "(foo|bar)"`},
{"*syntax.LabelParserExpr", `| json`},
{"*syntax.LineParserExpr", `| json`},
}
query := `

@ -271,7 +271,7 @@ func maxRangeVectorAndOffsetDuration(expr syntax.Expr) (time.Duration, time.Dura
var maxRVDuration, maxOffset time.Duration
expr.Walk(func(e syntax.Expr) {
if r, ok := e.(*syntax.LogRange); ok {
if r, ok := e.(*syntax.LogRangeExpr); ok {
if r.Interval > maxRVDuration {
maxRVDuration = r.Interval
}

Loading…
Cancel
Save