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

315 lines
7.3 KiB

package syntax
import (
"github.com/prometheus/prometheus/model/labels"
"github.com/grafana/loki/v3/pkg/logql/log"
)
type cloneVisitor struct {
cloned Expr
}
var _ RootVisitor = &cloneVisitor{}
func cloneGrouping(g *Grouping) *Grouping {
copied := &Grouping{
Without: g.Without,
}
if g.Groups != nil {
copied.Groups = make([]string, len(g.Groups))
copy(copied.Groups, g.Groups)
}
return copied
}
func cloneVectorMatching(v *VectorMatching) *VectorMatching {
copied := *v
copy(copied.Include, v.Include)
copy(copied.MatchingLabels, v.MatchingLabels)
return &copied
}
func (v *cloneVisitor) VisitBinOp(e *BinOpExpr) {
lhs := MustClone[SampleExpr](e.SampleExpr)
rhs := MustClone[SampleExpr](e.RHS)
copied := &BinOpExpr{
SampleExpr: lhs,
RHS: rhs,
Op: e.Op,
}
if e.Opts != nil {
copied.Opts = &BinOpOptions{
ReturnBool: e.Opts.ReturnBool,
VectorMatching: cloneVectorMatching(e.Opts.VectorMatching),
}
}
v.cloned = copied
}
func (v *cloneVisitor) VisitVectorAggregation(e *VectorAggregationExpr) {
copied := &VectorAggregationExpr{
Left: MustClone[SampleExpr](e.Left),
Params: e.Params,
Operation: e.Operation,
}
if e.Grouping != nil {
copied.Grouping = cloneGrouping(e.Grouping)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitRangeAggregation(e *RangeAggregationExpr) {
copied := &RangeAggregationExpr{
Left: MustClone[*LogRangeExpr](e.Left),
Operation: e.Operation,
}
if e.Grouping != nil {
copied.Grouping = cloneGrouping(e.Grouping)
}
if e.Params != nil {
tmp := *e.Params
copied.Params = &tmp
}
v.cloned = copied
}
func (v *cloneVisitor) VisitLabelReplace(e *LabelReplaceExpr) {
left := MustClone[SampleExpr](e.Left)
v.cloned = mustNewLabelReplaceExpr(left, e.Dst, e.Replacement, e.Src, e.Regex)
}
func (v *cloneVisitor) VisitLiteral(e *LiteralExpr) {
v.cloned = &LiteralExpr{Val: e.Val}
}
func (v *cloneVisitor) VisitVector(e *VectorExpr) {
v.cloned = &VectorExpr{Val: e.Val}
}
func (v *cloneVisitor) VisitLogRange(e *LogRangeExpr) {
copied := &LogRangeExpr{
Left: MustClone[LogSelectorExpr](e.Left),
Interval: e.Interval,
Offset: e.Offset,
}
if e.Unwrap != nil {
copied.Unwrap = &UnwrapExpr{
Identifier: e.Unwrap.Identifier,
Operation: e.Unwrap.Operation,
}
if e.Unwrap.PostFilters != nil {
copied.Unwrap.PostFilters = make([]log.LabelFilterer, len(e.Unwrap.PostFilters))
for i, f := range e.Unwrap.PostFilters {
copied.Unwrap.PostFilters[i] = cloneLabelFilterer(f)
}
}
}
v.cloned = copied
}
func (v *cloneVisitor) VisitMatchers(e *MatchersExpr) {
copied := &MatchersExpr{
Mts: make([]*labels.Matcher, len(e.Mts)),
}
for i, m := range e.Mts {
copied.Mts[i] = labels.MustNewMatcher(m.Type, m.Name, m.Value)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitPipeline(e *PipelineExpr) {
copied := &PipelineExpr{
Left: MustClone[*MatchersExpr](e.Left),
MultiStages: make(MultiStageExpr, len(e.MultiStages)),
}
for i, s := range e.MultiStages {
copied.MultiStages[i] = MustClone[StageExpr](s)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitDecolorize(*DecolorizeExpr) {
v.cloned = &DecolorizeExpr{}
}
func (v *cloneVisitor) VisitDropLabels(e *DropLabelsExpr) {
copied := &DropLabelsExpr{
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.NewNamedLabelMatcher(matcher, l.Name)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitJSONExpressionParser(e *JSONExpressionParserExpr) {
copied := &JSONExpressionParserExpr{
Expressions: make([]log.LabelExtractionExpr, len(e.Expressions)),
}
copy(copied.Expressions, e.Expressions)
v.cloned = copied
}
func (v *cloneVisitor) VisitKeepLabel(e *KeepLabelsExpr) {
copied := &KeepLabelsExpr{
keepLabels: make([]log.NamedLabelMatcher, len(e.keepLabels)),
}
for i, k := range e.keepLabels {
copied.keepLabels[i] = log.NamedLabelMatcher{
Name: k.Name,
}
if k.Matcher != nil {
copied.keepLabels[i].Matcher = labels.MustNewMatcher(k.Matcher.Type, k.Matcher.Name, k.Matcher.Value)
}
}
v.cloned = copied
}
func (v *cloneVisitor) VisitLabelFilter(e *LabelFilterExpr) {
v.cloned = &LabelFilterExpr{
LabelFilterer: cloneLabelFilterer(e.LabelFilterer),
}
}
func cloneLabelFilterer(filter log.LabelFilterer) log.LabelFilterer {
switch concrete := filter.(type) {
case *log.BinaryLabelFilter:
return &log.BinaryLabelFilter{
Left: cloneLabelFilterer(concrete.Left),
Right: cloneLabelFilterer(concrete.Right),
And: concrete.And,
}
case *log.NoopLabelFilter:
copied := &log.NoopLabelFilter{}
if concrete.Matcher != nil {
copied.Matcher = mustNewMatcher(concrete.Type, concrete.Name, concrete.Value)
}
return copied
case *log.BytesLabelFilter:
return &log.BytesLabelFilter{
Name: concrete.Name,
Value: concrete.Value,
Type: concrete.Type,
}
case *log.DurationLabelFilter:
return &log.DurationLabelFilter{
Name: concrete.Name,
Value: concrete.Value,
Type: concrete.Type,
}
case *log.NumericLabelFilter:
return &log.NumericLabelFilter{
Name: concrete.Name,
Value: concrete.Value,
Type: concrete.Type,
}
case *log.StringLabelFilter:
copied := &log.StringLabelFilter{}
if concrete.Matcher != nil {
copied.Matcher = mustNewMatcher(concrete.Type, concrete.Name, concrete.Value)
}
return copied
case *log.LineFilterLabelFilter:
copied := &log.LineFilterLabelFilter{
Filter: concrete.Filter,
}
if concrete.Matcher != nil {
copied.Matcher = mustNewMatcher(concrete.Type, concrete.Name, concrete.Value)
}
return copied
case *log.IPLabelFilter:
return log.NewIPLabelFilter(concrete.Pattern, concrete.Label, concrete.Ty)
}
return nil
}
func (v *cloneVisitor) VisitLabelFmt(e *LabelFmtExpr) {
copied := &LabelFmtExpr{
Formats: make([]log.LabelFmt, len(e.Formats)),
}
copy(copied.Formats, e.Formats)
v.cloned = copied
}
func (v *cloneVisitor) VisitLabelParser(e *LineParserExpr) {
v.cloned = &LineParserExpr{
Op: e.Op,
Param: e.Param,
}
}
func (v *cloneVisitor) VisitLineFilter(e *LineFilterExpr) {
copied := &LineFilterExpr{
LineFilter: LineFilter{
Ty: e.Ty,
Match: e.Match,
Op: e.Op,
},
IsOrChild: e.IsOrChild,
}
if e.Left != nil {
copied.Left = MustClone[*LineFilterExpr](e.Left)
}
if e.Or != nil {
copied.Or = MustClone[*LineFilterExpr](e.Or)
}
v.cloned = copied
}
func (v *cloneVisitor) VisitLineFmt(e *LineFmtExpr) {
v.cloned = &LineFmtExpr{Value: e.Value}
}
func (v *cloneVisitor) VisitLogfmtExpressionParser(e *LogfmtExpressionParserExpr) {
copied := &LogfmtExpressionParserExpr{
Expressions: make([]log.LabelExtractionExpr, len(e.Expressions)),
Strict: e.Strict,
KeepEmpty: e.KeepEmpty,
}
copy(copied.Expressions, e.Expressions)
v.cloned = copied
}
func (v *cloneVisitor) VisitLogfmtParser(e *LogfmtParserExpr) {
v.cloned = &LogfmtParserExpr{
Strict: e.Strict,
KeepEmpty: e.KeepEmpty,
}
}
func (v *cloneVisitor) VisitVariants(e *MultiVariantExpr) {
copied := &MultiVariantExpr{
logRange: MustClone[*LogRangeExpr](e.logRange),
variants: make([]SampleExpr, len(e.variants)),
}
for i, v := range e.variants {
copied.variants[i] = MustClone[SampleExpr](v)
}
v.cloned = copied
}