adds stringer methods for all ast expr types (#1630)

* adds stringer methods for all ast expr types

* Update pkg/logql/ast.go

Co-Authored-By: Cyril Tovena <cyril.tovena@gmail.com>

Co-authored-by: Cyril Tovena <cyril.tovena@gmail.com>
pull/1633/head
Owen Diehl 5 years ago committed by GitHub
parent a135652e69
commit 6930fb2a5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 66
      pkg/logql/ast.go
  2. 22
      pkg/logql/ast_test.go

@ -12,6 +12,7 @@ import (
"github.com/grafana/loki/pkg/iter"
"github.com/grafana/loki/pkg/logproto"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/promql"
)
@ -19,6 +20,7 @@ import (
// Expr is the root expression which can be a SampleExpr or LogSelectorExpr
type Expr interface {
logQLExpr() // ensure it's not implemented accidentally
fmt.Stringer
}
// SelectParams specifies parameters passed to data selections.
@ -53,7 +55,6 @@ type Filter func(line []byte) bool
type LogSelectorExpr interface {
Filter() (Filter, error)
Matchers() []*labels.Matcher
fmt.Stringer
Expr
}
@ -188,6 +189,16 @@ type logRange struct {
interval time.Duration
}
// impls Stringer
func (r logRange) String() string {
var sb strings.Builder
sb.WriteString("(")
sb.WriteString(r.left.String())
sb.WriteString(")")
sb.WriteString(fmt.Sprintf("[%v]", model.Duration(r.interval)))
return sb.String()
}
func newLogRange(left LogSelectorExpr, interval time.Duration) *logRange {
return &logRange{
left: left,
@ -279,11 +290,34 @@ func (e *rangeAggregationExpr) Selector() LogSelectorExpr {
// impl Expr
func (e *rangeAggregationExpr) logQLExpr() {}
// impls Stringer
func (e *rangeAggregationExpr) String() string {
return formatOperation(e.operation, nil, e.left.String())
}
type grouping struct {
groups []string
without bool
}
// impls Stringer
func (g grouping) String() string {
var sb strings.Builder
if g.without {
sb.WriteString(" without")
} else if len(g.groups) > 0 {
sb.WriteString(" by")
}
if len(g.groups) > 0 {
sb.WriteString("(")
sb.WriteString(strings.Join(g.groups, ","))
sb.WriteString(")")
}
return sb.String()
}
type vectorAggregationExpr struct {
left SampleExpr
@ -325,3 +359,33 @@ func (e *vectorAggregationExpr) Selector() LogSelectorExpr {
// impl Expr
func (e *vectorAggregationExpr) logQLExpr() {}
func (e *vectorAggregationExpr) String() string {
var params []string
if e.params != 0 {
params = []string{fmt.Sprintf("%d", e.params), e.left.String()}
} else {
params = []string{e.left.String()}
}
return formatOperation(e.operation, e.grouping, params...)
}
// helper used to impl Stringer for vector and range aggregations
func formatOperation(op string, grouping *grouping, params ...string) string {
nonEmptyParams := make([]string, 0, len(params))
for _, p := range params {
if p != "" {
nonEmptyParams = append(nonEmptyParams, p)
}
}
var sb strings.Builder
sb.WriteString(op)
if grouping != nil {
sb.WriteString(grouping.String())
}
sb.WriteString("(")
sb.WriteString(strings.Join(nonEmptyParams, ","))
sb.WriteString(")")
return sb.String()
}

@ -5,6 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/pkg/labels"
)
@ -33,6 +34,27 @@ func Test_logSelectorExpr_String(t *testing.T) {
}
}
func Test_SampleExpr_String(t *testing.T) {
t.Parallel()
for _, tc := range []string{
`rate( ( {job="mysql"} |="error" !="timeout" ) [10s] )`,
`sum without(a) ( rate ( ( {job="mysql"} |="error" !="timeout" ) [10s] ) )`,
`sum by(a) (rate( ( {job="mysql"} |="error" !="timeout" ) [10s] ) )`,
`sum(count_over_time({job="mysql"}[5m]))`,
`topk(10,sum(rate({region="us-east1"}[5m])) by (name))`,
`avg( rate( ( {job="nginx"} |= "GET" ) [10s] ) ) by (region)`,
} {
t.Run(tc, func(t *testing.T) {
expr, err := ParseExpr(tc)
require.Nil(t, err)
expr2, err := ParseExpr(expr.String())
require.Nil(t, err)
require.Equal(t, expr, expr2)
})
}
}
type linecheck struct {
l string
e bool

Loading…
Cancel
Save