skywalkingproto_to_traces_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package skywalking
  4. import (
  5. "strconv"
  6. "testing"
  7. "time"
  8. "github.com/stretchr/testify/assert"
  9. "go.opentelemetry.io/collector/pdata/pcommon"
  10. "go.opentelemetry.io/collector/pdata/ptrace"
  11. common "skywalking.apache.org/repo/goapi/collect/common/v3"
  12. agent "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
  13. agentV3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
  14. )
  15. func TestSetInternalSpanStatus(t *testing.T) {
  16. tests := []struct {
  17. name string
  18. swSpan *agentV3.SpanObject
  19. dest ptrace.Status
  20. code ptrace.StatusCode
  21. }{
  22. {
  23. name: "StatusCodeError",
  24. swSpan: &agentV3.SpanObject{
  25. IsError: true,
  26. },
  27. dest: generateTracesOneEmptyResourceSpans().Status(),
  28. code: ptrace.StatusCodeError,
  29. },
  30. {
  31. name: "StatusCodeOk",
  32. swSpan: &agentV3.SpanObject{
  33. IsError: false,
  34. },
  35. dest: generateTracesOneEmptyResourceSpans().Status(),
  36. code: ptrace.StatusCodeOk,
  37. },
  38. }
  39. for _, test := range tests {
  40. t.Run(test.name, func(t *testing.T) {
  41. setInternalSpanStatus(test.swSpan, test.dest)
  42. assert.Equal(t, test.code, test.dest.Code())
  43. })
  44. }
  45. }
  46. func TestSwKvPairsToInternalAttributes(t *testing.T) {
  47. tests := []struct {
  48. name string
  49. swSpan *agentV3.SegmentObject
  50. dest ptrace.Span
  51. }{
  52. {
  53. name: "mock-sw-swgment-1",
  54. swSpan: mockGrpcTraceSegment(1),
  55. dest: generateTracesOneEmptyResourceSpans(),
  56. },
  57. {
  58. name: "mock-sw-swgment-2",
  59. swSpan: mockGrpcTraceSegment(2),
  60. dest: generateTracesOneEmptyResourceSpans(),
  61. },
  62. }
  63. for _, test := range tests {
  64. t.Run(test.name, func(t *testing.T) {
  65. swKvPairsToInternalAttributes(test.swSpan.GetSpans()[0].Tags, test.dest.Attributes())
  66. assert.Equal(t, test.dest.Attributes().Len(), len(test.swSpan.GetSpans()[0].Tags))
  67. for _, tag := range test.swSpan.GetSpans()[0].Tags {
  68. value, _ := test.dest.Attributes().Get(tag.Key)
  69. assert.Equal(t, tag.Value, value.AsString())
  70. }
  71. })
  72. }
  73. }
  74. func TestSwProtoToTraces(t *testing.T) {
  75. tests := []struct {
  76. name string
  77. swSpan *agentV3.SegmentObject
  78. dest ptrace.Traces
  79. code ptrace.StatusCode
  80. }{
  81. {
  82. name: "mock-sw-swgment-1",
  83. swSpan: mockGrpcTraceSegment(1),
  84. },
  85. }
  86. for _, test := range tests {
  87. t.Run(test.name, func(t *testing.T) {
  88. td := ProtoToTraces(test.swSpan)
  89. assert.Equal(t, 1, td.ResourceSpans().Len())
  90. assert.Equal(t, 2, td.ResourceSpans().At(0).ScopeSpans().At(0).Spans().Len())
  91. })
  92. }
  93. }
  94. func TestSwReferencesToSpanLinks(t *testing.T) {
  95. tests := []struct {
  96. name string
  97. swSpan *agentV3.SegmentObject
  98. dest ptrace.Span
  99. }{
  100. {
  101. name: "mock-sw-swgment-1",
  102. swSpan: mockGrpcTraceSegment(1),
  103. dest: generateTracesOneEmptyResourceSpans(),
  104. },
  105. {
  106. name: "mock-sw-swgment-2",
  107. swSpan: mockGrpcTraceSegment(2),
  108. dest: generateTracesOneEmptyResourceSpans(),
  109. },
  110. }
  111. for _, test := range tests {
  112. t.Run(test.name, func(t *testing.T) {
  113. swReferencesToSpanLinks(test.swSpan.GetSpans()[0].Refs, test.dest.Links())
  114. assert.Equal(t, 1, test.dest.Links().Len())
  115. })
  116. }
  117. }
  118. func TestSwLogsToSpanEvents(t *testing.T) {
  119. tests := []struct {
  120. name string
  121. swSpan *agentV3.SegmentObject
  122. dest ptrace.Span
  123. }{
  124. {
  125. name: "mock-sw-swgment-0",
  126. swSpan: mockGrpcTraceSegment(0),
  127. dest: generateTracesOneEmptyResourceSpans(),
  128. },
  129. {
  130. name: "mock-sw-swgment-1",
  131. swSpan: mockGrpcTraceSegment(1),
  132. dest: generateTracesOneEmptyResourceSpans(),
  133. },
  134. }
  135. for index, test := range tests {
  136. t.Run(test.name, func(t *testing.T) {
  137. seq := strconv.Itoa(index)
  138. swLogsToSpanEvents(test.swSpan.GetSpans()[0].Logs, test.dest.Events())
  139. assert.Equal(t, 1, test.dest.Events().Len())
  140. assert.Equal(t, "logs", test.dest.Events().At(0).Name())
  141. logValue, _ := test.dest.Events().At(0).Attributes().Get("log-key" + seq)
  142. assert.Equal(t, "log-value"+seq, logValue.AsString())
  143. })
  144. }
  145. }
  146. func Test_stringToTraceID(t *testing.T) {
  147. type args struct {
  148. traceID string
  149. }
  150. tests := []struct {
  151. name string
  152. segmentObject args
  153. want pcommon.TraceID
  154. }{
  155. {
  156. name: "mock-sw-normal-trace-id-rfc4122v4",
  157. segmentObject: args{traceID: "de5980b8-fce3-4a37-aab9-b4ac3af7eedd"},
  158. want: [16]byte{222, 89, 128, 184, 252, 227, 74, 55, 170, 185, 180, 172, 58, 247, 238, 221},
  159. },
  160. {
  161. name: "mock-sw-normal-trace-id-rfc4122",
  162. segmentObject: args{traceID: "de5980b8fce34a37aab9b4ac3af7eedd"},
  163. want: [16]byte{222, 89, 128, 184, 252, 227, 74, 55, 170, 185, 180, 172, 58, 247, 238, 221},
  164. },
  165. {
  166. name: "mock-sw-trace-id-length-shorter",
  167. segmentObject: args{traceID: "de59"},
  168. want: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  169. },
  170. {
  171. name: "mock-sw-trace-id-length-java-agent",
  172. segmentObject: args{traceID: "de5980b8fce34a37aab9b4ac3af7eedd.1.16563474296430001"},
  173. want: [16]byte{222, 89, 128, 184, 253, 227, 74, 55, 27, 228, 27, 205, 94, 47, 212, 221},
  174. },
  175. {
  176. name: "mock-sw-trace-id-illegal",
  177. segmentObject: args{traceID: ".,<>?/-=+MNop"},
  178. want: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  179. },
  180. }
  181. for _, tt := range tests {
  182. t.Run(tt.name, func(t *testing.T) {
  183. got := swTraceIDToTraceID(tt.segmentObject.traceID)
  184. assert.Equal(t, tt.want, got)
  185. })
  186. }
  187. }
  188. func Test_stringToTraceID_Unique(t *testing.T) {
  189. type args struct {
  190. traceID string
  191. }
  192. tests := []struct {
  193. name string
  194. segmentObject args
  195. }{
  196. {
  197. name: "mock-sw-trace-id-unique-1",
  198. segmentObject: args{traceID: "de5980b8fce34a37aab9b4ac3af7eedd.133.16563474296430001"},
  199. },
  200. {
  201. name: "mock-sw-trace-id-unique-2",
  202. segmentObject: args{traceID: "de5980b8fce34a37aab9b4ac3af7eedd.133.16534574123430001"},
  203. },
  204. }
  205. var results [2][16]byte
  206. for i := 0; i < 2; i++ {
  207. tt := tests[i]
  208. t.Run(tt.name, func(t *testing.T) {
  209. got := swTraceIDToTraceID(tt.segmentObject.traceID)
  210. results[i] = got
  211. })
  212. }
  213. assert.NotEqual(t, tests[0].segmentObject.traceID, t, tests[1].segmentObject.traceID)
  214. assert.NotEqual(t, results[0], results[1])
  215. }
  216. func Test_segmentIdToSpanId(t *testing.T) {
  217. type args struct {
  218. segmentID string
  219. spanID uint32
  220. }
  221. tests := []struct {
  222. name string
  223. args args
  224. want pcommon.SpanID
  225. }{
  226. {
  227. name: "mock-sw-span-id-normal",
  228. args: args{segmentID: "4f2f27748b8e44ecaf18fe0347194e86.33.16560607369950066", spanID: 123},
  229. want: [8]byte{233, 196, 85, 168, 37, 66, 48, 106},
  230. },
  231. {
  232. name: "mock-sw-span-id-python-agent",
  233. args: args{segmentID: "4f2f27748b8e44ecaf18fe0347194e86", spanID: 123},
  234. want: [8]byte{155, 55, 217, 119, 204, 151, 10, 106},
  235. },
  236. {
  237. name: "mock-sw-span-id-short",
  238. args: args{segmentID: "16560607369950066", spanID: 12},
  239. want: [8]byte{0, 0, 0, 0, 0, 0, 0, 0},
  240. },
  241. {
  242. name: "mock-sw-span-id-illegal-1",
  243. args: args{segmentID: "1", spanID: 2},
  244. want: [8]byte{0, 0, 0, 0, 0, 0, 0, 0},
  245. },
  246. {
  247. name: "mock-sw-span-id-illegal-char",
  248. args: args{segmentID: ".,<>?/-=+MNop", spanID: 2},
  249. want: [8]byte{0, 0, 0, 0, 0, 0, 0, 0},
  250. },
  251. }
  252. for _, tt := range tests {
  253. t.Run(tt.name, func(t *testing.T) {
  254. got := segmentIDToSpanID(tt.args.segmentID, tt.args.spanID)
  255. assert.Equal(t, tt.want, got)
  256. })
  257. }
  258. }
  259. func Test_segmentIdToSpanId_Unique(t *testing.T) {
  260. type args struct {
  261. segmentID string
  262. spanID uint32
  263. }
  264. tests := []struct {
  265. name string
  266. args args
  267. }{
  268. {
  269. name: "mock-sw-span-id-unique-1",
  270. args: args{segmentID: "4f2f27748b8e44ecaf18fe0347194e86.33.16560607369950066", spanID: 123},
  271. },
  272. {
  273. name: "mock-sw-span-id-unique-2",
  274. args: args{segmentID: "4f2f27748b8e44ecaf18fe0347194e86.33.16560607369950066", spanID: 1},
  275. },
  276. }
  277. var results [2][8]byte
  278. for i := 0; i < 2; i++ {
  279. tt := tests[i]
  280. t.Run(tt.name, func(t *testing.T) {
  281. got := segmentIDToSpanID(tt.args.segmentID, tt.args.spanID)
  282. results[i] = got
  283. })
  284. }
  285. assert.NotEqual(t, results[0], results[1])
  286. }
  287. func Test_swSpanToSpan_ParentSpanId(t *testing.T) {
  288. type args struct {
  289. span *agentV3.SpanObject
  290. }
  291. tests := []struct {
  292. name string
  293. args args
  294. want pcommon.SpanID
  295. }{
  296. {
  297. name: "mock-sw-span-with-parent-segment",
  298. args: args{span: &agentV3.SpanObject{
  299. ParentSpanId: -1,
  300. Refs: []*agentV3.SegmentReference{{
  301. ParentTraceSegmentId: "4f2f27748b8e44ecaf18fe0347194e86.33.16560607369950066",
  302. ParentSpanId: 123,
  303. }}}},
  304. want: [8]byte{233, 196, 85, 168, 37, 66, 48, 106},
  305. },
  306. {
  307. name: "mock-sw-span-without-parent-segment",
  308. args: args{span: &agentV3.SpanObject{Refs: []*agentV3.SegmentReference{{
  309. ParentSpanId: -1,
  310. }}}},
  311. },
  312. }
  313. for _, tt := range tests {
  314. t.Run(tt.name, func(t *testing.T) {
  315. dest := ptrace.NewSpan()
  316. swSpanToSpan("de5980b8-fce3-4a37-aab9-b4ac3af7eedd", "", tt.args.span, dest)
  317. assert.Equal(t, tt.want, dest.ParentSpanID())
  318. })
  319. }
  320. }
  321. func generateTracesOneEmptyResourceSpans() ptrace.Span {
  322. td := ptrace.NewTraces()
  323. resourceSpan := td.ResourceSpans().AppendEmpty()
  324. il := resourceSpan.ScopeSpans().AppendEmpty()
  325. il.Spans().AppendEmpty()
  326. return il.Spans().At(0)
  327. }
  328. func mockGrpcTraceSegment(sequence int) *agent.SegmentObject {
  329. seq := strconv.Itoa(sequence)
  330. return &agent.SegmentObject{
  331. TraceId: "trace" + seq,
  332. TraceSegmentId: "trace-segment" + seq,
  333. Service: "demo-segmentReportService" + seq,
  334. ServiceInstance: "demo-instance" + seq,
  335. IsSizeLimited: false,
  336. Spans: []*agent.SpanObject{
  337. {
  338. SpanId: 1,
  339. ParentSpanId: 0,
  340. StartTime: time.Now().Unix(),
  341. EndTime: time.Now().Unix() + 10,
  342. OperationName: "operation" + seq,
  343. Peer: "127.0.0.1:6666",
  344. SpanType: agent.SpanType_Entry,
  345. SpanLayer: agent.SpanLayer_Http,
  346. ComponentId: 1,
  347. IsError: false,
  348. SkipAnalysis: false,
  349. Tags: []*common.KeyStringValuePair{
  350. {
  351. Key: "mock-key" + seq,
  352. Value: "mock-value" + seq,
  353. },
  354. },
  355. Logs: []*agent.Log{
  356. {
  357. Time: time.Now().Unix(),
  358. Data: []*common.KeyStringValuePair{
  359. {
  360. Key: "log-key" + seq,
  361. Value: "log-value" + seq,
  362. },
  363. },
  364. },
  365. },
  366. Refs: []*agent.SegmentReference{
  367. {
  368. RefType: agent.RefType_CrossThread,
  369. TraceId: "trace" + seq,
  370. ParentTraceSegmentId: "parent-trace-segment" + seq,
  371. ParentSpanId: 0,
  372. ParentService: "parent" + seq,
  373. ParentServiceInstance: "parent" + seq,
  374. ParentEndpoint: "parent" + seq,
  375. NetworkAddressUsedAtPeer: "127.0.0.1:6666",
  376. },
  377. },
  378. },
  379. {
  380. SpanId: 2,
  381. ParentSpanId: 1,
  382. StartTime: time.Now().Unix(),
  383. EndTime: time.Now().Unix() + 20,
  384. OperationName: "operation" + seq,
  385. Peer: "127.0.0.1:6666",
  386. SpanType: agent.SpanType_Local,
  387. SpanLayer: agent.SpanLayer_Http,
  388. ComponentId: 2,
  389. IsError: false,
  390. SkipAnalysis: false,
  391. Tags: []*common.KeyStringValuePair{
  392. {
  393. Key: "mock-key" + seq,
  394. Value: "mock-value" + seq,
  395. },
  396. },
  397. Logs: []*agent.Log{
  398. {
  399. Time: time.Now().Unix(),
  400. Data: []*common.KeyStringValuePair{
  401. {
  402. Key: "log-key" + seq,
  403. Value: "log-value" + seq,
  404. },
  405. },
  406. },
  407. },
  408. },
  409. },
  410. }
  411. }