jaegerthrift_to_traces_test.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package jaeger
  4. import (
  5. "encoding/binary"
  6. "testing"
  7. "github.com/jaegertracing/jaeger/thrift-gen/jaeger"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. "go.opentelemetry.io/collector/pdata/pcommon"
  11. "go.opentelemetry.io/collector/pdata/ptrace"
  12. conventions "go.opentelemetry.io/collector/semconv/v1.9.0"
  13. "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/testdata"
  14. "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/tracetranslator"
  15. )
  16. func TestJThriftTagsToInternalAttributes(t *testing.T) {
  17. var intVal int64 = 123
  18. boolVal := true
  19. stringVal := "abc"
  20. doubleVal := 1.23
  21. tags := []*jaeger.Tag{
  22. {
  23. Key: "bool-val",
  24. VType: jaeger.TagType_BOOL,
  25. VBool: &boolVal,
  26. },
  27. {
  28. Key: "int-val",
  29. VType: jaeger.TagType_LONG,
  30. VLong: &intVal,
  31. },
  32. {
  33. Key: "string-val",
  34. VType: jaeger.TagType_STRING,
  35. VStr: &stringVal,
  36. },
  37. {
  38. Key: "double-val",
  39. VType: jaeger.TagType_DOUBLE,
  40. VDouble: &doubleVal,
  41. },
  42. {
  43. Key: "binary-val",
  44. VType: jaeger.TagType_BINARY,
  45. VBinary: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7D, 0x98},
  46. },
  47. }
  48. expected := pcommon.NewMap()
  49. expected.PutBool("bool-val", true)
  50. expected.PutInt("int-val", 123)
  51. expected.PutStr("string-val", "abc")
  52. expected.PutDouble("double-val", 1.23)
  53. expected.PutStr("binary-val", "AAAAAABkfZg=")
  54. got := pcommon.NewMap()
  55. jThriftTagsToInternalAttributes(tags, got)
  56. require.EqualValues(t, expected, got)
  57. }
  58. func TestThriftBatchToInternalTraces(t *testing.T) {
  59. tests := []struct {
  60. name string
  61. jb *jaeger.Batch
  62. td ptrace.Traces
  63. }{
  64. {
  65. name: "empty",
  66. jb: &jaeger.Batch{},
  67. td: ptrace.NewTraces(),
  68. },
  69. {
  70. name: "no-spans",
  71. jb: &jaeger.Batch{
  72. Process: generateThriftProcess(),
  73. },
  74. td: testdata.GenerateTracesNoLibraries(),
  75. },
  76. {
  77. name: "one-span-no-resources",
  78. jb: &jaeger.Batch{
  79. Spans: []*jaeger.Span{
  80. generateThriftSpan(),
  81. },
  82. },
  83. td: generateTracesOneSpanNoResource(),
  84. },
  85. {
  86. name: "two-spans-child-parent",
  87. jb: &jaeger.Batch{
  88. Spans: []*jaeger.Span{
  89. generateThriftSpan(),
  90. generateThriftChildSpan(),
  91. },
  92. },
  93. td: generateTracesTwoSpansChildParent(),
  94. },
  95. {
  96. name: "a-spans-with-two-parent",
  97. jb: &jaeger.Batch{
  98. Spans: []*jaeger.Span{
  99. generateThriftSpan(),
  100. generateThriftFollowerSpan(),
  101. generateThriftTwoParentsSpan(),
  102. },
  103. },
  104. td: generateTracesSpanWithTwoParents(),
  105. },
  106. {
  107. name: "two-spans-with-follower",
  108. jb: &jaeger.Batch{
  109. Spans: []*jaeger.Span{
  110. generateThriftSpan(),
  111. generateThriftFollowerSpan(),
  112. },
  113. },
  114. td: generateTracesTwoSpansWithFollower(),
  115. },
  116. }
  117. for _, test := range tests {
  118. t.Run(test.name, func(t *testing.T) {
  119. td, err := ThriftToTraces(test.jb)
  120. assert.NoError(t, err)
  121. assert.EqualValues(t, test.td, td)
  122. })
  123. }
  124. }
  125. func generateThriftProcess() *jaeger.Process {
  126. attrVal := "resource-attr-val-1"
  127. return &jaeger.Process{
  128. Tags: []*jaeger.Tag{
  129. {
  130. Key: "resource-attr",
  131. VType: jaeger.TagType_STRING,
  132. VStr: &attrVal,
  133. },
  134. },
  135. }
  136. }
  137. func generateThriftSpan() *jaeger.Span {
  138. spanStartTs := unixNanoToMicroseconds(testSpanStartTimestamp)
  139. spanEndTs := unixNanoToMicroseconds(testSpanEndTimestamp)
  140. eventTs := unixNanoToMicroseconds(testSpanEventTimestamp)
  141. intAttrVal := int64(123)
  142. eventName := "event-with-attr"
  143. eventStrAttrVal := "span-event-attr-val"
  144. statusCode := statusError
  145. statusMsg := "status-cancelled"
  146. kind := string(tracetranslator.OpenTracingSpanKindClient)
  147. return &jaeger.Span{
  148. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  149. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  150. SpanId: int64(binary.BigEndian.Uint64([]byte{0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8})),
  151. OperationName: "operationA",
  152. StartTime: spanStartTs,
  153. Duration: spanEndTs - spanStartTs,
  154. Logs: []*jaeger.Log{
  155. {
  156. Timestamp: eventTs,
  157. Fields: []*jaeger.Tag{
  158. {
  159. Key: eventNameAttr,
  160. VType: jaeger.TagType_STRING,
  161. VStr: &eventName,
  162. },
  163. {
  164. Key: "span-event-attr",
  165. VType: jaeger.TagType_STRING,
  166. VStr: &eventStrAttrVal,
  167. },
  168. },
  169. },
  170. {
  171. Timestamp: eventTs,
  172. Fields: []*jaeger.Tag{
  173. {
  174. Key: "attr-int",
  175. VType: jaeger.TagType_LONG,
  176. VLong: &intAttrVal,
  177. },
  178. },
  179. },
  180. },
  181. Tags: []*jaeger.Tag{
  182. {
  183. Key: conventions.OtelStatusCode,
  184. VType: jaeger.TagType_STRING,
  185. VStr: &statusCode,
  186. },
  187. {
  188. Key: conventions.OtelStatusDescription,
  189. VType: jaeger.TagType_STRING,
  190. VStr: &statusMsg,
  191. },
  192. {
  193. Key: tracetranslator.TagSpanKind,
  194. VType: jaeger.TagType_STRING,
  195. VStr: &kind,
  196. },
  197. },
  198. }
  199. }
  200. func generateThriftChildSpan() *jaeger.Span {
  201. spanStartTs := unixNanoToMicroseconds(testSpanStartTimestamp)
  202. spanEndTs := unixNanoToMicroseconds(testSpanEndTimestamp)
  203. notFoundAttrVal := int64(404)
  204. kind := string(tracetranslator.OpenTracingSpanKindServer)
  205. return &jaeger.Span{
  206. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  207. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  208. SpanId: int64(binary.BigEndian.Uint64([]byte{0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18})),
  209. ParentSpanId: int64(binary.BigEndian.Uint64([]byte{0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8})),
  210. OperationName: "operationB",
  211. StartTime: spanStartTs,
  212. Duration: spanEndTs - spanStartTs,
  213. Tags: []*jaeger.Tag{
  214. {
  215. Key: conventions.AttributeHTTPStatusCode,
  216. VType: jaeger.TagType_LONG,
  217. VLong: &notFoundAttrVal,
  218. },
  219. {
  220. Key: tracetranslator.TagSpanKind,
  221. VType: jaeger.TagType_STRING,
  222. VStr: &kind,
  223. },
  224. },
  225. }
  226. }
  227. func generateThriftFollowerSpan() *jaeger.Span {
  228. statusCode := statusOk
  229. statusMsg := "status-ok"
  230. kind := string(tracetranslator.OpenTracingSpanKindConsumer)
  231. return &jaeger.Span{
  232. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  233. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  234. SpanId: int64(binary.BigEndian.Uint64([]byte{0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18})),
  235. OperationName: "operationC",
  236. StartTime: unixNanoToMicroseconds(testSpanEndTimestamp),
  237. Duration: 1000,
  238. Tags: []*jaeger.Tag{
  239. {
  240. Key: conventions.OtelStatusCode,
  241. VType: jaeger.TagType_STRING,
  242. VStr: &statusCode,
  243. },
  244. {
  245. Key: conventions.OtelStatusDescription,
  246. VType: jaeger.TagType_STRING,
  247. VStr: &statusMsg,
  248. },
  249. {
  250. Key: tracetranslator.TagSpanKind,
  251. VType: jaeger.TagType_STRING,
  252. VStr: &kind,
  253. },
  254. },
  255. References: []*jaeger.SpanRef{
  256. {
  257. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  258. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  259. SpanId: int64(binary.BigEndian.Uint64([]byte{0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8})),
  260. RefType: jaeger.SpanRefType_FOLLOWS_FROM,
  261. },
  262. },
  263. }
  264. }
  265. func generateThriftTwoParentsSpan() *jaeger.Span {
  266. spanStartTs := unixNanoToMicroseconds(testSpanStartTimestamp)
  267. spanEndTs := unixNanoToMicroseconds(testSpanEndTimestamp)
  268. statusCode := statusOk
  269. statusMsg := "status-ok"
  270. kind := string(tracetranslator.OpenTracingSpanKindConsumer)
  271. return &jaeger.Span{
  272. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  273. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  274. SpanId: int64(binary.BigEndian.Uint64([]byte{0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x20})),
  275. OperationName: "operationD",
  276. StartTime: spanStartTs,
  277. Duration: spanEndTs - spanStartTs,
  278. ParentSpanId: int64(binary.BigEndian.Uint64([]byte{0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8})),
  279. Tags: []*jaeger.Tag{
  280. {
  281. Key: conventions.OtelStatusCode,
  282. VType: jaeger.TagType_STRING,
  283. VStr: &statusCode,
  284. },
  285. {
  286. Key: conventions.OtelStatusDescription,
  287. VType: jaeger.TagType_STRING,
  288. VStr: &statusMsg,
  289. },
  290. {
  291. Key: tracetranslator.TagSpanKind,
  292. VType: jaeger.TagType_STRING,
  293. VStr: &kind,
  294. },
  295. },
  296. References: []*jaeger.SpanRef{
  297. {
  298. TraceIdHigh: int64(binary.BigEndian.Uint64([]byte{0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8})),
  299. TraceIdLow: int64(binary.BigEndian.Uint64([]byte{0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x80})),
  300. SpanId: int64(binary.BigEndian.Uint64([]byte{0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18})),
  301. RefType: jaeger.SpanRefType_CHILD_OF,
  302. },
  303. },
  304. }
  305. }
  306. func unixNanoToMicroseconds(ns pcommon.Timestamp) int64 {
  307. return int64(ns / 1000)
  308. }
  309. func BenchmarkThriftBatchToInternalTraces(b *testing.B) {
  310. jb := &jaeger.Batch{
  311. Process: generateThriftProcess(),
  312. Spans: []*jaeger.Span{
  313. generateThriftSpan(),
  314. generateThriftChildSpan(),
  315. },
  316. }
  317. b.ResetTimer()
  318. for n := 0; n < b.N; n++ {
  319. _, err := ThriftToTraces(jb)
  320. assert.NoError(b, err)
  321. }
  322. }