Skip to content

Commit 222a90a

Browse files
committed
add buildDDForwardURL
1 parent 2b5ab97 commit 222a90a

File tree

2 files changed

+137
-2
lines changed

2 files changed

+137
-2
lines changed

pkg/otlp/logs/transform_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,3 +881,43 @@ func TestDeriveStatus(t *testing.T) {
881881
})
882882
}
883883
}
884+
885+
func TestBuildDDForwardURL(t *testing.T) {
886+
tests := []struct {
887+
name string
888+
rattrs pcommon.Map
889+
lattrs pcommon.Map
890+
want string
891+
}{
892+
{
893+
name: "successfully build ddforward url",
894+
rattrs: func() pcommon.Map {
895+
rattrs := pcommon.NewMap()
896+
rattrs.PutStr("batch_time", "123")
897+
ddTagsMap := rattrs.PutEmptyMap("ddtags")
898+
ddTagsMap.PutStr("service", "service-rattrs")
899+
ddTagsMap.PutStr("env", "prod")
900+
ddTagsMap.PutStr("sdk_version", "1.2.3")
901+
ddTagsMap.PutStr("version", "1.2.3")
902+
rattrs.PutStr("ddsource", "browser")
903+
rattrs.PutStr("dd-evp-origin", "browser")
904+
rattrs.PutStr("dd-request-id", "456")
905+
return rattrs
906+
}(),
907+
lattrs: func() pcommon.Map {
908+
lattrs := pcommon.NewMap()
909+
serviceMap := lattrs.PutEmptyMap("service")
910+
serviceMap.PutStr("name", "service")
911+
serviceMap.PutStr("version", "1.2.3")
912+
return lattrs
913+
}(),
914+
want: "/api/v2/rum?batch_time=123&ddtags=env:prod,sdk_version:1.2.3,service:service,version:1.2.3&ddsource=browser&dd-evp-origin=browser&dd-request-id=456",
915+
},
916+
}
917+
for _, tt := range tests {
918+
t.Run(tt.name, func(t *testing.T) {
919+
got := buildDDForwardURL(tt.rattrs, tt.lattrs)
920+
assert.Equal(t, tt.want, got)
921+
})
922+
}
923+
}

pkg/otlp/logs/translator.go

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@ package logs
1717
import (
1818
"bytes"
1919
"context"
20+
"crypto/rand"
21+
"encoding/hex"
2022
"encoding/json"
2123
"fmt"
2224
"io"
2325
"net/http"
26+
"sort"
27+
"strconv"
28+
"strings"
2429
"time"
2530

2631
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
@@ -90,6 +95,96 @@ func (t *Translator) hostFromAttributes(ctx context.Context, attrs pcommon.Map)
9095
return ""
9196
}
9297

