diff --git a/pkg/logql/log/ip.go b/pkg/logql/log/ip.go index cd803e820c10c..1cc27fa01a08f 100644 --- a/pkg/logql/log/ip.go +++ b/pkg/logql/log/ip.go @@ -108,6 +108,8 @@ func (f *IPLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder) ([]byt return line, f.filterTy(line, f.ty, lbs) } +func (f *IPLabelFilter) isLabelFilterer() {} + // `RequiredLabelNames` implements `Stage` interface func (f *IPLabelFilter) RequiredLabelNames() []string { return []string{f.label} diff --git a/pkg/logql/log/label_filter.go b/pkg/logql/log/label_filter.go index 9d8b56c587ac0..90cc99f009fe2 100644 --- a/pkg/logql/log/label_filter.go +++ b/pkg/logql/log/label_filter.go @@ -57,6 +57,9 @@ func (f LabelFilterType) String() string { type LabelFilterer interface { Stage fmt.Stringer + + // Seal trait + isLabelFilterer() } type BinaryLabelFilter struct { @@ -94,6 +97,8 @@ func (b *BinaryLabelFilter) Process(ts int64, line []byte, lbs *LabelsBuilder) ( return line, lok && rok } +func (b *BinaryLabelFilter) isLabelFilterer() {} + func (b *BinaryLabelFilter) RequiredLabelNames() []string { var names []string names = append(names, b.Left.RequiredLabelNames()...) @@ -122,6 +127,9 @@ type NoopLabelFilter struct { func (NoopLabelFilter) Process(_ int64, line []byte, _ *LabelsBuilder) ([]byte, bool) { return line, true } + +func (NoopLabelFilter) isLabelFilterer() {} + func (NoopLabelFilter) RequiredLabelNames() []string { return []string{} } func (f NoopLabelFilter) String() string { @@ -197,6 +205,8 @@ func (d *BytesLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder) ([] } } +func (b *BytesLabelFilter) isLabelFilterer() {} + func (d *BytesLabelFilter) RequiredLabelNames() []string { return []string{d.Name} } @@ -262,6 +272,8 @@ func (d *DurationLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder) } } +func (b *DurationLabelFilter) isLabelFilterer() {} + func (d *DurationLabelFilter) RequiredLabelNames() []string { return []string{d.Name} } @@ -323,6 +335,8 @@ func (n *NumericLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder) ( } +func (n *NumericLabelFilter) isLabelFilterer() {} + func (n *NumericLabelFilter) RequiredLabelNames() []string { return []string{n.Name} } @@ -358,6 +372,8 @@ func (s *StringLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder) ([ return line, s.Matches(labelValue(s.Name, lbs)) } +func (s *StringLabelFilter) isLabelFilterer() {} + func (s *StringLabelFilter) RequiredLabelNames() []string { return []string{s.Name} } @@ -383,6 +399,8 @@ func (s *lineFilterLabelFilter) Process(_ int64, line []byte, lbs *LabelsBuilder return line, s.filter.Filter(unsafeGetBytes(v)) } +func (s *lineFilterLabelFilter) isLabelFilterer() {} + func (s *lineFilterLabelFilter) RequiredLabelNames() []string { return []string{s.Name} } diff --git a/pkg/logql/syntax/serialize.go b/pkg/logql/syntax/serialize.go index 3625c3df0bfe2..4084cd609c0f3 100644 --- a/pkg/logql/syntax/serialize.go +++ b/pkg/logql/syntax/serialize.go @@ -6,6 +6,8 @@ import ( "time" jsoniter "github.com/json-iterator/go" + + "github.com/grafana/loki/pkg/logql/log" ) type JSONSerializer struct { @@ -312,11 +314,11 @@ func encodeUnwrap(s *jsoniter.Stream, u *UnwrapExpr) { s.WriteMore() s.WriteObjectField("post_filterers") s.WriteArrayStart() - for i, group := range u.PostFilters{ + for i, filter := range u.PostFilters { if i > 0 { s.WriteMore() } - s.WriteString(group) + encodePostFilter(s, filter) } s.WriteArrayEnd() @@ -339,6 +341,20 @@ func decodeUnwrap(iter *jsoniter.Iterator) *UnwrapExpr { return e } +func encodePostFilter(s *jsoniter.Stream, filter log.LabelFilterer) { + switch concrete := filter.(type) { + case *log.BinaryLabelFilter: + s.WriteObjectStart() + s.WriteObjectField("left") + encodePostFilter(s, concrete.Left) + + s.WriteMore() + s.WriteObjectField("right") + encodePostFilter(s, concrete.Right) + s.WriteObjectEnd() + } +} + func encodeLogSelector(s *jsoniter.Stream, e LogSelectorExpr) { s.WriteObjectStart() s.WriteObjectField("raw")