Skip to content

Commit b27ccc6

Browse files
authored
[processor/datadogsemantics] Clean up datadogsemanticsprocessor traces code (#39564)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Clean up code for traces in datadogsemanticsprocessor. Small functionality changes: - If there are fields that start with `datadog.*` that aren't set by the processor, the "overrideIncomingDatadogFields" option would remove them in the previous version. This is no longer the case, they will get left alone. - "datadog.[service|env|version]" are now written to resource attributes instead of span attributes. This write only happens once. - Changed override logic for `datadog.host.name` to align with other fields. in the previous version, the value in `datadog.host.name` was respected even if "overrideIncomingDatadogFields" is set, which is different than all other `datadog.*` namespaced attributes. The rationale was that `datadog.host.name` is a canonical way to set host name outside of the processor, so it should work regardless of the override setting - however, it would be confusing for this one attribute to be different, and it's fair to assume users know what they're doing if they opt in to `overrideIncomingDatadogFields` <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes <!--Describe what testing was performed and which tests were added.--> #### Testing Changed unit tests and verified by running processor locally <!--Describe the documentation added.--> #### Documentation <!--Please delete paragraphs that you did not use before submitting.-->
1 parent 9a57b62 commit b27ccc6

File tree

2 files changed

+99
-112
lines changed

2 files changed

+99
-112
lines changed

processor/datadogsemanticsprocessor/processor.go

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616
semconv "go.opentelemetry.io/collector/semconv/v1.27.0"
1717
)
1818

