Skip to content

Commit 4bc0aab

Browse files
IbraheemAmx-psi
andauthored
[processor/datadogsemantics] Make defaults explicit and add test (#39596)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Explicitly set defaults for each field - whatever the Datadog backend would populate if you send the field as blank; e.g., if we send a blank env, it would show up in the UI as the string `default`, so we should surface that to the user with this processor. Also, populate `datadog.*` fields even if they would be blank (this includes overriding them even if the result would be blank if the `overrideIncomingDatadogFields` option is set, for consistency) <!-- 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 <!--Describe the documentation added.--> #### Documentation <!--Please delete paragraphs that you did not use before submitting.--> --------- Co-authored-by: Pablo Baeyens <[email protected]>
1 parent 301fd41 commit 4bc0aab

File tree

2 files changed

+101
-20
lines changed

2 files changed

+101
-20
lines changed

processor/datadogsemanticsprocessor/processor.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,37 @@ 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-
if service := traceutil.GetOTelService(otelres, true); service != "" {
41-
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.service", service); err != nil {
42-
return ptrace.Traces{}, err
43-
}
40+
// Note: default value from GetOTelService is "otlpresourcenoservicename"
41+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.service", traceutil.GetOTelService(otelres, true)); err != nil {
42+
return ptrace.Traces{}, err
4443
}
45-
if serviceVersion, ok := otelres.Attributes().Get(string(semconv.ServiceVersionKey)); ok {
46-
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.version", serviceVersion.AsString()); err != nil {
47-
return ptrace.Traces{}, err
48-
}
44+
45+
serviceVersion := ""
46+
if serviceVersionAttr, ok := otelres.Attributes().Get(string(semconv.ServiceVersionKey)); ok {
47+
serviceVersion = serviceVersionAttr.AsString()
4948
}
50-
if env := traceutil.GetOTelEnv(otelres); env != "" {
51-
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.env", env); err != nil {
52-
return ptrace.Traces{}, err
53-
}
49+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.version", serviceVersion); err != nil {
50+
return ptrace.Traces{}, err
51+
}
52+
53+
env := "default"
54+
if envFromAttr := traceutil.GetOTelEnv(otelres); envFromAttr != "" {
55+
env = envFromAttr
56+
}
57+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.env", env); err != nil {
58+
return ptrace.Traces{}, err
5459
}
5560

5661
if tp.overrideIncomingDatadogFields {
5762
rattr.Remove("datadog.host.name")
5863
}
5964

65+
datadogHostName := ""
6066
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 {
62-
return ptrace.Traces{}, err
63-
}
67+
datadogHostName = src.Identifier
68+
}
69+
if err = tp.insertAttrIfMissingOrShouldOverride(rattr, "datadog.host.name", datadogHostName); err != nil {
70+
return ptrace.Traces{}, err
6471
}
6572

6673
libspans := rspan.ScopeSpans().At(j)
@@ -92,17 +99,13 @@ func (tp *tracesProcessor) processTraces(ctx context.Context, td ptrace.Traces)
9299
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error", ddError); err != nil {
93100
return ptrace.Traces{}, err
94101
}
95-
if metaMap["error.msg"] != "" {
102+
if ddError == 1 {
96103
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.msg", metaMap["error.msg"]); err != nil {
97104
return ptrace.Traces{}, err
98105
}
99-
}
100-
if metaMap["error.type"] != "" {
101106
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.type", metaMap["error.type"]); err != nil {
102107
return ptrace.Traces{}, err
103108
}
104-
}
105-
if metaMap["error.stack"] != "" {
106109
if err = tp.insertAttrIfMissingOrShouldOverride(sattr, "datadog.error.stack", metaMap["error.stack"]); err != nil {
107110
return ptrace.Traces{}, err
108111
}

processor/datadogsemanticsprocessor/processor_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,84 @@ func TestBasicTranslation(t *testing.T) {
251251
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.stack", "overridden-stack")
252252
},
253253
},
254+
{
255+
name: "overrideIncomingDatadogFields even if override would be empty",
256+
overrideIncomingDatadogFields: true,
257+
in: []testutil.OTLPResourceSpan{
258+
{
259+
LibName: "libname",
260+
LibVersion: "1.2",
261+
Attributes: map[string]any{
262+
"service.name": "",
263+
"resource.name": "",
264+
"deployment.environment.name": "",
265+
"host.name": "",
266+
"service.version": "",
267+
"datadog.env": "specified-host-name",
268+
"datadog.host.name": "specified-host-name",
269+
"datadog.version": "specified-version",
270+
},
271+
Spans: []*testutil.OTLPSpan{
272+
{
273+
Events: []testutil.OTLPSpanEvent{
274+
{
275+
Timestamp: 66,
276+
Name: "exception",
277+
Attributes: map[string]any{
278+
string(semconv.ExceptionMessageKey): "",
279+
string(semconv.ExceptionTypeKey): "",
280+
string(semconv.ExceptionStacktraceKey): "",
281+
},
282+
Dropped: 4,
283+
},
284+
},
285+
StatusCode: ptrace.StatusCodeError,
286+
StatusMsg: "overridden-error-msg",
287+
TraceID: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
288+
SpanID: [8]byte{0, 1, 2, 3, 4, 5, 6, 7},
289+
ParentID: [8]byte{0, 0, 0, 0, 0, 0, 0, 1},
290+
Kind: ptrace.SpanKindServer,
291+
Attributes: map[string]any{
292+
"datadog.service": "specified-service",
293+
"datadog.resource": "specified-resource",
294+
"datadog.name": "specified-operation",
295+
"datadog.type": "specified-type",
296+
"datadog.host.name": "specified-hostname",
297+
"datadog.span.kind": "specified-span-kind",
298+
"datadog.env": "specified-env",
299+
"datadog.http_status_code": "500",
300+
"datadog.error": 1,
301+
"datadog.error.msg": "specified-error-msg",
302+
"datadog.error.type": "specified-error-type",
303+
"datadog.error.stack": "specified-error-stack",
304+
string(semconv.HTTPStatusCodeKey): 200,
305+
},
306+
},
307+
},
308+
},
309+
},
310+
fn: func(out *ptrace.Traces) {
311+
rs := out.ResourceSpans().At(0)
312+
rattr := rs.Resource().Attributes()
313+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.service", "otlpresourcenoservicename")
314+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.env", "default")
315+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.version", "")
316+
assertKeyInAttributesMatchesValue(t, rattr, "datadog.host.name", "")
317+
318+
span := rs.ScopeSpans().At(0).Spans().At(0)
319+
sattr := span.Attributes()
320+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.name", "server.request")
321+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.resource", "")
322+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.type", "web")
323+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.span.kind", "server")
324+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.http_status_code", "200")
325+
ddError, _ := sattr.Get("datadog.error")
326+
require.Equal(t, int64(1), ddError.Int())
327+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.msg", "")
328+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.type", "")
329+
assertKeyInAttributesMatchesValue(t, sattr, "datadog.error.stack", "")
330+
},
331+
},
254332
{
255333
name: "dont override incoming Datadog fields",
256334
overrideIncomingDatadogFields: false,

0 commit comments

Comments
 (0)