Skip to content

Commit 89e2bff

Browse files
committed
[receiver/datadog] Add support for HTTP tags
1 parent 70d14d0 commit 89e2bff

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

receiver/datadogreceiver/internal/translator/tags.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ var datadogKnownResourceAttributes = map[string]string{
5050
"kube_namespace": semconv.AttributeK8SNamespaceName,
5151
"pod_name": semconv.AttributeK8SPodName,
5252

53+
// HTTP
54+
"http.client_ip": semconv.AttributeClientAddress,
55+
"http.response.content_length": semconv.AttributeHTTPResponseBodySize,
56+
"http.status_code": semconv.AttributeHTTPResponseStatusCode,
57+
"http.request.content_length": semconv.AttributeHTTPRequestBodySize,
58+
"http.referer": "http.request.header.referer",
59+
"http.method": semconv.AttributeHTTPRequestMethod,
60+
"http.route": semconv.AttributeHTTPRoute,
61+
"http.version": semconv.AttributeNetworkProtocolVersion,
62+
"http.server_name": semconv.AttributeServerAddress,
63+
"http.url": semconv.AttributeURLFull,
64+
"http.useragent": semconv.AttributeUserAgentOriginal,
65+
5366
// Other
5467
"process_id": semconv.AttributeProcessPID,
5568
"error.stacktrace": semconv.AttributeExceptionStacktrace,
@@ -80,6 +93,15 @@ func translateDatadogKeyToOTel(k string) string {
8093
if otelKey, ok := datadogKnownResourceAttributes[strings.ToLower(k)]; ok {
8194
return otelKey
8295
}
96+
97+
// HTTP dynamic attributes
98+
if strings.HasPrefix(k, "http.response.headers.") { // type: string[]
99+
header := strings.TrimPrefix(k, "http.response.headers.")
100+
return "http.response.header." + header
101+
} else if strings.HasPrefix(k, "http.request.headers.") { // type: string[]
102+
header := strings.TrimPrefix(k, "http.request.headers.")
103+
return "http.request.header." + header
104+
}
83105
return k
84106
}
85107

@@ -136,12 +158,15 @@ func tagsToAttributes(tags []string, host string, stringPool *StringPool) attrib
136158
for _, tag := range tags {
137159
key, val = translateDatadogTagToKeyValuePair(tag)
138160
if attr, ok := datadogKnownResourceAttributes[key]; ok {
139-
val = stringPool.Intern(val) // No need to intern the key if we already have it
140-
if key == semconv.AttributeContainerImageTags {
161+
val = stringPool.Intern(val) // No need to intern the key if we already have it
162+
if key == semconv.AttributeContainerImageTags { // type: string[]
141163
attrs.resource.PutEmptySlice(attr).AppendEmpty().SetStr(val)
142164
} else {
143165
attrs.resource.PutStr(attr, val)
144166
}
167+
} else if strings.HasPrefix(key, "http.request.header") || strings.HasPrefix(key, "http.response.header.") {
168+
// type: string[]
169+
attrs.resource.PutEmptySlice(attr).AppendEmpty().SetStr(val)
145170
} else {
146171
key = stringPool.Intern(translateDatadogKeyToOTel(key))
147172
val = stringPool.Intern(val)

receiver/datadogreceiver/internal/translator/tags_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,10 @@ func TestTranslateDataDogKeyToOtel(t *testing.T) {
148148
assert.Equal(t, v, translateDatadogKeyToOTel(k))
149149
})
150150
}
151+
152+
// test dynamic attributes:
153+
// * http.request.header.<header_name>
154+
// * http.response.header.<header_name>
155+
assert.Equal(t, "http.request.header.referer", translateDatadogKeyToOTel("http.request.headers.referer"))
156+
assert.Equal(t, "http.response.header.content-type", translateDatadogKeyToOTel("http.response.headers.content-type"))
151157
}

receiver/datadogreceiver/internal/translator/traces_translator.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ func upsertHeadersAttributes(req *http.Request, attrs pcommon.Map) {
5555
}
5656
}
5757

58+
// getSpanName returns a better suited span name on specific conditions
59+
// see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/36924
60+
func getSpanName(span *pb.Span) string {
61+
if span.Name == "servlet.request" || span.Name == "spring.handler" {
62+
return span.Resource
63+
}
64+
return span.Name
65+
}
66+
5867
func ToTraces(payload *pb.TracerPayload, req *http.Request) ptrace.Traces {
5968
var traces pb.Traces
6069
for _, p := range payload.GetChunks() {
@@ -106,7 +115,7 @@ func ToTraces(payload *pb.TracerPayload, req *http.Request) ptrace.Traces {
106115
newSpan.SetStartTimestamp(pcommon.Timestamp(span.Start))
107116
newSpan.SetEndTimestamp(pcommon.Timestamp(span.Start + span.Duration))
108117
newSpan.SetParentSpanID(uInt64ToSpanID(span.ParentID))
109-
newSpan.SetName(span.Name)
118+
newSpan.SetName(getSpanName(span))
110119
newSpan.Status().SetCode(ptrace.StatusCodeOk)
111120
newSpan.Attributes().PutStr("dd.span.Resource", span.Resource)
112121
if samplingPriority, ok := span.Metrics["_sampling_priority_v1"]; ok {

0 commit comments

Comments
 (0)