github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/logql/syntax/ast.go (about)

     1  package syntax
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  	"github.com/prometheus/common/model"
    13  	"github.com/prometheus/prometheus/model/labels"
    14  	"github.com/prometheus/prometheus/promql"
    15  
    16  	"github.com/grafana/loki/pkg/logql/log"
    17  	"github.com/grafana/loki/pkg/logqlmodel"
    18  )
    19  
    20  // Expr is the root expression which can be a SampleExpr or LogSelectorExpr
    21  type Expr interface {
    22  	logQLExpr()      // ensure it's not implemented accidentally
    23  	Shardable() bool // A recursive check on the AST to see if it's shardable.
    24  	Walkable
    25  	fmt.Stringer
    26  }
    27  
    28  func Clone(e Expr) (Expr, error) {
    29  	return ParseExpr(e.String())
    30  }
    31  
    32  // implicit holds default implementations
    33  type implicit struct{}
    34  
    35  func (implicit) logQLExpr() {}
    36  
    37  // LogSelectorExpr is a LogQL expression filtering and returning logs.
    38  type LogSelectorExpr interface {
    39  	Matchers() []*labels.Matcher
    40  	LogPipelineExpr
    41  	HasFilter() bool
    42  	Expr
    43  }
    44  
    45  // Type alias for backward compatibility
    46  type (
    47  	Pipeline        = log.Pipeline
    48  	SampleExtractor = log.SampleExtractor
    49  )
    50  
    51  // LogPipelineExpr is an expression defining a log pipeline.
    52  type LogPipelineExpr interface {
    53  	Pipeline() (Pipeline, error)
    54  	Expr
    55  }
    56  
    57  // StageExpr is an expression defining a single step into a log pipeline
    58  type StageExpr interface {
    59  	Stage() (log.Stage, error)
    60  	Expr
    61  }
    62  
    63  // MultiStageExpr is multiple stages which implement a PipelineExpr.
    64  type MultiStageExpr []StageExpr
    65  
    66  func (m MultiStageExpr) Pipeline() (log.Pipeline, error) {
    67  	stages, err := m.stages()
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	return log.NewPipeline(stages), nil
    72  }
    73  
    74  func (m MultiStageExpr) stages() ([]log.Stage, error) {
    75  	c := make([]log.Stage, 0, len(m))
    76  	for _, e := range m {
    77  		p, err := e.Stage()
    78  		if err != nil {
    79  			return nil, logqlmodel.NewStageError(e.String(), err)
    80  		}
    81  		if p == log.NoopStage {
    82  			continue
    83  		}
    84  		c = append(c, p)
    85  	}
    86  	return c, nil
    87  }
    88  
    89  func (m MultiStageExpr) String() string {
    90  	var sb strings.Builder
    91  	for i, e := range m {
    92  		sb.WriteString(e.String())
    93  		if i+1 != len(m) {
    94  			sb.WriteString(" ")
    95  		}
    96  	}
    97  	return sb.String()
    98  }
    99  
   100  func (MultiStageExpr) logQLExpr() {} // nolint:unused
   101  
   102  type MatchersExpr struct {
   103  	Mts []*labels.Matcher
   104  	implicit
   105  }
   106  
   107  func newMatcherExpr(matchers []*labels.Matcher) *MatchersExpr {
   108  	return &MatchersExpr{Mts: matchers}
   109  }
   110  
   111  func (e *MatchersExpr) Matchers() []*labels.Matcher {
   112  	return e.Mts
   113  }
   114  
   115  func (e *MatchersExpr) AppendMatchers(m []*labels.Matcher) {
   116  	e.Mts = append(e.Mts, m...)
   117  }
   118  
   119  func (e *MatchersExpr) Shardable() bool { return true }
   120  
   121  func (e *MatchersExpr) Walk(f WalkFn) { f(e) }
   122  
   123  func (e *MatchersExpr) String() string {
   124  	var sb strings.Builder
   125  	sb.WriteString("{")
   126  	for i, m := range e.Mts {
   127  		sb.WriteString(m.String())
   128  		if i+1 != len(e.Mts) {
   129  			sb.WriteString(", ")
   130  		}
   131  	}
   132  	sb.WriteString("}")
   133  	return sb.String()
   134  }
   135  
   136  func (e *MatchersExpr) Pipeline() (log.Pipeline, error) {
   137  	return log.NewNoopPipeline(), nil
   138  }
   139  
   140  func (e *MatchersExpr) HasFilter() bool {
   141  	return false
   142  }
   143  
   144  type PipelineExpr struct {
   145  	MultiStages MultiStageExpr
   146  	Left        *MatchersExpr
   147  	implicit
   148  }
   149  
   150  func newPipelineExpr(left *MatchersExpr, pipeline MultiStageExpr) LogSelectorExpr {
   151  	return &PipelineExpr{
   152  		Left:        left,
   153  		MultiStages: pipeline,
   154  	}
   155  }
   156  
   157  func (e *PipelineExpr) Shardable() bool {
   158  	for _, p := range e.MultiStages {
   159  		if !p.Shardable() {
   160  			return false
   161  		}
   162  	}
   163  	return true
   164  }
   165  
   166  func (e *PipelineExpr) Walk(f WalkFn) {
   167  	f(e)
   168  
   169  	if e.Left == nil {
   170  		return
   171  	}
   172  
   173  	xs := make([]Walkable, 0, len(e.MultiStages)+1)
   174  	xs = append(xs, e.Left)
   175  	for _, p := range e.MultiStages {
   176  		xs = append(xs, p)
   177  	}
   178  	walkAll(f, xs...)
   179  }
   180  
   181  func (e *PipelineExpr) Matchers() []*labels.Matcher {
   182  	return e.Left.Matchers()
   183  }
   184  
   185  func (e *PipelineExpr) String() string {
   186  	var sb strings.Builder
   187  	sb.WriteString(e.Left.String())
   188  	sb.WriteString(" ")
   189  	sb.WriteString(e.MultiStages.String())
   190  	return sb.String()
   191  }
   192  
   193  func (e *PipelineExpr) Pipeline() (log.Pipeline, error) {
   194  	return e.MultiStages.Pipeline()
   195  }
   196  
   197  // HasFilter returns true if the pipeline contains stage that can filter out lines.
   198  func (e *PipelineExpr) HasFilter() bool {
   199  	for _, p := range e.MultiStages {
   200  		switch p.(type) {
   201  		case *LineFilterExpr, *LabelFilterExpr:
   202  			return true
   203  		default:
   204  			continue
   205  		}
   206  	}
   207  	return false
   208  }
   209  
   210  type LineFilterExpr struct {
   211  	Left  *LineFilterExpr
   212  	Ty    labels.MatchType
   213  	Match string
   214  	Op    string
   215  	implicit
   216  }
   217  
   218  func newLineFilterExpr(ty labels.MatchType, op, match string) *LineFilterExpr {
   219  	return &LineFilterExpr{
   220  		Ty:    ty,
   221  		Match: match,
   222  		Op:    op,
   223  	}
   224  }
   225  
   226  func newNestedLineFilterExpr(left *LineFilterExpr, right *LineFilterExpr) *LineFilterExpr {
   227  	return &LineFilterExpr{
   228  		Left:  left,
   229  		Ty:    right.Ty,
   230  		Match: right.Match,
   231  		Op:    right.Op,
   232  	}
   233  }
   234  
   235  func (e *LineFilterExpr) Walk(f WalkFn) {
   236  	f(e)
   237  	if e.Left == nil {
   238  		return
   239  	}
   240  	e.Left.Walk(f)
   241  }
   242  
   243  // AddFilterExpr adds a filter expression to a logselector expression.
   244  func AddFilterExpr(expr LogSelectorExpr, ty labels.MatchType, op, match string) (LogSelectorExpr, error) {
   245  	filter := newLineFilterExpr(ty, op, match)
   246  	switch e := expr.(type) {
   247  	case *MatchersExpr:
   248  		return newPipelineExpr(e, MultiStageExpr{filter}), nil
   249  	case *PipelineExpr:
   250  		e.MultiStages = append(e.MultiStages, filter)
   251  		return e, nil
   252  	default:
   253  		return nil, fmt.Errorf("unknown LogSelector: %v+", expr)
   254  	}
   255  }
   256  
   257  func (e *LineFilterExpr) Shardable() bool { return true }
   258  
   259  func (e *LineFilterExpr) String() string {
   260  	var sb strings.Builder
   261  	if e.Left != nil {
   262  		sb.WriteString(e.Left.String())
   263  		sb.WriteString(" ")
   264  	}
   265  	switch e.Ty {
   266  	case labels.MatchRegexp:
   267  		sb.WriteString("|~")
   268  	case labels.MatchNotRegexp:
   269  		sb.WriteString("!~")
   270  	case labels.MatchEqual:
   271  		sb.WriteString("|=")
   272  	case labels.MatchNotEqual:
   273  		sb.WriteString("!=")
   274  	}
   275  	sb.WriteString(" ")
   276  	if e.Op == "" {
   277  		sb.WriteString(strconv.Quote(e.Match))
   278  		return sb.String()
   279  	}
   280  	sb.WriteString(e.Op)
   281  	sb.WriteString("(")
   282  	sb.WriteString(strconv.Quote(e.Match))
   283  	sb.WriteString(")")
   284  	return sb.String()
   285  }
   286  
   287  func (e *LineFilterExpr) Filter() (log.Filterer, error) {
   288  	acc := make([]log.Filterer, 0)
   289  	for curr := e; curr != nil; curr = curr.Left {
   290  		switch curr.Op {
   291  		case OpFilterIP:
   292  			var err error
   293  			next, err := log.NewIPLineFilter(curr.Match, curr.Ty)
   294  			if err != nil {
   295  				return nil, err
   296  			}
   297  			acc = append(acc, next)
   298  		default:
   299  			next, err := log.NewFilter(curr.Match, curr.Ty)
   300  			if err != nil {
   301  				return nil, err
   302  			}
   303  			acc = append(acc, next)
   304  		}
   305  	}
   306  
   307  	if len(acc) == 1 {
   308  		return acc[0], nil
   309  	}
   310  
   311  	// The accumulation is right to left so it needs to be reversed.
   312  	for i := len(acc)/2 - 1; i >= 0; i-- {
   313  		opp := len(acc) - 1 - i
   314  		acc[i], acc[opp] = acc[opp], acc[i]
   315  	}
   316  
   317  	return log.NewAndFilters(acc), nil
   318  }
   319  
   320  func (e *LineFilterExpr) Stage() (log.Stage, error) {
   321  	f, err := e.Filter()
   322  	if err != nil {
   323  		return nil, err
   324  	}
   325  	return f.ToStage(), nil
   326  }
   327  
   328  type LabelParserExpr struct {
   329  	Op    string
   330  	Param string
   331  	implicit
   332  }
   333  
   334  func newLabelParserExpr(op, param string) *LabelParserExpr {
   335  	return &LabelParserExpr{
   336  		Op:    op,
   337  		Param: param,
   338  	}
   339  }
   340  
   341  func (e *LabelParserExpr) Shardable() bool { return true }
   342  
   343  func (e *LabelParserExpr) Walk(f WalkFn) { f(e) }
   344  
   345  func (e *LabelParserExpr) Stage() (log.Stage, error) {
   346  	switch e.Op {
   347  	case OpParserTypeJSON:
   348  		return log.NewJSONParser(), nil
   349  	case OpParserTypeLogfmt:
   350  		return log.NewLogfmtParser(), nil
   351  	case OpParserTypeRegexp:
   352  		return log.NewRegexpParser(e.Param)
   353  	case OpParserTypeUnpack:
   354  		return log.NewUnpackParser(), nil
   355  	case OpParserTypePattern:
   356  		return log.NewPatternParser(e.Param)
   357  	default:
   358  		return nil, fmt.Errorf("unknown parser operator: %s", e.Op)
   359  	}
   360  }
   361  
   362  func (e *LabelParserExpr) String() string {
   363  	var sb strings.Builder
   364  	sb.WriteString(OpPipe)
   365  	sb.WriteString(" ")
   366  	sb.WriteString(e.Op)
   367  	if e.Param != "" {
   368  		sb.WriteString(" ")
   369  		sb.WriteString(strconv.Quote(e.Param))
   370  	}
   371  	return sb.String()
   372  }
   373  
   374  type LabelFilterExpr struct {
   375  	log.LabelFilterer
   376  	implicit
   377  }
   378  
   379  func newLabelFilterExpr(filterer log.LabelFilterer) *LabelFilterExpr {
   380  	return &LabelFilterExpr{
   381  		LabelFilterer: filterer,
   382  	}
   383  }
   384  
   385  func (e *LabelFilterExpr) Shardable() bool { return true }
   386  
   387  func (e *LabelFilterExpr) Walk(f WalkFn) { f(e) }
   388  
   389  func (e *LabelFilterExpr) Stage() (log.Stage, error) {
   390  	switch ip := e.LabelFilterer.(type) {
   391  	case *log.IPLabelFilter:
   392  		return ip, ip.PatternError()
   393  	}
   394  	return e.LabelFilterer, nil
   395  }
   396  
   397  func (e *LabelFilterExpr) String() string {
   398  	return fmt.Sprintf("%s %s", OpPipe, e.LabelFilterer.String())
   399  }
   400  
   401  type LineFmtExpr struct {
   402  	Value string
   403  	implicit
   404  }
   405  
   406  func newLineFmtExpr(value string) *LineFmtExpr {
   407  	return &LineFmtExpr{
   408  		Value: value,
   409  	}
   410  }
   411  
   412  func (e *LineFmtExpr) Shardable() bool { return true }
   413  
   414  func (e *LineFmtExpr) Walk(f WalkFn) { f(e) }
   415  
   416  func (e *LineFmtExpr) Stage() (log.Stage, error) {
   417  	return log.NewFormatter(e.Value)
   418  }
   419  
   420  func (e *LineFmtExpr) String() string {
   421  	return fmt.Sprintf("%s %s %s", OpPipe, OpFmtLine, strconv.Quote(e.Value))
   422  }
   423  
   424  type LabelFmtExpr struct {
   425  	Formats []log.LabelFmt
   426  
   427  	implicit
   428  }
   429  
   430  func newLabelFmtExpr(fmts []log.LabelFmt) *LabelFmtExpr {
   431  	return &LabelFmtExpr{
   432  		Formats: fmts,
   433  	}
   434  }
   435  
   436  func (e *LabelFmtExpr) Shardable() bool { return false }
   437  
   438  func (e *LabelFmtExpr) Walk(f WalkFn) { f(e) }
   439  
   440  func (e *LabelFmtExpr) Stage() (log.Stage, error) {
   441  	return log.NewLabelsFormatter(e.Formats)
   442  }
   443  
   444  func (e *LabelFmtExpr) String() string {
   445  	var sb strings.Builder
   446  	sb.WriteString(fmt.Sprintf("%s %s ", OpPipe, OpFmtLabel))
   447  	for i, f := range e.Formats {
   448  		sb.WriteString(f.Name)
   449  		sb.WriteString("=")
   450  		if f.Rename {
   451  			sb.WriteString(f.Value)
   452  		} else {
   453  			sb.WriteString(strconv.Quote(f.Value))
   454  		}
   455  		if i+1 != len(e.Formats) {
   456  			sb.WriteString(",")
   457  		}
   458  	}
   459  	return sb.String()
   460  }
   461  
   462  type JSONExpressionParser struct {
   463  	Expressions []log.JSONExpression
   464  
   465  	implicit
   466  }
   467  
   468  func newJSONExpressionParser(expressions []log.JSONExpression) *JSONExpressionParser {
   469  	return &JSONExpressionParser{
   470  		Expressions: expressions,
   471  	}
   472  }
   473  
   474  func (j *JSONExpressionParser) Shardable() bool { return true }
   475  
   476  func (j *JSONExpressionParser) Walk(f WalkFn) { f(j) }
   477  
   478  func (j *JSONExpressionParser) Stage() (log.Stage, error) {
   479  	return log.NewJSONExpressionParser(j.Expressions)
   480  }
   481  
   482  func (j *JSONExpressionParser) String() string {
   483  	var sb strings.Builder
   484  	sb.WriteString(fmt.Sprintf("%s %s ", OpPipe, OpParserTypeJSON))
   485  	for i, exp := range j.Expressions {
   486  		sb.WriteString(exp.Identifier)
   487  		sb.WriteString("=")
   488  		sb.WriteString(strconv.Quote(exp.Expression))
   489  
   490  		if i+1 != len(j.Expressions) {
   491  			sb.WriteString(",")
   492  		}
   493  	}
   494  	return sb.String()
   495  }
   496  
   497  func mustNewMatcher(t labels.MatchType, n, v string) *labels.Matcher {
   498  	m, err := labels.NewMatcher(t, n, v)
   499  	if err != nil {
   500  		panic(logqlmodel.NewParseError(err.Error(), 0, 0))
   501  	}
   502  	return m
   503  }
   504  
   505  func mustNewFloat(s string) float64 {
   506  	n, err := strconv.ParseFloat(s, 64)
   507  	if err != nil {
   508  		panic(logqlmodel.NewParseError(fmt.Sprintf("unable to parse float: %s", err.Error()), 0, 0))
   509  	}
   510  	return n
   511  }
   512  
   513  type UnwrapExpr struct {
   514  	Identifier string
   515  	Operation  string
   516  
   517  	PostFilters []log.LabelFilterer
   518  }
   519  
   520  func (u UnwrapExpr) String() string {
   521  	var sb strings.Builder
   522  	if u.Operation != "" {
   523  		sb.WriteString(fmt.Sprintf(" %s %s %s(%s)", OpPipe, OpUnwrap, u.Operation, u.Identifier))
   524  	} else {
   525  		sb.WriteString(fmt.Sprintf(" %s %s %s", OpPipe, OpUnwrap, u.Identifier))
   526  	}
   527  	for _, f := range u.PostFilters {
   528  		sb.WriteString(fmt.Sprintf(" %s %s", OpPipe, f))
   529  	}
   530  	return sb.String()
   531  }
   532  
   533  func (u *UnwrapExpr) addPostFilter(f log.LabelFilterer) *UnwrapExpr {
   534  	u.PostFilters = append(u.PostFilters, f)
   535  	return u
   536  }
   537  
   538  func newUnwrapExpr(id string, operation string) *UnwrapExpr {
   539  	return &UnwrapExpr{Identifier: id, Operation: operation}
   540  }
   541  
   542  type LogRange struct {
   543  	Left     LogSelectorExpr
   544  	Interval time.Duration
   545  	Offset   time.Duration
   546  
   547  	Unwrap *UnwrapExpr
   548  
   549  	implicit
   550  }
   551  
   552  // impls Stringer
   553  func (r LogRange) String() string {
   554  	var sb strings.Builder
   555  	sb.WriteString(r.Left.String())
   556  	if r.Unwrap != nil {
   557  		sb.WriteString(r.Unwrap.String())
   558  	}
   559  	sb.WriteString(fmt.Sprintf("[%v]", model.Duration(r.Interval)))
   560  	if r.Offset != 0 {
   561  		offsetExpr := OffsetExpr{Offset: r.Offset}
   562  		sb.WriteString(offsetExpr.String())
   563  	}
   564  	return sb.String()
   565  }
   566  
   567  func (r *LogRange) Shardable() bool { return r.Left.Shardable() }
   568  
   569  func (r *LogRange) Walk(f WalkFn) {
   570  	f(r)
   571  	if r.Left == nil {
   572  		return
   573  	}
   574  	r.Left.Walk(f)
   575  }
   576  
   577  func newLogRange(left LogSelectorExpr, interval time.Duration, u *UnwrapExpr, o *OffsetExpr) *LogRange {
   578  	var offset time.Duration
   579  	if o != nil {
   580  		offset = o.Offset
   581  	}
   582  	return &LogRange{
   583  		Left:     left,
   584  		Interval: interval,
   585  		Unwrap:   u,
   586  		Offset:   offset,
   587  	}
   588  }
   589  
   590  type OffsetExpr struct {
   591  	Offset time.Duration
   592  }
   593  
   594  func (o *OffsetExpr) String() string {
   595  	var sb strings.Builder
   596  	sb.WriteString(fmt.Sprintf(" %s %s", OpOffset, o.Offset.String()))
   597  	return sb.String()
   598  }
   599  
   600  func newOffsetExpr(offset time.Duration) *OffsetExpr {
   601  	return &OffsetExpr{
   602  		Offset: offset,
   603  	}
   604  }
   605  
   606  const (
   607  	// vector ops
   608  	OpTypeSum     = "sum"
   609  	OpTypeAvg     = "avg"
   610  	OpTypeMax     = "max"
   611  	OpTypeMin     = "min"
   612  	OpTypeCount   = "count"
   613  	OpTypeStddev  = "stddev"
   614  	OpTypeStdvar  = "stdvar"
   615  	OpTypeBottomK = "bottomk"
   616  	OpTypeTopK    = "topk"
   617  
   618  	// range vector ops
   619  	OpRangeTypeCount       = "count_over_time"
   620  	OpRangeTypeRate        = "rate"
   621  	OpRangeTypeRateCounter = "rate_counter"
   622  	OpRangeTypeBytes       = "bytes_over_time"
   623  	OpRangeTypeBytesRate   = "bytes_rate"
   624  	OpRangeTypeAvg         = "avg_over_time"
   625  	OpRangeTypeSum         = "sum_over_time"
   626  	OpRangeTypeMin         = "min_over_time"
   627  	OpRangeTypeMax         = "max_over_time"
   628  	OpRangeTypeStdvar      = "stdvar_over_time"
   629  	OpRangeTypeStddev      = "stddev_over_time"
   630  	OpRangeTypeQuantile    = "quantile_over_time"
   631  	OpRangeTypeFirst       = "first_over_time"
   632  	OpRangeTypeLast        = "last_over_time"
   633  	OpRangeTypeAbsent      = "absent_over_time"
   634  
   635  	// binops - logical/set
   636  	OpTypeOr     = "or"
   637  	OpTypeAnd    = "and"
   638  	OpTypeUnless = "unless"
   639  
   640  	// binops - operations
   641  	OpTypeAdd = "+"
   642  	OpTypeSub = "-"
   643  	OpTypeMul = "*"
   644  	OpTypeDiv = "/"
   645  	OpTypeMod = "%"
   646  	OpTypePow = "^"
   647  
   648  	// binops - comparison
   649  	OpTypeCmpEQ = "=="
   650  	OpTypeNEQ   = "!="
   651  	OpTypeGT    = ">"
   652  	OpTypeGTE   = ">="
   653  	OpTypeLT    = "<"
   654  	OpTypeLTE   = "<="
   655  
   656  	// parsers
   657  	OpParserTypeJSON    = "json"
   658  	OpParserTypeLogfmt  = "logfmt"
   659  	OpParserTypeRegexp  = "regexp"
   660  	OpParserTypeUnpack  = "unpack"
   661  	OpParserTypePattern = "pattern"
   662  
   663  	OpFmtLine  = "line_format"
   664  	OpFmtLabel = "label_format"
   665  
   666  	OpPipe   = "|"
   667  	OpUnwrap = "unwrap"
   668  	OpOffset = "offset"
   669  
   670  	OpOn       = "on"
   671  	OpIgnoring = "ignoring"
   672  
   673  	OpGroupLeft  = "group_left"
   674  	OpGroupRight = "group_right"
   675  
   676  	// conversion Op
   677  	OpConvBytes           = "bytes"
   678  	OpConvDuration        = "duration"
   679  	OpConvDurationSeconds = "duration_seconds"
   680  
   681  	OpLabelReplace = "label_replace"
   682  
   683  	// function filters
   684  	OpFilterIP = "ip"
   685  )
   686  
   687  func IsComparisonOperator(op string) bool {
   688  	switch op {
   689  	case OpTypeCmpEQ, OpTypeNEQ, OpTypeGT, OpTypeGTE, OpTypeLT, OpTypeLTE:
   690  		return true
   691  	default:
   692  		return false
   693  	}
   694  }
   695  
   696  // IsLogicalBinOp tests whether an operation is a logical/set binary operation
   697  func IsLogicalBinOp(op string) bool {
   698  	switch op {
   699  	case OpTypeOr, OpTypeAnd, OpTypeUnless:
   700  		return true
   701  	default:
   702  		return false
   703  	}
   704  }
   705  
   706  // SampleExpr is a LogQL expression filtering logs and returning metric samples.
   707  type SampleExpr interface {
   708  	// Selector is the LogQL selector to apply when retrieving logs.
   709  	Selector() LogSelectorExpr
   710  	Extractor() (SampleExtractor, error)
   711  	MatcherGroups() []MatcherRange
   712  	Expr
   713  }
   714  
   715  type RangeAggregationExpr struct {
   716  	Left      *LogRange
   717  	Operation string
   718  
   719  	Params   *float64
   720  	Grouping *Grouping
   721  	implicit
   722  }
   723  
   724  func newRangeAggregationExpr(left *LogRange, operation string, gr *Grouping, stringParams *string) SampleExpr {
   725  	var params *float64
   726  	if stringParams != nil {
   727  		if operation != OpRangeTypeQuantile {
   728  			panic(logqlmodel.NewParseError(fmt.Sprintf("parameter %s not supported for operation %s", *stringParams, operation), 0, 0))
   729  		}
   730  		var err error
   731  		params = new(float64)
   732  		*params, err = strconv.ParseFloat(*stringParams, 64)
   733  		if err != nil {
   734  			panic(logqlmodel.NewParseError(fmt.Sprintf("invalid parameter for operation %s: %s", operation, err), 0, 0))
   735  		}
   736  
   737  	} else {
   738  		if operation == OpRangeTypeQuantile {
   739  			panic(logqlmodel.NewParseError(fmt.Sprintf("parameter required for operation %s", operation), 0, 0))
   740  		}
   741  	}
   742  	e := &RangeAggregationExpr{
   743  		Left:      left,
   744  		Operation: operation,
   745  		Grouping:  gr,
   746  		Params:    params,
   747  	}
   748  	if err := e.validate(); err != nil {
   749  		panic(logqlmodel.NewParseError(err.Error(), 0, 0))
   750  	}
   751  	return e
   752  }
   753  
   754  func (e *RangeAggregationExpr) Selector() LogSelectorExpr {
   755  	return e.Left.Left
   756  }
   757  
   758  func (e *RangeAggregationExpr) MatcherGroups() []MatcherRange {
   759  	xs := e.Left.Left.Matchers()
   760  	if len(xs) > 0 {
   761  		return []MatcherRange{
   762  			{
   763  				Matchers: xs,
   764  				Interval: e.Left.Interval,
   765  				Offset:   e.Left.Offset,
   766  			},
   767  		}
   768  	}
   769  	return nil
   770  }
   771  
   772  func (e RangeAggregationExpr) validate() error {
   773  	if e.Grouping != nil {
   774  		switch e.Operation {
   775  		case OpRangeTypeAvg, OpRangeTypeStddev, OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeMax, OpRangeTypeMin, OpRangeTypeFirst, OpRangeTypeLast:
   776  		default:
   777  			return fmt.Errorf("grouping not allowed for %s aggregation", e.Operation)
   778  		}
   779  	}
   780  	if e.Left.Unwrap != nil {
   781  		switch e.Operation {
   782  		case OpRangeTypeAvg, OpRangeTypeSum, OpRangeTypeMax, OpRangeTypeMin, OpRangeTypeStddev,
   783  			OpRangeTypeStdvar, OpRangeTypeQuantile, OpRangeTypeRate, OpRangeTypeRateCounter,
   784  			OpRangeTypeAbsent, OpRangeTypeFirst, OpRangeTypeLast:
   785  			return nil
   786  		default:
   787  			return fmt.Errorf("invalid aggregation %s with unwrap", e.Operation)
   788  		}
   789  	}
   790  	switch e.Operation {
   791  	case OpRangeTypeBytes, OpRangeTypeBytesRate, OpRangeTypeCount, OpRangeTypeRate, OpRangeTypeAbsent:
   792  		return nil
   793  	default:
   794  		return fmt.Errorf("invalid aggregation %s without unwrap", e.Operation)
   795  	}
   796  }
   797  
   798  func (e RangeAggregationExpr) Validate() error {
   799  	return e.validate()
   800  }
   801  
   802  // impls Stringer
   803  func (e *RangeAggregationExpr) String() string {
   804  	var sb strings.Builder
   805  	sb.WriteString(e.Operation)
   806  	sb.WriteString("(")
   807  	if e.Params != nil {
   808  		sb.WriteString(strconv.FormatFloat(*e.Params, 'f', -1, 64))
   809  		sb.WriteString(",")
   810  	}
   811  	sb.WriteString(e.Left.String())
   812  	sb.WriteString(")")
   813  	if e.Grouping != nil {
   814  		sb.WriteString(e.Grouping.String())
   815  	}
   816  	return sb.String()
   817  }
   818  
   819  // impl SampleExpr
   820  func (e *RangeAggregationExpr) Shardable() bool {
   821  	return shardableOps[e.Operation] && e.Left.Shardable()
   822  }
   823  
   824  func (e *RangeAggregationExpr) Walk(f WalkFn) {
   825  	f(e)
   826  	if e.Left == nil {
   827  		return
   828  	}
   829  	e.Left.Walk(f)
   830  }
   831  
   832  type Grouping struct {
   833  	Groups  []string
   834  	Without bool
   835  }
   836  
   837  // impls Stringer
   838  func (g Grouping) String() string {
   839  	var sb strings.Builder
   840  	if g.Without {
   841  		sb.WriteString(" without")
   842  	} else if len(g.Groups) > 0 {
   843  		sb.WriteString(" by")
   844  	}
   845  
   846  	if len(g.Groups) > 0 {
   847  		sb.WriteString("(")
   848  		sb.WriteString(strings.Join(g.Groups, ","))
   849  		sb.WriteString(")")
   850  	}
   851  
   852  	return sb.String()
   853  }
   854  
   855  type VectorAggregationExpr struct {
   856  	Left SampleExpr
   857  
   858  	Grouping  *Grouping
   859  	Params    int
   860  	Operation string
   861  	implicit
   862  }
   863  
   864  func mustNewVectorAggregationExpr(left SampleExpr, operation string, gr *Grouping, params *string) SampleExpr {
   865  	var p int
   866  	var err error
   867  	switch operation {
   868  	case OpTypeBottomK, OpTypeTopK:
   869  		if params == nil {
   870  			panic(logqlmodel.NewParseError(fmt.Sprintf("parameter required for operation %s", operation), 0, 0))
   871  		}
   872  		if p, err = strconv.Atoi(*params); err != nil {
   873  			panic(logqlmodel.NewParseError(fmt.Sprintf("invalid parameter %s(%s,", operation, *params), 0, 0))
   874  		}
   875  
   876  	default:
   877  		if params != nil {
   878  			panic(logqlmodel.NewParseError(fmt.Sprintf("unsupported parameter for operation %s(%s,", operation, *params), 0, 0))
   879  		}
   880  	}
   881  	if gr == nil {
   882  		gr = &Grouping{}
   883  	}
   884  	return &VectorAggregationExpr{
   885  		Left:      left,
   886  		Operation: operation,
   887  		Grouping:  gr,
   888  		Params:    p,
   889  	}
   890  }
   891  
   892  func (e *VectorAggregationExpr) MatcherGroups() []MatcherRange {
   893  	return e.Left.MatcherGroups()
   894  }
   895  
   896  func (e *VectorAggregationExpr) Selector() LogSelectorExpr {
   897  	return e.Left.Selector()
   898  }
   899  
   900  func (e *VectorAggregationExpr) Extractor() (log.SampleExtractor, error) {
   901  	// inject in the range vector extractor the outer groups to improve performance.
   902  	// This is only possible if the operation is a sum. Anything else needs all labels.
   903  	if r, ok := e.Left.(*RangeAggregationExpr); ok && canInjectVectorGrouping(e.Operation, r.Operation) {
   904  		// if the range vec operation has no grouping we can push down the vec one.
   905  		if r.Grouping == nil {
   906  			return r.extractor(e.Grouping)
   907  		}
   908  	}
   909  	return e.Left.Extractor()
   910  }
   911  
   912  // canInjectVectorGrouping tells if a vector operation can inject grouping into the nested range vector.
   913  func canInjectVectorGrouping(vecOp, rangeOp string) bool {
   914  	if vecOp != OpTypeSum {
   915  		return false
   916  	}
   917  	switch rangeOp {
   918  	case OpRangeTypeBytes, OpRangeTypeBytesRate, OpRangeTypeSum, OpRangeTypeRate, OpRangeTypeCount:
   919  		return true
   920  	default:
   921  		return false
   922  	}
   923  }
   924  
   925  func (e *VectorAggregationExpr) String() string {
   926  	var params []string
   927  	if e.Params != 0 {
   928  		params = []string{fmt.Sprintf("%d", e.Params), e.Left.String()}
   929  	} else {
   930  		params = []string{e.Left.String()}
   931  	}
   932  	return formatOperation(e.Operation, e.Grouping, params...)
   933  }
   934  
   935  // impl SampleExpr
   936  func (e *VectorAggregationExpr) Shardable() bool {
   937  	if e.Operation == OpTypeCount || e.Operation == OpTypeAvg {
   938  		if !e.Left.Shardable() {
   939  			return false
   940  		}
   941  		// count is shardable if labels are not mutated
   942  		// otherwise distinct values can be counted twice per shard
   943  		shardable := true
   944  		e.Left.Walk(func(e interface{}) {
   945  			switch e.(type) {
   946  			// LabelParserExpr is normally shardable, but not in this case.
   947  			// TODO(owen-d): I think LabelParserExpr is shardable
   948  			// for avg, but not for count. Let's refactor to make this
   949  			// cleaner. For now I'm disallowing sharding on both.
   950  			case *LabelParserExpr:
   951  				shardable = false
   952  			}
   953  		})
   954  		return shardable
   955  	}
   956  	return shardableOps[e.Operation] && e.Left.Shardable()
   957  }
   958  
   959  func (e *VectorAggregationExpr) Walk(f WalkFn) {
   960  	f(e)
   961  	if e.Left == nil {
   962  		return
   963  	}
   964  	e.Left.Walk(f)
   965  }
   966  
   967  // VectorMatchCardinality describes the cardinality relationship
   968  // of two Vectors in a binary operation.
   969  type VectorMatchCardinality int
   970  
   971  const (
   972  	CardOneToOne VectorMatchCardinality = iota
   973  	CardManyToOne
   974  	CardOneToMany
   975  )
   976  
   977  func (vmc VectorMatchCardinality) String() string {
   978  	switch vmc {
   979  	case CardOneToOne:
   980  		return "one-to-one"
   981  	case CardManyToOne:
   982  		return "many-to-one"
   983  	case CardOneToMany:
   984  		return "one-to-many"
   985  	}
   986  	panic("promql.VectorMatchCardinality.String: unknown match cardinality")
   987  }
   988  
   989  // VectorMatching describes how elements from two Vectors in a binary
   990  // operation are supposed to be matched.
   991  type VectorMatching struct {
   992  	// The cardinality of the two Vectors.
   993  	Card VectorMatchCardinality
   994  	// MatchingLabels contains the labels which define equality of a pair of
   995  	// elements from the Vectors.
   996  	MatchingLabels []string
   997  	// On includes the given label names from matching,
   998  	// rather than excluding them.
   999  	On bool
  1000  	// Include contains additional labels that should be included in
  1001  	// the result from the side with the lower cardinality.
  1002  	Include []string
  1003  }
  1004  
  1005  type BinOpOptions struct {
  1006  	ReturnBool     bool
  1007  	VectorMatching *VectorMatching
  1008  }
  1009  
  1010  type BinOpExpr struct {
  1011  	SampleExpr
  1012  	RHS  SampleExpr
  1013  	Op   string
  1014  	Opts *BinOpOptions
  1015  }
  1016  
  1017  func (e *BinOpExpr) MatcherGroups() []MatcherRange {
  1018  	return append(e.SampleExpr.MatcherGroups(), e.RHS.MatcherGroups()...)
  1019  }
  1020  
  1021  func (e *BinOpExpr) String() string {
  1022  	op := e.Op
  1023  	if e.Opts != nil {
  1024  		if e.Opts.ReturnBool {
  1025  			op = fmt.Sprintf("%s bool", op)
  1026  		}
  1027  		if e.Opts.VectorMatching != nil {
  1028  			group := ""
  1029  			if e.Opts.VectorMatching.Card == CardManyToOne {
  1030  				group = OpGroupLeft
  1031  			} else if e.Opts.VectorMatching.Card == CardOneToMany {
  1032  				group = OpGroupRight
  1033  			}
  1034  			if e.Opts.VectorMatching.Include != nil {
  1035  				group = fmt.Sprintf("%s (%s)", group, strings.Join(e.Opts.VectorMatching.Include, ","))
  1036  			}
  1037  
  1038  			if e.Opts.VectorMatching.On || e.Opts.VectorMatching.MatchingLabels != nil {
  1039  				on := OpOn
  1040  				if !e.Opts.VectorMatching.On {
  1041  					on = OpIgnoring
  1042  				}
  1043  				op = fmt.Sprintf("%s %s (%s) %s", op, on, strings.Join(e.Opts.VectorMatching.MatchingLabels, ","), group)
  1044  			}
  1045  		}
  1046  	}
  1047  	return fmt.Sprintf("(%s %s %s)", e.SampleExpr.String(), op, e.RHS.String())
  1048  }
  1049  
  1050  // impl SampleExpr
  1051  func (e *BinOpExpr) Shardable() bool {
  1052  	if e.Opts != nil && e.Opts.VectorMatching != nil {
  1053  		// prohibit sharding when we're changing the label groupings, such as on or ignoring
  1054  		return false
  1055  	}
  1056  	return shardableOps[e.Op] && e.SampleExpr.Shardable() && e.RHS.Shardable()
  1057  }
  1058  
  1059  func (e *BinOpExpr) Walk(f WalkFn) {
  1060  	walkAll(f, e.SampleExpr, e.RHS)
  1061  }
  1062  
  1063  func mustNewBinOpExpr(op string, opts *BinOpOptions, lhs, rhs Expr) SampleExpr {
  1064  	left, ok := lhs.(SampleExpr)
  1065  	if !ok {
  1066  		panic(logqlmodel.NewParseError(fmt.Sprintf(
  1067  			"unexpected type for left leg of binary operation (%s): %T",
  1068  			op,
  1069  			lhs,
  1070  		), 0, 0))
  1071  	}
  1072  
  1073  	right, ok := rhs.(SampleExpr)
  1074  	if !ok {
  1075  		panic(logqlmodel.NewParseError(fmt.Sprintf(
  1076  			"unexpected type for right leg of binary operation (%s): %T",
  1077  			op,
  1078  			rhs,
  1079  		), 0, 0))
  1080  	}
  1081  
  1082  	leftLit, lOk := left.(*LiteralExpr)
  1083  	rightLit, rOk := right.(*LiteralExpr)
  1084  
  1085  	if IsLogicalBinOp(op) {
  1086  		if lOk {
  1087  			panic(logqlmodel.NewParseError(fmt.Sprintf(
  1088  				"unexpected literal for left leg of logical/set binary operation (%s): %f",
  1089  				op,
  1090  				leftLit.Val,
  1091  			), 0, 0))
  1092  		}
  1093  
  1094  		if rOk {
  1095  			panic(logqlmodel.NewParseError(fmt.Sprintf(
  1096  				"unexpected literal for right leg of logical/set binary operation (%s): %f",
  1097  				op,
  1098  				rightLit.Val,
  1099  			), 0, 0))
  1100  		}
  1101  	}
  1102  
  1103  	// map expr like (1+1) -> 2
  1104  	if lOk && rOk {
  1105  		return reduceBinOp(op, leftLit, rightLit)
  1106  	}
  1107  
  1108  	return &BinOpExpr{
  1109  		SampleExpr: left,
  1110  		RHS:        right,
  1111  		Op:         op,
  1112  		Opts:       opts,
  1113  	}
  1114  }
  1115  
  1116  // Reduces a binary operation expression. A binop is reducible if both of its legs are literal expressions.
  1117  // This is because literals need match all labels, which is currently difficult to encode into StepEvaluators.
  1118  // Therefore, we ensure a binop can be reduced/simplified, maintaining the invariant that it does not have two literal legs.
  1119  func reduceBinOp(op string, left, right *LiteralExpr) *LiteralExpr {
  1120  	merged := MergeBinOp(
  1121  		op,
  1122  		&promql.Sample{Point: promql.Point{V: left.Val}},
  1123  		&promql.Sample{Point: promql.Point{V: right.Val}},
  1124  		false,
  1125  		false,
  1126  	)
  1127  	return &LiteralExpr{Val: merged.V}
  1128  }
  1129  
  1130  func MergeBinOp(op string, left, right *promql.Sample, filter, isVectorComparison bool) *promql.Sample {
  1131  	var merger func(left, right *promql.Sample) *promql.Sample
  1132  
  1133  	switch op {
  1134  	case OpTypeAdd:
  1135  		merger = func(left, right *promql.Sample) *promql.Sample {
  1136  			if left == nil || right == nil {
  1137  				return nil
  1138  			}
  1139  			res := promql.Sample{
  1140  				Metric: left.Metric,
  1141  				Point:  left.Point,
  1142  			}
  1143  			res.Point.V += right.Point.V
  1144  			return &res
  1145  		}
  1146  
  1147  	case OpTypeSub:
  1148  		merger = func(left, right *promql.Sample) *promql.Sample {
  1149  			if left == nil || right == nil {
  1150  				return nil
  1151  			}
  1152  			res := promql.Sample{
  1153  				Metric: left.Metric,
  1154  				Point:  left.Point,
  1155  			}
  1156  			res.Point.V -= right.Point.V
  1157  			return &res
  1158  		}
  1159  
  1160  	case OpTypeMul:
  1161  		merger = func(left, right *promql.Sample) *promql.Sample {
  1162  			if left == nil || right == nil {
  1163  				return nil
  1164  			}
  1165  			res := promql.Sample{
  1166  				Metric: left.Metric,
  1167  				Point:  left.Point,
  1168  			}
  1169  			res.Point.V *= right.Point.V
  1170  			return &res
  1171  		}
  1172  
  1173  	case OpTypeDiv:
  1174  		merger = func(left, right *promql.Sample) *promql.Sample {
  1175  			if left == nil || right == nil {
  1176  				return nil
  1177  			}
  1178  			res := promql.Sample{
  1179  				Metric: left.Metric,
  1180  				Point:  left.Point,
  1181  			}
  1182  
  1183  			// guard against divide by zero
  1184  			if right.Point.V == 0 {
  1185  				res.Point.V = math.NaN()
  1186  			} else {
  1187  				res.Point.V /= right.Point.V
  1188  			}
  1189  			return &res
  1190  		}
  1191  
  1192  	case OpTypeMod:
  1193  		merger = func(left, right *promql.Sample) *promql.Sample {
  1194  			if left == nil || right == nil {
  1195  				return nil
  1196  			}
  1197  			res := promql.Sample{
  1198  				Metric: left.Metric,
  1199  				Point:  left.Point,
  1200  			}
  1201  			// guard against divide by zero
  1202  			if right.Point.V == 0 {
  1203  				res.Point.V = math.NaN()
  1204  			} else {
  1205  				res.Point.V = math.Mod(res.Point.V, right.Point.V)
  1206  			}
  1207  			return &res
  1208  		}
  1209  
  1210  	case OpTypePow:
  1211  		merger = func(left, right *promql.Sample) *promql.Sample {
  1212  			if left == nil || right == nil {
  1213  				return nil
  1214  			}
  1215  
  1216  			res := promql.Sample{
  1217  				Metric: left.Metric,
  1218  				Point:  left.Point,
  1219  			}
  1220  			res.Point.V = math.Pow(left.Point.V, right.Point.V)
  1221  			return &res
  1222  		}
  1223  
  1224  	case OpTypeCmpEQ:
  1225  		merger = func(left, right *promql.Sample) *promql.Sample {
  1226  			if left == nil || right == nil {
  1227  				return nil
  1228  			}
  1229  
  1230  			res := &promql.Sample{
  1231  				Metric: left.Metric,
  1232  				Point:  left.Point,
  1233  			}
  1234  
  1235  			val := 0.
  1236  			if left.Point.V == right.Point.V {
  1237  				val = 1.
  1238  			} else if filter {
  1239  				return nil
  1240  			}
  1241  			res.Point.V = val
  1242  			return res
  1243  		}
  1244  
  1245  	case OpTypeNEQ:
  1246  		merger = func(left, right *promql.Sample) *promql.Sample {
  1247  			if left == nil || right == nil {
  1248  				return nil
  1249  			}
  1250  
  1251  			res := &promql.Sample{
  1252  				Metric: left.Metric,
  1253  				Point:  left.Point,
  1254  			}
  1255  
  1256  			val := 0.
  1257  			if left.Point.V != right.Point.V {
  1258  				val = 1.
  1259  			} else if filter {
  1260  				return nil
  1261  			}
  1262  			res.Point.V = val
  1263  			return res
  1264  		}
  1265  
  1266  	case OpTypeGT:
  1267  		merger = func(left, right *promql.Sample) *promql.Sample {
  1268  			if left == nil || right == nil {
  1269  				return nil
  1270  			}
  1271  
  1272  			res := &promql.Sample{
  1273  				Metric: left.Metric,
  1274  				Point:  left.Point,
  1275  			}
  1276  
  1277  			val := 0.
  1278  			if left.Point.V > right.Point.V {
  1279  				val = 1.
  1280  			} else if filter {
  1281  				return nil
  1282  			}
  1283  			res.Point.V = val
  1284  			return res
  1285  		}
  1286  
  1287  	case OpTypeGTE:
  1288  		merger = func(left, right *promql.Sample) *promql.Sample {
  1289  			if left == nil || right == nil {
  1290  				return nil
  1291  			}
  1292  
  1293  			res := &promql.Sample{
  1294  				Metric: left.Metric,
  1295  				Point:  left.Point,
  1296  			}
  1297  
  1298  			val := 0.
  1299  			if left.Point.V >= right.Point.V {
  1300  				val = 1.
  1301  			} else if filter {
  1302  				return nil
  1303  			}
  1304  			res.Point.V = val
  1305  			return res
  1306  		}
  1307  
  1308  	case OpTypeLT:
  1309  		merger = func(left, right *promql.Sample) *promql.Sample {
  1310  			if left == nil || right == nil {
  1311  				return nil
  1312  			}
  1313  
  1314  			res := &promql.Sample{
  1315  				Metric: left.Metric,
  1316  				Point:  left.Point,
  1317  			}
  1318  
  1319  			val := 0.
  1320  			if left.Point.V < right.Point.V {
  1321  				val = 1.
  1322  			} else if filter {
  1323  				return nil
  1324  			}
  1325  			res.Point.V = val
  1326  			return res
  1327  		}
  1328  
  1329  	case OpTypeLTE:
  1330  		merger = func(left, right *promql.Sample) *promql.Sample {
  1331  			if left == nil || right == nil {
  1332  				return nil
  1333  			}
  1334  
  1335  			res := &promql.Sample{
  1336  				Metric: left.Metric,
  1337  				Point:  left.Point,
  1338  			}
  1339  
  1340  			val := 0.
  1341  			if left.Point.V <= right.Point.V {
  1342  				val = 1.
  1343  			} else if filter {
  1344  				return nil
  1345  			}
  1346  			res.Point.V = val
  1347  			return res
  1348  		}
  1349  
  1350  	default:
  1351  		panic(errors.Errorf("should never happen: unexpected operation: (%s)", op))
  1352  	}
  1353  
  1354  	res := merger(left, right)
  1355  	if !isVectorComparison {
  1356  		return res
  1357  	}
  1358  
  1359  	if filter {
  1360  		// if a filter-enabled vector-wise comparison has returned non-nil,
  1361  		// ensure we return the left hand side's value (2) instead of the
  1362  		// comparison operator's result (1: the truthy answer)
  1363  		if res != nil {
  1364  			return left
  1365  		}
  1366  	}
  1367  	return res
  1368  }
  1369  
  1370  type LiteralExpr struct {
  1371  	Val float64
  1372  	implicit
  1373  }
  1374  
  1375  func mustNewLiteralExpr(s string, invert bool) *LiteralExpr {
  1376  	n, err := strconv.ParseFloat(s, 64)
  1377  	if err != nil {
  1378  		panic(logqlmodel.NewParseError(fmt.Sprintf("unable to parse literal as a float: %s", err.Error()), 0, 0))
  1379  	}
  1380  
  1381  	if invert {
  1382  		n = -n
  1383  	}
  1384  
  1385  	return &LiteralExpr{
  1386  		Val: n,
  1387  	}
  1388  }
  1389  
  1390  func (e *LiteralExpr) String() string {
  1391  	return fmt.Sprint(e.Val)
  1392  }
  1393  
  1394  // literlExpr impls SampleExpr & LogSelectorExpr mainly to reduce the need for more complicated typings
  1395  // to facilitate sum types. We'll be type switching when evaluating them anyways
  1396  // and they will only be present in binary operation legs.
  1397  func (e *LiteralExpr) Selector() LogSelectorExpr               { return e }
  1398  func (e *LiteralExpr) HasFilter() bool                         { return false }
  1399  func (e *LiteralExpr) Shardable() bool                         { return true }
  1400  func (e *LiteralExpr) Walk(f WalkFn)                           { f(e) }
  1401  func (e *LiteralExpr) Pipeline() (log.Pipeline, error)         { return log.NewNoopPipeline(), nil }
  1402  func (e *LiteralExpr) Matchers() []*labels.Matcher             { return nil }
  1403  func (e *LiteralExpr) MatcherGroups() []MatcherRange           { return nil }
  1404  func (e *LiteralExpr) Extractor() (log.SampleExtractor, error) { return nil, nil }
  1405  func (e *LiteralExpr) Value() float64                          { return e.Val }
  1406  
  1407  // helper used to impl Stringer for vector and range aggregations
  1408  // nolint:interfacer
  1409  func formatOperation(op string, grouping *Grouping, params ...string) string {
  1410  	nonEmptyParams := make([]string, 0, len(params))
  1411  	for _, p := range params {
  1412  		if p != "" {
  1413  			nonEmptyParams = append(nonEmptyParams, p)
  1414  		}
  1415  	}
  1416  
  1417  	var sb strings.Builder
  1418  	sb.WriteString(op)
  1419  	if grouping != nil {
  1420  		sb.WriteString(grouping.String())
  1421  	}
  1422  	sb.WriteString("(")
  1423  	sb.WriteString(strings.Join(nonEmptyParams, ","))
  1424  	sb.WriteString(")")
  1425  	return sb.String()
  1426  }
  1427  
  1428  type LabelReplaceExpr struct {
  1429  	Left        SampleExpr
  1430  	Dst         string
  1431  	Replacement string
  1432  	Src         string
  1433  	Regex       string
  1434  	Re          *regexp.Regexp
  1435  
  1436  	implicit
  1437  }
  1438  
  1439  func mustNewLabelReplaceExpr(left SampleExpr, dst, replacement, src, regex string) *LabelReplaceExpr {
  1440  	re, err := regexp.Compile("^(?:" + regex + ")$")
  1441  	if err != nil {
  1442  		panic(logqlmodel.NewParseError(fmt.Sprintf("invalid regex in label_replace: %s", err.Error()), 0, 0))
  1443  	}
  1444  	return &LabelReplaceExpr{
  1445  		Left:        left,
  1446  		Dst:         dst,
  1447  		Replacement: replacement,
  1448  		Src:         src,
  1449  		Re:          re,
  1450  		Regex:       regex,
  1451  	}
  1452  }
  1453  
  1454  func (e *LabelReplaceExpr) Selector() LogSelectorExpr {
  1455  	return e.Left.Selector()
  1456  }
  1457  
  1458  func (e *LabelReplaceExpr) MatcherGroups() []MatcherRange {
  1459  	return e.Left.MatcherGroups()
  1460  }
  1461  
  1462  func (e *LabelReplaceExpr) Extractor() (SampleExtractor, error) {
  1463  	return e.Left.Extractor()
  1464  }
  1465  
  1466  func (e *LabelReplaceExpr) Shardable() bool {
  1467  	return false
  1468  }
  1469  
  1470  func (e *LabelReplaceExpr) Walk(f WalkFn) {
  1471  	f(e)
  1472  	if e.Left == nil {
  1473  		return
  1474  	}
  1475  	e.Left.Walk(f)
  1476  }
  1477  
  1478  func (e *LabelReplaceExpr) String() string {
  1479  	var sb strings.Builder
  1480  	sb.WriteString(OpLabelReplace)
  1481  	sb.WriteString("(")
  1482  	sb.WriteString(e.Left.String())
  1483  	sb.WriteString(",")
  1484  	sb.WriteString(strconv.Quote(e.Dst))
  1485  	sb.WriteString(",")
  1486  	sb.WriteString(strconv.Quote(e.Replacement))
  1487  	sb.WriteString(",")
  1488  	sb.WriteString(strconv.Quote(e.Src))
  1489  	sb.WriteString(",")
  1490  	sb.WriteString(strconv.Quote(e.Regex))
  1491  	sb.WriteString(")")
  1492  	return sb.String()
  1493  }
  1494  
  1495  // shardableOps lists the operations which may be sharded.
  1496  // topk, botk, max, & min all must be concatenated and then evaluated in order to avoid
  1497  // potential data loss due to series distribution across shards.
  1498  // For example, grouping by `cluster` for a `max` operation may yield
  1499  // 2 results on the first shard and 10 results on the second. If we prematurely
  1500  // calculated `max`s on each shard, the shard/label combination with `2` may be
  1501  // discarded and some other combination with `11` may be reported falsely as the max.
  1502  //
  1503  // Explanation: this is my (owen-d) best understanding.
  1504  //
  1505  // For an operation to be shardable, first the sample-operation itself must be associative like (+, *) but not (%, /, ^).
  1506  // Secondly, if the operation is part of a vector aggregation expression or utilizes logical/set binary ops,
  1507  // the vector operation must be distributive over the sample-operation.
  1508  // This ensures that the vector merging operation can be applied repeatedly to data in different shards.
  1509  // references:
  1510  // https://en.wikipedia.org/wiki/Associative_property
  1511  // https://en.wikipedia.org/wiki/Distributive_property
  1512  var shardableOps = map[string]bool{
  1513  	// vector ops
  1514  	OpTypeSum: true,
  1515  	// avg is only marked as shardable because we remap it into sum/count.
  1516  	OpTypeAvg:   true,
  1517  	OpTypeCount: true,
  1518  
  1519  	// range vector ops
  1520  	OpRangeTypeCount:     true,
  1521  	OpRangeTypeRate:      true,
  1522  	OpRangeTypeBytes:     true,
  1523  	OpRangeTypeBytesRate: true,
  1524  	OpRangeTypeSum:       true,
  1525  	OpRangeTypeMax:       true,
  1526  	OpRangeTypeMin:       true,
  1527  
  1528  	// binops - arith
  1529  	OpTypeAdd: true,
  1530  	OpTypeMul: true,
  1531  }
  1532  
  1533  type MatcherRange struct {
  1534  	Matchers         []*labels.Matcher
  1535  	Interval, Offset time.Duration
  1536  }
  1537  
  1538  func MatcherGroups(expr Expr) []MatcherRange {
  1539  	switch e := expr.(type) {
  1540  	case SampleExpr:
  1541  		return e.MatcherGroups()
  1542  	case LogSelectorExpr:
  1543  		if xs := e.Matchers(); len(xs) > 0 {
  1544  			return []MatcherRange{
  1545  				{
  1546  					Matchers: xs,
  1547  				},
  1548  			}
  1549  		}
  1550  		return nil
  1551  	default:
  1552  		return nil
  1553  	}
  1554  }