98+
type ParamValue struct {
99+
ParamKey string
100+
SpanAttr string
101+
Fallback string
102+
}
103+
104+
func getParamValue(rattrs pcommon.Map, lattrs pcommon.Map, param ParamValue) string {
105+
if param.SpanAttr != "" {
106+
parts := strings.Split(param.SpanAttr, ".")
107+
m := lattrs
108+
for i, part := range parts {
109+
if v, ok := m.Get(part); ok {
110+
if i == len(parts)-1 {
111+
return v.AsString()
112+
}
113+
if v.Type() == pcommon.ValueTypeMap {
114+
m = v.Map()
115+
}
116+
}
117+
}
118+
}
119+
if v, ok := rattrs.Get(param.ParamKey); ok {
120+
return v.AsString()
121+
}
122+
return param.Fallback
123+
}
124+
125+
func buildDDTags(rattrs pcommon.Map, lattrs pcommon.Map) string {
126+
requiredTags := []ParamValue{
127+
{ParamKey: "service", SpanAttr: "service.name", Fallback: "unknown"},
128+
{ParamKey: "version", SpanAttr: "service.version", Fallback: "unknown"},
129+
{ParamKey: "sdk_version", SpanAttr: "_dd.sdk_version", Fallback: "unknown"},
130+
{ParamKey: "env", Fallback: "unknown"},
131+
}
132+
133+
tagMap := make(map[string]string)
134+
135+
if v, ok := rattrs.Get("ddtags"); ok && v.Type() == pcommon.ValueTypeMap {
136+
v.Map().Range(func(k string, val pcommon.Value) bool {
137+
tagMap[k] = val.AsString()
138+
return true
139+
})
140+
}
141+
142+
for _, tag := range requiredTags {
143+
val := getParamValue(rattrs, lattrs, tag)
144+
if val != "unknown" {
145+
tagMap[tag.ParamKey] = val
146+
}
147+
}
148+
149+
var tagParts []string
150+
for k, v := range tagMap {
151+
tagParts = append(tagParts, k+":"+v)
152+
}
153+
154+
// sort the tags to ensure consistent ordering for testing purposes
155+
sort.Strings(tagParts)
156+
157+
return strings.Join(tagParts, ",")
158+
}
159+
160+
func randomID() string {
161+
b := make([]byte, 16)
162+
if _, err := rand.Read(b); err != nil {
163+
panic(err)
164+
}
165+
return hex.EncodeToString(b)
166+
}
167+
168+
func buildDDForwardURL(rattrs pcommon.Map, lattrs pcommon.Map) string {
169+
var parts []string
170+
171+
batchTimeParam := ParamValue{ParamKey: "batch_time", Fallback: strconv.FormatInt(time.Now().UnixMilli(), 10)}
172+
parts = append(parts, batchTimeParam.ParamKey+"="+getParamValue(rattrs, lattrs, batchTimeParam))
173+
174+
parts = append(parts, "ddtags="+buildDDTags(rattrs, lattrs))
175+
176+
ddsourceParam := ParamValue{ParamKey: "ddsource", SpanAttr: "source", Fallback: "browser"}
177+
parts = append(parts, ddsourceParam.ParamKey+"="+getParamValue(rattrs, lattrs, ddsourceParam))
178+
179+
ddEvpOriginParam := ParamValue{ParamKey: "dd-evp-origin", SpanAttr: "source", Fallback: "browser"}
180+
parts = append(parts, ddEvpOriginParam.ParamKey+"="+getParamValue(rattrs, lattrs, ddEvpOriginParam))
181+
182+
ddRequestIdParam := ParamValue{ParamKey: "dd-request-id", SpanAttr: "", Fallback: randomID()}
183+
parts = append(parts, ddRequestIdParam.ParamKey+"="+getParamValue(rattrs, lattrs, ddRequestIdParam))
184+
185+
return "/api/v2/rum?" + strings.Join(parts, "&")
186+
}
187+
93188
// MapLogsAndRouteRUMEvents from OTLP format to Datadog format if shouldForwardOTLPRUMToDDRUM is true.
94189
func (t *Translator) MapLogsAndRouteRUMEvents(ctx context.Context, ld plog.Logs, hostFromAttributesHandler attributes.HostFromAttributesHandler, shouldForwardOTLPRUMToDDRUM bool) ([]datadogV2.HTTPLogItem, error) {
95190
if t.httpClient == nil {
@@ -116,9 +211,9 @@ func (t *Translator) MapLogsAndRouteRUMEvents(ctx context.Context, ld plog.Logs,
116211
lattr := logRecord.Attributes()
117212

118213
// build the Datadog intake URL
119-
ddforward, _ := rattr.Get("request_ddforward")
214+
ddforward := buildDDForwardURL(rattr, lattr)
120215
outUrlString := "https://browser-intake-datadoghq.com" +
121-
ddforward.AsString()
216+
ddforward
122217

123218
rumPayload := rum.ConstructRumPayloadFromOTLP(lattr)
124219
byts, err := json.Marshal(rumPayload)

0 commit comments

Comments
 (0)