translator_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package datadogreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/datadogreceiver"
  4. import (
  5. "bytes"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "testing"
  10. pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/trace"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/stretchr/testify/require"
  13. vmsgp "github.com/vmihailenco/msgpack/v4"
  14. "go.opentelemetry.io/collector/pdata/pcommon"
  15. semconv "go.opentelemetry.io/collector/semconv/v1.16.0"
  16. "google.golang.org/protobuf/proto"
  17. )
  18. var data = [2]any{
  19. 0: []string{
  20. 0: "baggage",
  21. 1: "item",
  22. 2: "elasticsearch.version",
  23. 3: "7.0",
  24. 4: "my-name",
  25. 5: "X",
  26. 6: "my-service",
  27. 7: "my-resource",
  28. 8: "_dd.sampling_rate_whatever",
  29. 9: "value whatever",
  30. 10: "sql",
  31. 11: "service.name",
  32. },
  33. 1: [][][12]any{
  34. {
  35. {
  36. 6,
  37. 4,
  38. 7,
  39. uint64(12345678901234561234),
  40. uint64(2),
  41. uint64(3),
  42. int64(123),
  43. int64(456),
  44. 1,
  45. map[any]any{
  46. 8: 9,
  47. 0: 1,
  48. 2: 3,
  49. 11: 6,
  50. },
  51. map[any]float64{
  52. 5: 1.2,
  53. },
  54. 10,
  55. },
  56. },
  57. },
  58. }
  59. func getTraces(t *testing.T) (traces pb.Traces) {
  60. payload, err := vmsgp.Marshal(&data)
  61. assert.NoError(t, err)
  62. if err2 := traces.UnmarshalMsgDictionary(payload); err2 != nil {
  63. t.Fatal(err)
  64. }
  65. return traces
  66. }
  67. func TestTracePayloadV05Unmarshalling(t *testing.T) {
  68. var traces pb.Traces
  69. payload, err := vmsgp.Marshal(&data)
  70. assert.NoError(t, err)
  71. require.NoError(t, traces.UnmarshalMsgDictionary(payload), "Must not error when marshaling content")
  72. req, _ := http.NewRequest(http.MethodPost, "/v0.5/traces", io.NopCloser(bytes.NewReader(payload)))
  73. translated := toTraces(&pb.TracerPayload{
  74. LanguageName: req.Header.Get("Datadog-Meta-Lang"),
  75. LanguageVersion: req.Header.Get("Datadog-Meta-Lang-Version"),
  76. TracerVersion: req.Header.Get("Datadog-Meta-Tracer-Version"),
  77. Chunks: traceChunksFromTraces(traces),
  78. }, req)
  79. assert.Equal(t, 1, translated.SpanCount(), "Span Count wrong")
  80. span := translated.ResourceSpans().At(0).ScopeSpans().At(0).Spans().At(0)
  81. assert.NotNil(t, span)
  82. assert.Equal(t, 7, span.Attributes().Len(), "missing attributes")
  83. value, exists := span.Attributes().Get("service.name")
  84. assert.True(t, exists, "service.name missing")
  85. assert.Equal(t, "my-service", value.AsString(), "service.name attribute value incorrect")
  86. assert.Equal(t, "my-name", span.Name())
  87. spanResource, _ := span.Attributes().Get("dd.span.Resource")
  88. assert.Equal(t, "my-resource", spanResource.Str())
  89. }
  90. func TestTracePayloadV07Unmarshalling(t *testing.T) {
  91. traces := getTraces(t)
  92. apiPayload := pb.TracerPayload{
  93. LanguageName: "1",
  94. LanguageVersion: "1",
  95. Chunks: traceChunksFromTraces(traces),
  96. TracerVersion: "1",
  97. }
  98. var reqBytes []byte
  99. bytez, _ := apiPayload.MarshalMsg(reqBytes)
  100. req, _ := http.NewRequest(http.MethodPost, "/v0.7/traces", io.NopCloser(bytes.NewReader(bytez)))
  101. translatedPayloads, _ := handlePayload(req)
  102. assert.Equal(t, len(translatedPayloads), 1, "Expected one translated payload")
  103. translated := translatedPayloads[0]
  104. span := translated.GetChunks()[0].GetSpans()[0]
  105. assert.NotNil(t, span)
  106. assert.Equal(t, 4, len(span.GetMeta()), "missing attributes")
  107. value, exists := span.GetMeta()["service.name"]
  108. assert.True(t, exists, "service.name missing")
  109. assert.Equal(t, "my-service", value, "service.name attribute value incorrect")
  110. assert.Equal(t, "my-name", span.GetName())
  111. assert.Equal(t, "my-resource", span.GetResource())
  112. }
  113. func BenchmarkTranslatorv05(b *testing.B) {
  114. b.StartTimer()
  115. for n := 0; n < b.N; n++ {
  116. TestTracePayloadV05Unmarshalling(&testing.T{})
  117. }
  118. b.StopTimer()
  119. }
  120. func BenchmarkTranslatorv07(b *testing.B) {
  121. b.StartTimer()
  122. for n := 0; n < b.N; n++ {
  123. TestTracePayloadV07Unmarshalling(&testing.T{})
  124. }
  125. b.StopTimer()
  126. }
  127. func TestTracePayloadApiV02Unmarshalling(t *testing.T) {
  128. traces := getTraces(t)
  129. agentPayload := agentPayloadFromTraces(&traces)
  130. bytez, _ := proto.Marshal(&agentPayload)
  131. req, _ := http.NewRequest(http.MethodPost, "/api/v0.2/traces", io.NopCloser(bytes.NewReader(bytez)))
  132. translatedPayloads, _ := handlePayload(req)
  133. assert.Equal(t, len(translatedPayloads), 2, "Expected two translated payload")
  134. for _, translated := range translatedPayloads {
  135. assert.NotNil(t, translated)
  136. assert.Equal(t, 1, len(translated.Chunks))
  137. assert.Equal(t, 1, len(translated.Chunks[0].Spans))
  138. span := translated.Chunks[0].Spans[0]
  139. assert.NotNil(t, span)
  140. assert.Equal(t, 4, len(span.Meta), "missing attributes")
  141. assert.Equal(t, "my-service", span.Meta["service.name"])
  142. assert.Equal(t, "my-name", span.Name)
  143. assert.Equal(t, "my-resource", span.Resource)
  144. }
  145. }
  146. func agentPayloadFromTraces(traces *pb.Traces) (agentPayload pb.AgentPayload) {
  147. numberOfTraces := 2
  148. var tracerPayloads []*pb.TracerPayload
  149. for i := 0; i < numberOfTraces; i++ {
  150. payload := &pb.TracerPayload{
  151. LanguageName: fmt.Sprintf("%d", i),
  152. LanguageVersion: fmt.Sprintf("%d", i),
  153. Chunks: traceChunksFromTraces(*traces),
  154. TracerVersion: fmt.Sprintf("%d", i),
  155. }
  156. tracerPayloads = append(tracerPayloads, payload)
  157. }
  158. return pb.AgentPayload{
  159. TracerPayloads: tracerPayloads,
  160. }
  161. }
  162. func TestUpsertHeadersAttributes(t *testing.T) {
  163. // Test case 1: Datadog-Meta-Tracer-Version is present in headers
  164. req1, _ := http.NewRequest("GET", "http://example.com", nil)
  165. req1.Header.Set("Datadog-Meta-Tracer-Version", "1.2.3")
  166. attrs1 := pcommon.NewMap()
  167. upsertHeadersAttributes(req1, attrs1)
  168. val, ok := attrs1.Get(semconv.AttributeTelemetrySDKVersion)
  169. assert.True(t, ok)
  170. assert.Equal(t, "Datadog-1.2.3", val.Str())
  171. // Test case 2: Datadog-Meta-Lang is present in headers with ".NET"
  172. req2, _ := http.NewRequest("GET", "http://example.com", nil)
  173. req2.Header.Set("Datadog-Meta-Lang", ".NET")
  174. attrs2 := pcommon.NewMap()
  175. upsertHeadersAttributes(req2, attrs2)
  176. val, ok = attrs2.Get(semconv.AttributeTelemetrySDKLanguage)
  177. assert.True(t, ok)
  178. assert.Equal(t, "dotnet", val.Str())
  179. }