traceGuards.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import {MissingInstrumentationNode} from './traceModels/missingInstrumentationNode';
  2. import {ParentAutogroupNode} from './traceModels/parentAutogroupNode';
  3. import {SiblingAutogroupNode} from './traceModels/siblingAutogroupNode';
  4. import type {TraceTree} from './traceModels/traceTree';
  5. import type {TraceTreeNode} from './traceModels/traceTreeNode';
  6. export function isMissingInstrumentationNode(
  7. node: TraceTreeNode<TraceTree.NodeValue>
  8. ): node is MissingInstrumentationNode {
  9. return node instanceof MissingInstrumentationNode;
  10. }
  11. export function isSpanNode(
  12. node: TraceTreeNode<TraceTree.NodeValue>
  13. ): node is TraceTreeNode<TraceTree.Span> {
  14. return (
  15. !!(node.value && !('transaction' in node.value) && 'span_id' in node.value) &&
  16. !isMissingInstrumentationNode(node) &&
  17. !isAutogroupedNode(node)
  18. );
  19. }
  20. export function isTransactionNode(
  21. node: TraceTreeNode<TraceTree.NodeValue>
  22. ): node is TraceTreeNode<TraceTree.Transaction> {
  23. return !!(node.value && 'transaction' in node.value) && !isAutogroupedNode(node);
  24. }
  25. export function isParentAutogroupedNode(
  26. node: TraceTreeNode<TraceTree.NodeValue>
  27. ): node is ParentAutogroupNode {
  28. return node instanceof ParentAutogroupNode;
  29. }
  30. export function isSiblingAutogroupedNode(
  31. node: TraceTreeNode<TraceTree.NodeValue>
  32. ): node is SiblingAutogroupNode {
  33. return node instanceof SiblingAutogroupNode;
  34. }
  35. export function isAutogroupedNode(
  36. node: TraceTreeNode<TraceTree.NodeValue>
  37. ): node is ParentAutogroupNode | SiblingAutogroupNode {
  38. return node instanceof ParentAutogroupNode || node instanceof SiblingAutogroupNode;
  39. }
  40. export function isTraceErrorNode(
  41. node: TraceTreeNode<TraceTree.NodeValue>
  42. ): node is TraceTreeNode<TraceTree.TraceError> {
  43. return !!(node.value && 'level' in node.value);
  44. }
  45. export function isRootNode(
  46. node: TraceTreeNode<TraceTree.NodeValue>
  47. ): node is TraceTreeNode<null> {
  48. return node.value === null;
  49. }
  50. export function isTraceNode(
  51. node: TraceTreeNode<TraceTree.NodeValue>
  52. ): node is TraceTreeNode<TraceTree.Trace> {
  53. return !!(
  54. node.value &&
  55. ('orphan_errors' in node.value || 'transactions' in node.value)
  56. );
  57. }
  58. export function shouldAddMissingInstrumentationSpan(sdk: string | undefined): boolean {
  59. if (!sdk) {
  60. return true;
  61. }
  62. if (sdk.length < 'sentry.javascript.'.length) {
  63. return true;
  64. }
  65. switch (sdk.toLowerCase()) {
  66. case 'sentry.javascript.browser':
  67. case 'sentry.javascript.react':
  68. case 'sentry.javascript.gatsby':
  69. case 'sentry.javascript.ember':
  70. case 'sentry.javascript.vue':
  71. case 'sentry.javascript.angular':
  72. case 'sentry.javascript.angular-ivy':
  73. case 'sentry.javascript.nextjs':
  74. case 'sentry.javascript.nuxt':
  75. case 'sentry.javascript.electron':
  76. case 'sentry.javascript.remix':
  77. case 'sentry.javascript.svelte':
  78. case 'sentry.javascript.sveltekit':
  79. case 'sentry.javascript.react-native':
  80. case 'sentry.javascript.astro':
  81. return false;
  82. case undefined:
  83. return true;
  84. default:
  85. return true;
  86. }
  87. }
  88. export function isJavascriptSDKTransaction(transaction: TraceTree.Transaction): boolean {
  89. return /javascript|angular|astro|backbone|ember|gatsby|nextjs|react|remix|svelte|vue/.test(
  90. transaction.sdk_name
  91. );
  92. }
  93. export function isPageloadTransactionNode(
  94. node: TraceTreeNode<TraceTree.NodeValue>
  95. ): boolean {
  96. return isTransactionNode(node) && node.value['transaction.op'] === 'pageload';
  97. }
  98. export function isServerRequestHandlerTransactionNode(
  99. node: TraceTreeNode<TraceTree.NodeValue>
  100. ): boolean {
  101. return isTransactionNode(node) && node.value['transaction.op'] === 'http.server';
  102. }
  103. export function isBrowserRequestSpan(value: TraceTree.Span): boolean {
  104. return (
  105. // Adjust for SDK changes in https://github.com/getsentry/sentry-javascript/pull/13527
  106. value.op === 'browser.request' ||
  107. (value.op === 'browser' && value.description === 'request')
  108. );
  109. }
  110. export function getPageloadTransactionChildCount(
  111. node: TraceTreeNode<TraceTree.NodeValue>
  112. ): number {
  113. if (!isTransactionNode(node)) {
  114. return 0;
  115. }
  116. let count = 0;
  117. for (const txn of node.value.children) {
  118. if (txn && txn['transaction.op'] === 'pageload') {
  119. count++;
  120. }
  121. }
  122. return count;
  123. }
  124. export function isTracePerformanceIssue(
  125. issue: TraceTree.TraceError | TraceTree.TracePerformanceIssue
  126. ): issue is TraceTree.TracePerformanceIssue {
  127. return 'suspect_spans' in issue;
  128. }