Skip to content

Commit 7eefa33

Browse files
committed
feat(frontend/tf): add RemoveInheritedTagsVisitor
1 parent 64f1cd0 commit 7eefa33

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

hack/tfconfig.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ batches:
138138
steps:
139139
- kind: ClusterNameVisitor
140140
- kind: PruneTagsVisitor
141+
- kind: RemoveInheritedTagVisitor
142+
traceSources:
141143
- name: collapse
142144
steps:
143145
- kind: CollapseNestingVisitor

pkg/frontend/tf/defaults/step/prune_tags.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package tfstep
1616

1717
import (
18+
"bytes"
1819
"fmt"
1920
"strings"
2021

@@ -23,6 +24,7 @@ import (
2324
tfconfig "github.com/kubewharf/kelemetry/pkg/frontend/tf/config"
2425
tftree "github.com/kubewharf/kelemetry/pkg/frontend/tf/tree"
2526
"github.com/kubewharf/kelemetry/pkg/manager"
27+
utilmarshal "github.com/kubewharf/kelemetry/pkg/util/marshal"
2628
"github.com/kubewharf/kelemetry/pkg/util/zconstants"
2729
)
2830

@@ -37,6 +39,11 @@ func init() {
3739
manager.Ptr(&tfconfig.VisitorStep[PruneTagsVisitor]{}),
3840
&manager.List[tfconfig.RegisteredStep]{},
3941
)
42+
manager.Global.ProvideListImpl(
43+
"tf-step/remove-inherited-tag-visitor",
44+
manager.Ptr(&tfconfig.VisitorStep[RemoveInheritedTagVisitor]{}),
45+
&manager.List[tfconfig.RegisteredStep]{},
46+
)
4047
}
4148

4249
type ReplaceNameVisitor struct{}
@@ -92,3 +99,74 @@ func removeZconstantKeys(tags model.KeyValues) model.KeyValues {
9299
}
93100
return newTags
94101
}
102+
103+
// An inherited tag is a tag in a span/log that also appears in its parent/owning span with the same key and value.
104+
// These tags are often useless and may be removed for brevity.
105+
//
106+
// This visitor assumes that each tag only appears once.
107+
type RemoveInheritedTagVisitor struct {
108+
// Spans with a matching traceSource tag (empty string for extension spans) will have inherited tags removed.
109+
TraceSources utilmarshal.StringFilter `json:"traceSources"`
110+
111+
// Whether to remove inherited span tags for matched spans.
112+
Spans bool `json:"spans"`
113+
// Whether to remove inherited log tags for matched spans.
114+
Logs bool `json:"logs"`
115+
116+
parentTags map[string]any
117+
}
118+
119+
func (visitor RemoveInheritedTagVisitor) Kind() string { return "RemoveInheritedTagVisitor" }
120+
121+
func removeInherited(parentTags map[string]any, tags []model.KeyValue) []model.KeyValue {
122+
outTags := []model.KeyValue{}
123+
124+
for _, tag := range tags {
125+
if parentValue, parentHasKey := parentTags[tag.Key]; parentHasKey {
126+
var equal bool
127+
if binary, isBinary := parentValue.([]byte); isBinary && tag.VType == model.BinaryType {
128+
equal = bytes.Equal(binary, tag.VBinary)
129+
} else {
130+
equal = parentValue == tag.Value()
131+
}
132+
133+
if !equal {
134+
outTags = append(outTags, tag)
135+
}
136+
}
137+
}
138+
139+
return outTags
140+
}
141+
142+
func (visitor RemoveInheritedTagVisitor) Enter(tree *tftree.SpanTree, span *model.Span) tftree.TreeVisitor {
143+
spanTags := make(map[string]any, len(span.Tags))
144+
var traceSource string
145+
for _, tag := range span.Tags {
146+
spanTags[tag.Key] = tag.Value()
147+
if tag.Key == zconstants.TraceSource {
148+
traceSource = tag.VStr
149+
}
150+
}
151+
152+
if visitor.TraceSources.Matches(traceSource) {
153+
if visitor.Spans {
154+
span.Tags = removeInherited(visitor.parentTags, span.Tags)
155+
}
156+
157+
if visitor.Logs {
158+
for i := range span.Logs {
159+
log := &span.Logs[i]
160+
log.Fields = removeInherited(spanTags, log.Fields)
161+
}
162+
}
163+
}
164+
165+
return RemoveInheritedTagVisitor{
166+
TraceSources: visitor.TraceSources,
167+
Logs: visitor.Logs,
168+
parentTags: spanTags,
169+
}
170+
}
171+
172+
func (visitor RemoveInheritedTagVisitor) Exit(tree *tftree.SpanTree, span *model.Span) {}

0 commit comments

Comments
 (0)