From 36b603da19a159fc909d98493786f7978fed252b Mon Sep 17 00:00:00 2001 From: Felipe Lopes Date: Thu, 19 Sep 2024 05:15:43 -0300 Subject: [PATCH] [receiver/datadog][bug-fix] Add DD span `metrics` as attributes (#35087) **Description:** Datadog [divides the span's tags](https://github.com/DataDog/dd-trace-java/blob/master/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapperV0_5.java#L210-L212) into [two fields](https://github.com/DataDog/datadog-agent/blob/1739a048156d968bbe5fd8a1ace8e07c997d16d9/pkg/proto/datadog/trace/span.proto#L50-L55), `meta` for string values and `metrics` for numeric ones. Currently, the receiver isn't considering the `metrics` field when building the OTel span's attributes, losing this metadata during the conversion. This PR fixes this issue. **Link to tracking Issue:** **Testing:** **Documentation:** --------- Co-authored-by: Sean Marciniak <30928402+MovieStoreGuy@users.noreply.github.com> --- ...tadog-receiver-metrics-attributes-fix.yaml | 27 +++++++++++++++++++ .../internal/translator/traces_translator.go | 5 ++++ .../translator/traces_translator_test.go | 22 ++++++++------- 3 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 .chloggen/datadog-receiver-metrics-attributes-fix.yaml diff --git a/.chloggen/datadog-receiver-metrics-attributes-fix.yaml b/.chloggen/datadog-receiver-metrics-attributes-fix.yaml new file mode 100644 index 000000000000..9be880dbf5e9 --- /dev/null +++ b/.chloggen/datadog-receiver-metrics-attributes-fix.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: datadogreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Fix numeric span attributes + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [35087] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [user] diff --git a/receiver/datadogreceiver/internal/translator/traces_translator.go b/receiver/datadogreceiver/internal/translator/traces_translator.go index a401d7a34ac8..0b92812cf2e0 100644 --- a/receiver/datadogreceiver/internal/translator/traces_translator.go +++ b/receiver/datadogreceiver/internal/translator/traces_translator.go @@ -119,6 +119,11 @@ func ToTraces(payload *pb.TracerPayload, req *http.Request) ptrace.Traces { newSpan.Attributes().PutStr(k, v) } } + for k, v := range span.GetMetrics() { + if k = translateDatadogKeyToOTel(k); len(k) > 0 { + newSpan.Attributes().PutDouble(k, v) + } + } switch span.Meta[datadogSpanKindKey] { case "server": diff --git a/receiver/datadogreceiver/internal/translator/traces_translator_test.go b/receiver/datadogreceiver/internal/translator/traces_translator_test.go index c197d5bb6d74..73c7f55de821 100644 --- a/receiver/datadogreceiver/internal/translator/traces_translator_test.go +++ b/receiver/datadogreceiver/internal/translator/traces_translator_test.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "net/http" + "strconv" "testing" pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/trace" @@ -28,7 +29,7 @@ var data = [2]any{ 2: "elasticsearch.version", 3: "7.0", 4: "my-name", - 5: "X", + 5: "numeric_attribute", 6: "my-service", 7: "my-resource", 8: "_sampling_priority_v1", @@ -86,26 +87,27 @@ func TestTracePayloadV05Unmarshalling(t *testing.T) { require.NoError(t, traces.UnmarshalMsgDictionary(payload), "Must not error when marshaling content") req, _ := http.NewRequest(http.MethodPost, "/v0.5/traces", io.NopCloser(bytes.NewReader(payload))) - translated := ToTraces(&pb.TracerPayload{ - LanguageName: req.Header.Get(header.Lang), - LanguageVersion: req.Header.Get(header.LangVersion), - TracerVersion: req.Header.Get(header.TracerVersion), - Chunks: traceChunksFromTraces(traces), - }, req) + tracePayloads, _ := HandleTracesPayload(req) + assert.Len(t, tracePayloads, 1, "Expected one translated payload") + tracePayload := tracePayloads[0] + translated := ToTraces(tracePayload, req) assert.Equal(t, 1, translated.SpanCount(), "Span Count wrong") span := translated.ResourceSpans().At(0).ScopeSpans().At(0).Spans().At(0) assert.NotNil(t, span) - assert.Equal(t, 9, span.Attributes().Len(), "missing attributes") + assert.Equal(t, "my-name", span.Name()) + assert.Equal(t, 10, span.Attributes().Len(), "missing attributes") value, exists := span.Attributes().Get("service.name") - serviceVersionValue, _ := span.Attributes().Get("service.version") assert.True(t, exists, "service.name missing") assert.Equal(t, "my-service", value.AsString(), "service.name attribute value incorrect") - assert.Equal(t, "my-name", span.Name()) + serviceVersionValue, _ := span.Attributes().Get("service.version") assert.Equal(t, "1.0.1", serviceVersionValue.AsString()) spanResource, _ := span.Attributes().Get("dd.span.Resource") assert.Equal(t, "my-resource", spanResource.Str()) spanResource1, _ := span.Attributes().Get("sampling.priority") assert.Equal(t, fmt.Sprintf("%f", 1.0), spanResource1.Str()) + numericAttributeValue, _ := span.Attributes().Get("numeric_attribute") + numericAttributeFloat, _ := strconv.ParseFloat(numericAttributeValue.AsString(), 64) + assert.Equal(t, 1.2, numericAttributeFloat) } func TestTracePayloadV07Unmarshalling(t *testing.T) {