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/optimize.go

89 lines
2.5 KiB

package logql
import "github.com/grafana/loki/pkg/logql/syntax"
// optimizeSampleExpr Attempt to optimize the SampleExpr to another that will run faster but will produce the same result.
func optimizeSampleExpr(expr syntax.SampleExpr) (syntax.SampleExpr, error) {
var skip bool
// we skip sharding AST for now, it's not easy to clone them since they are not part of the language.
expr.Walk(func(e interface{}) {
switch e.(type) {
case *ConcatSampleExpr, *DownstreamSampleExpr:
skip = true
return
}
})
if skip {
return expr, nil
}
// clone the expr.
q := expr.String()
expr, err := syntax.ParseSampleExpr(q)
if err != nil {
return nil, err
}
removeLineformat(expr)
return expr, nil
}
// removeLineformat removes unnecessary line_format within a SampleExpr.
func removeLineformat(expr syntax.SampleExpr) {
expr.Walk(func(e interface{}) {
rangeExpr, ok := e.(*syntax.RangeAggregationExpr)
if !ok {
return
}
// bytes operation count bytes of the log line so line_format changes the result.
if rangeExpr.Operation == syntax.OpRangeTypeBytes ||
rangeExpr.Operation == syntax.OpRangeTypeBytesRate {
return
}
pipelineExpr, ok := rangeExpr.Left.Left.(*syntax.PipelineExpr)
if !ok {
return
}
temp := pipelineExpr.MultiStages[:0]
for i, s := range pipelineExpr.MultiStages {
_, ok := s.(*syntax.LineFmtExpr)
if !ok {
temp = append(temp, s)
continue
}
// we found a lineFmtExpr, we need to check if it's followed by a labelParser or lineFilter
// in which case it could be useful for further processing.
var found bool
for j := i; j < len(pipelineExpr.MultiStages); j++ {
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LogfmtParserExpr); ok {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LabelParserExpr); ok {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LineFilterExpr); ok {
found = true
break
}
if _, ok := pipelineExpr.MultiStages[j].(*syntax.JSONExpressionParser); ok {
found = true
break
}
Add logfmt selective label extraction (#6675) <!-- Thanks for sending a pull request! Before submitting: 1. Read our CONTRIBUTING.md guide 2. Name your PR as `<Feature Area>: Describe your change`. a. Do not end the title with punctuation. It will be added in the changelog. b. Start with an imperative verb. Example: Fix the latency between System A and System B. c. Use sentence case, not title case. d. Use a complete phrase or sentence. The PR title will appear in a changelog, so help other people understand what your change will be. 3. Rebase your PR if it gets out of sync with main --> **What this PR does / why we need it**: This PR introduces extracting labels from a log line in `logfmt`, with an extra option to rename them. For example, this query: ``` {app=”foo”} | logfmt msg,status ``` will extract the labels `msg` and `status` from the following logfmt line: ``` level=error ts=2021-02-12T19:18:10.037940878Z caller=client.go:294 component=client host=observability-loki-gateway msg="final error sending batch" status=400 error="server returned HTTP status 400 Bad Request (400): entry with timestamp 2021-02-12 19:18:08.917452 +0000 UTC ignored, reason: 'entry out of order' for stream..." ``` With the following results: ``` msg="final error sending batch" status=”400” ``` -------------- Another possible scenario with label renaming: ``` {app=”foo”} | logfmt message="msg", status ``` That produces the following results: ``` message="final error sending batch" status=”400” ``` **Which issue(s) this PR fixes**: Fixes #3355 **Special notes for your reviewer**: <!-- Note about CHANGELOG entries, if a change adds: * an important feature * fixes an issue present in a previous release, * causes a change in operation that would be useful for an operator of Loki to know then please add a CHANGELOG entry. For documentation changes, build changes, simple fixes etc please skip this step. We are attempting to curate a changelog of the most relevant and important changes to be easier to ingest by end users of Loki. Note about the upgrade guide, if this changes: * default configuration values * metric names or label names * changes existing log lines such as the metrics.go query output line * configuration parameters * anything to do with any API * any other change that would require special attention or extra steps to upgrade Please document clearly what changed AND what needs to be done in the upgrade guide. --> **Checklist** - [x] Documentation added - [x] Tests updated - [x] Is this an important fix or new feature? Add an entry in the `CHANGELOG.md`. - [x] Changes that require user attention or interaction to upgrade are documented in `docs/sources/upgrading/_index.md` --------- Signed-off-by: Christian Haudum <christian.haudum@gmail.com> Co-authored-by: Christian Haudum <christian.haudum@gmail.com>
2 years ago
if _, ok := pipelineExpr.MultiStages[j].(*syntax.LogfmtExpressionParser); ok {
found = true
break
}
}
if found {
// we cannot remove safely the linefmtExpr.
temp = append(temp, s)
}
}
pipelineExpr.MultiStages = temp
// transform into a matcherExpr if there's no more pipeline.
if len(pipelineExpr.MultiStages) == 0 {
rangeExpr.Left.Left = &syntax.MatchersExpr{Mts: rangeExpr.Left.Left.Matchers()}
}
})
}