traceTree.missinginstrumentation.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import {
  2. makeEventTransaction,
  3. makeSpan,
  4. makeTrace,
  5. makeTransaction,
  6. } from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeTestUtils';
  7. import {isMissingInstrumentationNode} from './../traceGuards';
  8. import {TraceTree} from './traceTree';
  9. const start = new Date('2024-02-29T00:00:00Z').getTime() / 1e3;
  10. const traceMetadata = {replay: null, meta: null};
  11. const singleTransactionTrace = makeTrace({
  12. transactions: [
  13. makeTransaction({
  14. start_timestamp: start,
  15. timestamp: start + 2,
  16. children: [],
  17. }),
  18. ],
  19. orphan_errors: [],
  20. });
  21. const missingInstrumentationSpans = [
  22. makeSpan({
  23. op: 'db',
  24. description: 'redis',
  25. start_timestamp: start,
  26. timestamp: start + 1,
  27. }),
  28. makeSpan({
  29. op: 'db',
  30. description: 'redis',
  31. start_timestamp: start + 2,
  32. timestamp: start + 4,
  33. }),
  34. ];
  35. const childrenMissingInstrumentationSpans = [
  36. makeSpan({
  37. op: 'db',
  38. description: 'redis',
  39. span_id: 'redis',
  40. start_timestamp: start,
  41. timestamp: start + 1,
  42. }),
  43. makeSpan({
  44. op: 'http',
  45. description: 'request',
  46. span_id: 'other redis',
  47. parent_span_id: 'redis',
  48. start_timestamp: start + 2,
  49. timestamp: start + 4,
  50. }),
  51. ];
  52. describe('missing instrumentation', () => {
  53. it('adds missing instrumentation between sibling spans', () => {
  54. const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
  55. TraceTree.FromSpans(
  56. tree.root.children[0].children[0],
  57. missingInstrumentationSpans,
  58. makeEventTransaction()
  59. );
  60. TraceTree.DetectMissingInstrumentation(tree.root);
  61. expect(tree.build().serialize()).toMatchSnapshot();
  62. });
  63. it('adds missing instrumentation between children spans', () => {
  64. const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
  65. TraceTree.FromSpans(
  66. tree.root.children[0].children[0],
  67. childrenMissingInstrumentationSpans,
  68. makeEventTransaction()
  69. );
  70. TraceTree.DetectMissingInstrumentation(tree.root);
  71. expect(tree.build().serialize()).toMatchSnapshot();
  72. });
  73. it('adds missing instrumentation between two spans that share a common root', () => {
  74. const tree = TraceTree.FromTrace(
  75. makeTrace({
  76. transactions: [
  77. makeTransaction({
  78. span_id: 'parent-transaction',
  79. }),
  80. ],
  81. }),
  82. traceMetadata
  83. );
  84. TraceTree.FromSpans(
  85. tree.root.children[0].children[0],
  86. [
  87. makeSpan({
  88. op: 'http',
  89. description: 'request',
  90. span_id: '0000',
  91. parent_span_id: 'parent-transaction',
  92. start_timestamp: start,
  93. timestamp: start + 2,
  94. }),
  95. makeSpan({
  96. op: 'db',
  97. description: 'redis',
  98. span_id: '0001',
  99. parent_span_id: '0000',
  100. start_timestamp: start,
  101. timestamp: start + 2,
  102. }),
  103. makeSpan({
  104. op: 'cache',
  105. description: 'redis',
  106. span_id: '0002',
  107. parent_span_id: 'parent-transaction',
  108. start_timestamp: start + 3,
  109. timestamp: start + 4,
  110. }),
  111. ],
  112. makeEventTransaction()
  113. );
  114. TraceTree.DetectMissingInstrumentation(tree.root);
  115. expect(tree.build().serialize()).toMatchSnapshot();
  116. });
  117. it('removes missing instrumentation nodes', () => {
  118. const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
  119. TraceTree.FromSpans(
  120. tree.root.children[0].children[0],
  121. missingInstrumentationSpans,
  122. makeEventTransaction()
  123. );
  124. const snapshot = tree.build().serialize();
  125. TraceTree.DetectMissingInstrumentation(tree.root);
  126. // Assert that missing instrumentation nodes exist
  127. expect(
  128. TraceTree.Find(tree.root, c => isMissingInstrumentationNode(c))
  129. ).not.toBeNull();
  130. // Remove it and assert that the tree is back to the original state
  131. TraceTree.RemoveMissingInstrumentationNodes(tree.root);
  132. expect(tree.build().serialize()).toEqual(snapshot);
  133. expect(tree.build().serialize()).toMatchSnapshot();
  134. });
  135. it('does not add missing instrumentation for browser SDKs', () => {
  136. const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
  137. TraceTree.FromSpans(
  138. tree.root.children[0].children[0],
  139. missingInstrumentationSpans,
  140. makeEventTransaction({sdk: {name: 'sentry.javascript.browser', version: '1.0.0'}})
  141. );
  142. TraceTree.DetectMissingInstrumentation(tree.root);
  143. expect(TraceTree.Find(tree.root, c => isMissingInstrumentationNode(c))).toBeNull();
  144. expect(tree.build().serialize()).toMatchSnapshot();
  145. });
  146. it.each([
  147. ['children', childrenMissingInstrumentationSpans],
  148. ['siblings', missingInstrumentationSpans],
  149. ])('idempotent - %s', (_type, setup) => {
  150. const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
  151. TraceTree.FromSpans(tree.root.children[0].children[0], setup, makeEventTransaction());
  152. TraceTree.DetectMissingInstrumentation(tree.root);
  153. const initial = tree.build().serialize();
  154. expect(tree.build().serialize()).toMatchSnapshot();
  155. expect(tree.build().serialize()).toEqual(initial);
  156. });
  157. });