19-
func insertAttrIfMissing(sattr pcommon.Map, key string, value any) (err error) {
20-
if _, ok := sattr.Get(key); !ok {
19+
func (tp *tracesProcessor) insertAttrIfMissingOrShouldOverride(sattr pcommon.Map, key string, value any) (err error) {
20+
if _, ok := sattr.Get(key); tp.overrideIncomingDatadogFields || !ok {
2121
switch v := value.(type) {
2222
case string:
2323
sattr.PutStr(key, v)
@@ -37,74 +37,73 @@ func (tp *tracesProcessor) processTraces(ctx context.Context, td ptrace.Traces)
3737
otelres := rspan.Resource()
3838
rattr := otelres.Attributes()
3939
for j := 0; j < rspan.ScopeSpans().Len(); j++ {
40-
libspans := rspan.ScopeSpans().At(j)
41-
for k := 0; k < libspans.Spans().Len(); k++ {
42-
otelspan := libspans.Spans().At(k)
43-
sattr := otelspan.Attributes()
44-
if tp.overrideIncomingDatadogFields {
45-
sattr.RemoveIf(func(k string, _ pcommon.Value) bool {
46-
return strings.HasPrefix(k, "datadog.")
47-
})
48-
if ddHostname, ok := rattr.Get("datadog.host.name"); ok && ddHostname.AsString() == "" {
49-
rattr.Remove("datadog.host.name")
50-
}
51-
}
52-
if err = insertAttrIfMissing(sattr, "datadog.service", traceutil.GetOTelService(otelres, true)); err != nil {
40+
if service := traceutil.GetOTelService(otelres, true); service != "" {
41+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.service", service); err != nil {
5342
return ptrace.Traces{}, err
5443
}
55-
if err = insertAttrIfMissing(sattr, "datadog.name", traceutil.GetOTelOperationNameV2(otelspan)); err != nil {
44+
}
45+
if serviceVersion, ok := otelres.Attributes().Get(semconv.AttributeServiceVersion); ok {
46+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.version", serviceVersion.AsString()); err != nil {
5647
return ptrace.Traces{}, err
5748
}
58-
if err = insertAttrIfMissing(sattr, "datadog.resource", traceutil.GetOTelResourceV2(otelspan, otelres)); err != nil {
49+
}
50+
if env := traceutil.GetOTelEnv(otelres); env != "" {
51+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.env", env); err != nil {
5952
return ptrace.Traces{}, err
6053
}
61-
if err = insertAttrIfMissing(sattr, "datadog.type", traceutil.GetOTelSpanType(otelspan, otelres)); err != nil {
54+
}
55+
56+
if tp.overrideIncomingDatadogFields {
57+
rattr.Remove("datadog.host.name")
58+
}
59+
60+
if src, ok := tp.attrsTranslator.ResourceToSource(ctx, otelres, traceutil.SignalTypeSet, nil); ok && src.Kind == source.HostnameKind {
61+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.host.name", src.Identifier); err != nil {
6262
return ptrace.Traces{}, err
6363
}
64-
if src, ok := tp.attrsTranslator.ResourceToSource(ctx, otelres, traceutil.SignalTypeSet, nil); ok && src.Kind == source.HostnameKind {
65-
if err = insertAttrIfMissing(otelres.Attributes(), "datadog.host.name", src.Identifier); err != nil {
66-
return ptrace.Traces{}, err
67-
}
68-
}
64+
}
6965

70-
spanKind := otelspan.Kind()
71-
if err = insertAttrIfMissing(sattr, "datadog.span.kind", traceutil.OTelSpanKindName(spanKind)); err != nil {
66+
libspans := rspan.ScopeSpans().At(j)
67+
for k := 0; k < libspans.Spans().Len(); k++ {
68+
otelspan := libspans.Spans().At(k)
69+
sattr := otelspan.Attributes()
70+
71+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.name", traceutil.GetOTelOperationNameV2(otelspan)); err != nil {
7272
return ptrace.Traces{}, err
7373
}
74-
if env := traceutil.GetOTelEnv(otelres); env != "" {
75-
if err = insertAttrIfMissing(sattr, "datadog.env", env); err != nil {
76-
return ptrace.Traces{}, err
77-
}
74+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.resource", traceutil.GetOTelResourceV2(otelspan, otelres)); err != nil {
75+
return ptrace.Traces{}, err
7876
}
79-
if serviceVersion, ok := otelres.Attributes().Get(semconv.AttributeServiceVersion); ok {
80-
if err = insertAttrIfMissing(sattr, "datadog.version", serviceVersion.AsString()); err != nil {
81-
return ptrace.Traces{}, err
82-
}
77+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.type", traceutil.GetOTelSpanType(otelspan, otelres)); err != nil {
78+
return ptrace.Traces{}, err
79+
}
80+
spanKind := otelspan.Kind()
81+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.span.kind", traceutil.OTelSpanKindName(spanKind)); err != nil {
82+
return ptrace.Traces{}, err
8383
}
84-
8584
metaMap := make(map[string]string)
8685
code := traceutil.GetOTelStatusCode(otelspan)
8786
if code != 0 {
88-
if err = insertAttrIfMissing(sattr, "datadog.http_status_code", fmt.Sprintf("%d", code)); err != nil {
87+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.http_status_code", fmt.Sprintf("%d", code)); err != nil {
8988
return ptrace.Traces{}, err
9089
}
9190
}
9291
ddError := int64(status2Error(otelspan.Status(), otelspan.Events(), metaMap))
93-
if err = insertAttrIfMissing(sattr, "datadog.error", ddError); err != nil {
92+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error", ddError); err != nil {
9493
return ptrace.Traces{}, err
9594
}
9695
if metaMap["error.msg"] != "" {
97-
if err = insertAttrIfMissing(sattr, "datadog.error.msg", metaMap["error.msg"]); err != nil {
96+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.msg", metaMap["error.msg"]); err != nil {
9897
return ptrace.Traces{}, err
9998
}
10099
}
101100
if metaMap["error.type"] != "" {
102-
if err = insertAttrIfMissing(sattr, "datadog.error.type", metaMap["error.type"]); err != nil {
101+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.type", metaMap["error.type"]); err != nil {
103102
return ptrace.Traces{}, err
104103
}
105104
}
106105
if metaMap["error.stack"] != "" {
107-
if err = insertAttrIfMissing(sattr, "datadog.error.stack", metaMap["error.stack"]); err != nil {
106+
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.stack", metaMap["error.stack"]); err != nil {
108107
return ptrace.Traces{}, err
109108
}
110109
}

processor/datadogsemanticsprocessor/processor_test.go

Lines changed: 61 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"go.opentelemetry.io/collector/component/componentstatus"
1515
"go.opentelemetry.io/collector/consumer"
1616
"go.opentelemetry.io/collector/consumer/consumertest"
17+
"go.opentelemetry.io/collector/pdata/pcommon"
1718
"go.opentelemetry.io/collector/pdata/ptrace"
1819
"go.opentelemetry.io/collector/processor"
1920
"go.opentelemetry.io/collector/processor/processortest"
@@ -104,6 +105,12 @@ func TestNilBatch(t *testing.T) {
104105
m.assertBatchesLen(1)
105106
}
106107

108+
func assertKeyInAttributesMatchesValue(t *testing.T, attr pcommon.Map, key string, expected string) {
109+
v, ok := attr.Get(key)
110+
require.True(t, ok)
111+
require.Equal(t, expected, v.AsString())
112+
}
113+
107114
func TestBasicTranslation(t *testing.T) {
108115
tests := []struct {
109116
name string
@@ -143,35 +150,27 @@ func TestBasicTranslation(t *testing.T) {
143150
},
144151
fn: func(out *ptrace.Traces) {
145152
rs := out.ResourceSpans().At(0)
146-
res := rs.Resource()
153+
rattr := rs.Resource().Attributes()
154+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.service", "test-service")
155+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.env", "spanenv2")
156+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.version", "v2")
157+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.host.name", "test-host-name")
158+
147159
span := rs.ScopeSpans().At(0).Spans().At(0)
148-
ddservice, _ := span.Attributes().Get("datadog.service")
149-
require.Equal(t, "test-service", ddservice.AsString())
150-
ddname, _ := span.Attributes().Get("datadog.name")
151-
require.Equal(t, "test-operation", ddname.AsString())
152-
ddresource, _ := span.Attributes().Get("datadog.resource")
153-
require.Equal(t, "test-resource", ddresource.AsString())
154-
ddType, _ := span.Attributes().Get("datadog.type")
155-
require.Equal(t, "web", ddType.AsString())
156-
ddSpanKind, _ := span.Attributes().Get("datadog.span.kind")
157-
require.Equal(t, "server", ddSpanKind.AsString())
158-
env, _ := span.Attributes().Get("datadog.env")
159-
require.Equal(t, "spanenv2", env.AsString())
160-
version, _ := span.Attributes().Get("datadog.version")
161-
require.Equal(t, "v2", version.AsString())
162-
statusCode, _ := span.Attributes().Get("datadog.http_status_code")
163-
require.Equal(t, "200", statusCode.AsString())
164-
ddError, _ := span.Attributes().Get("datadog.error")
160+
sattr := span.Attributes()
161+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.name", "test-operation")
162+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.resource", "test-resource")
163+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.type", "web")
164+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.span.kind", "server")
165+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.http_status_code", "200")
166+
ddError, _ := sattr.Get("datadog.error")
165167
require.Equal(t, int64(0), ddError.Int())
166-
_, ok := span.Attributes().Get("datadog.error.msg")
168+
_, ok := sattr.Get("datadog.error.msg")
167169
require.False(t, ok)
168-
_, ok = span.Attributes().Get("datadog.error.type")
170+
_, ok = sattr.Get("datadog.error.type")
169171
require.False(t, ok)
170-
_, ok = span.Attributes().Get("datadog.error.stack")
172+
_, ok = sattr.Get("datadog.error.stack")
171173
require.False(t, ok)
172-
173-
ddHost, _ := res.Attributes().Get("datadog.host.name")
174-
require.Equal(t, "test-host-name", ddHost.AsString())
175174
},
176175
},
177176
{
@@ -186,7 +185,9 @@ func TestBasicTranslation(t *testing.T) {
186185
"resource.name": "test-resource",
187186
"deployment.environment.name": "spanenv2",
188187
"host.name": "overridden-host-name",
189-
"datadog.host.name": "",
188+
"datadog.host.name": "specified-host-name",
189+
"datadog.version": "specified-version",
190+
"service.version": "overridden-version",
190191
},
191192
Spans: []*testutil.OTLPSpan{
192193
{
@@ -216,7 +217,6 @@ func TestBasicTranslation(t *testing.T) {
216217
"datadog.host.name": "specified-hostname",
217218
"datadog.span.kind": "specified-span-kind",
218219
"datadog.env": "specified-env",
219-
"datadog.version": "specified-version",
220220
"datadog.http_status_code": "500",
221221
"datadog.error": 1,
222222
"datadog.error.msg": "specified-error-msg",
@@ -231,30 +231,24 @@ func TestBasicTranslation(t *testing.T) {
231231
},
232232
fn: func(out *ptrace.Traces) {
233233
rs := out.ResourceSpans().At(0)
234+
rattr := rs.Resource().Attributes()
235+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.service", "test-service")
236+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.env", "spanenv2")
237+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.version", "overridden-version")
238+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.host.name", "overridden-host-name")
239+
234240
span := rs.ScopeSpans().At(0).Spans().At(0)
235-
ddservice, _ := span.Attributes().Get("datadog.service")
236-
require.Equal(t, "test-service", ddservice.AsString())
237-
ddname, _ := span.Attributes().Get("datadog.name")
238-
require.Equal(t, "test-operation", ddname.AsString())
239-
ddresource, _ := span.Attributes().Get("datadog.resource")
240-
require.Equal(t, "test-resource", ddresource.AsString())
241-
ddType, _ := span.Attributes().Get("datadog.type")
242-
require.Equal(t, "web", ddType.AsString())
243-
env, _ := span.Attributes().Get("datadog.env")
244-
require.Equal(t, "spanenv2", env.AsString())
245-
statusCode, _ := span.Attributes().Get("datadog.http_status_code")
246-
require.Equal(t, "200", statusCode.AsString())
247-
ddError, _ := span.Attributes().Get("datadog.error")
241+
sattr := span.Attributes()
242+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.name", "test-operation")
243+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.resource", "test-resource")
244+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.type", "web")
245+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.span.kind", "server")
246+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.http_status_code", "200")
247+
ddError, _ := sattr.Get("datadog.error")
248248
require.Equal(t, int64(1), ddError.Int())
249-
ddErrorMsg, _ := span.Attributes().Get("datadog.error.msg")
250-
require.Equal(t, "overridden-msg", ddErrorMsg.AsString())
251-
ddErrorType, _ := span.Attributes().Get("datadog.error.type")
252-
require.Equal(t, "overridden-type", ddErrorType.AsString())
253-
ddErrorStack, _ := span.Attributes().Get("datadog.error.stack")
254-
require.Equal(t, "overridden-stack", ddErrorStack.AsString())
255-
256-
ddHost, _ := rs.Resource().Attributes().Get("datadog.host.name")
257-
require.Equal(t, "overridden-host-name", ddHost.AsString())
249+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.msg", "overridden-msg")
250+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.type", "overridden-type")
251+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.stack", "overridden-stack")
258252
},
259253
},
260254
{
@@ -265,6 +259,9 @@ func TestBasicTranslation(t *testing.T) {
265259
LibName: "libname",
266260
LibVersion: "1.2",
267261
Attributes: map[string]any{
262+
"datadog.service": "specified-service",
263+
"datadog.env": "specified-env",
264+
"datadog.version": "specified-version",
268265
"service.name": "test-service",
269266
"resource.name": "test-resource",
270267
"deployment.environment.name": "spanenv2",
@@ -292,13 +289,10 @@ func TestBasicTranslation(t *testing.T) {
292289
ParentID: [8]byte{0, 0, 0, 0, 0, 0, 0, 1},
293290
Kind: ptrace.SpanKindServer,
294291
Attributes: map[string]any{
295-
"datadog.service": "specified-service",
296292
"datadog.resource": "specified-resource",
297293
"datadog.name": "specified-operation",
298294
"datadog.type": "specified-type",
299295
"datadog.span.kind": "specified-span-kind",
300-
"datadog.env": "specified-env",
301-
"datadog.version": "specified-version",
302296
"datadog.http_status_code": "500",
303297
"datadog.error": 1,
304298
"datadog.error.msg": "specified-error-msg",
@@ -313,30 +307,24 @@ func TestBasicTranslation(t *testing.T) {
313307
},
314308
fn: func(out *ptrace.Traces) {
315309
rs := out.ResourceSpans().At(0)
310+
rattr := rs.Resource().Attributes()
311+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.service", "specified-service")
312+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.env", "specified-env")
313+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.version", "specified-version")
314+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.host.name", "")
315+
316316
span := rs.ScopeSpans().At(0).Spans().At(0)
317-
ddservice, _ := span.Attributes().Get("datadog.service")
318-
require.Equal(t, "specified-service", ddservice.AsString())
319-
ddname, _ := span.Attributes().Get("datadog.name")
320-
require.Equal(t, "specified-operation", ddname.AsString())
321-
ddresource, _ := span.Attributes().Get("datadog.resource")
322-
require.Equal(t, "specified-resource", ddresource.AsString())
323-
ddType, _ := span.Attributes().Get("datadog.type")
324-
require.Equal(t, "specified-type", ddType.AsString())
325-
env, _ := span.Attributes().Get("datadog.env")
326-
require.Equal(t, "specified-env", env.AsString())
327-
statusCode, _ := span.Attributes().Get("datadog.http_status_code")
328-
require.Equal(t, "500", statusCode.AsString())
329-
ddError, _ := span.Attributes().Get("datadog.error")
317+
sattr := span.Attributes()
318+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.name", "specified-operation")
319+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.resource", "specified-resource")
320+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.type", "specified-type")
321+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.span.kind", "specified-span-kind")
322+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.http_status_code", "500")
323+
ddError, _ := sattr.Get("datadog.error")
330324
require.Equal(t, int64(1), ddError.Int())
331-
ddErrorMsg, _ := span.Attributes().Get("datadog.error.msg")
332-
require.Equal(t, "specified-error-msg", ddErrorMsg.AsString())
333-
ddErrorType, _ := span.Attributes().Get("datadog.error.type")
334-
require.Equal(t, "specified-error-type", ddErrorType.AsString())
335-
ddErrorStack, _ := span.Attributes().Get("datadog.error.stack")
336-
require.Equal(t, "specified-error-stack", ddErrorStack.AsString())
337-
338-
ddHost, _ := rs.Resource().Attributes().Get("datadog.host.name")
339-
require.Empty(t, ddHost.AsString())
325+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.msg", "specified-error-msg")
326+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.type", "specified-error-type")
327+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.stack", "specified-error-stack")
340328
},
341329
},
342330
}

0 commit comments

Comments
 (0)