Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
loki/pkg/logql/syntax/extractor.go

84 lines
2.4 KiB

package syntax
import (
"fmt"
"sort"
"github.com/grafana/loki/v3/pkg/logql/log"
)
const UnsupportedErr = "unsupported range vector aggregation operation: %s"
func (r RangeAggregationExpr) Extractor() (log.SampleExtractor, error) {
return r.extractor(nil)
}
// extractor creates a SampleExtractor but allows for the grouping to be overridden.
func (r RangeAggregationExpr) extractor(override *Grouping) (log.SampleExtractor, error) {
if r.err != nil {
return nil, r.err
}
if err := r.validate(); err != nil {
return nil, err
}
var groups []string
var without bool
var noLabels bool
// TODO(owen-d|cyriltovena): override grouping (i.e. from a parent `sum`)
// technically can break the query.
// For intance, in `sum by (foo) (max_over_time by (bar) (...))`
// the `by (bar)` grouping in the child is ignored in favor of the parent's `by (foo)`
for _, grp := range []*Grouping{r.Grouping, override} {
if grp != nil {
groups = grp.Groups
without = grp.Without
noLabels = grp.Singleton()
}
}
// absent_over_time cannot be grouped (yet?), so set noLabels=true
// to make extraction more efficient and less likely to strip per query series limits.
if r.Operation == OpRangeTypeAbsent {
noLabels = true
}
sort.Strings(groups)
var stages []log.Stage
if p, ok := r.Left.Left.(*PipelineExpr); ok {
// if the expression is a pipeline then take all stages into account first.
st, err := p.MultiStages.stages()
if err != nil {
return nil, err
}
stages = st
}
// unwrap...means we want to extract metrics from labels.
if r.Left.Unwrap != nil {
var convOp string
switch r.Left.Unwrap.Operation {
case OpConvBytes:
convOp = log.ConvertBytes
case OpConvDuration, OpConvDurationSeconds:
convOp = log.ConvertDuration
default:
convOp = log.ConvertFloat
}
return log.LabelExtractorWithStages(
r.Left.Unwrap.Identifier,
convOp, groups, without, noLabels, stages,
log.ReduceAndLabelFilter(r.Left.Unwrap.PostFilters),
)
}
// otherwise we extract metrics from the log line.
switch r.Operation {
case OpRangeTypeRate, OpRangeTypeCount, OpRangeTypeAbsent:
return log.NewLineSampleExtractor(log.CountExtractor, stages, groups, without, noLabels)
case OpRangeTypeBytes, OpRangeTypeBytesRate:
return log.NewLineSampleExtractor(log.BytesExtractor, stages, groups, without, noLabels)
default:
return nil, fmt.Errorf(UnsupportedErr, r.Operation)
}
}