issuesTraceTree.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import type {Client} from 'sentry/api';
  2. import type {Organization} from 'sentry/types/organization';
  3. import {
  4. isTraceErrorNode,
  5. isTransactionNode,
  6. } from 'sentry/views/performance/newTraceDetails/traceGuards';
  7. import {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
  8. import type {TracePreferencesState} from 'sentry/views/performance/newTraceDetails/traceState/tracePreferences';
  9. import type {ReplayRecord} from 'sentry/views/replays/types';
  10. import type {TraceMetaQueryResults} from '../traceApi/useTraceMeta';
  11. import {CollapsedNode} from '../traceModels/traceCollapsedNode';
  12. import {makeExampleTrace} from './makeExampleTrace';
  13. import type {TraceTreeNode} from './traceTreeNode';
  14. export class IssuesTraceTree extends TraceTree {
  15. static Empty() {
  16. const tree = new IssuesTraceTree().build();
  17. tree.type = 'empty';
  18. return tree;
  19. }
  20. static Loading(metadata: TraceTree.Metadata): IssuesTraceTree {
  21. const t = makeExampleTrace(metadata);
  22. const tree = new IssuesTraceTree();
  23. tree.root = t.root;
  24. tree.type = 'loading';
  25. tree.build();
  26. return tree;
  27. }
  28. static Error(metadata: TraceTree.Metadata): IssuesTraceTree {
  29. const t = makeExampleTrace(metadata);
  30. const tree = new IssuesTraceTree();
  31. tree.root = t.root;
  32. tree.type = 'error';
  33. tree.build();
  34. return tree;
  35. }
  36. static FromTrace(
  37. trace: TraceTree.Trace,
  38. options: {
  39. meta: TraceMetaQueryResults['data'] | null;
  40. replay: ReplayRecord | null;
  41. }
  42. ): IssuesTraceTree {
  43. const tree = super.FromTrace(trace, options);
  44. const issuesTree = new IssuesTraceTree();
  45. issuesTree.root = tree.root;
  46. return issuesTree;
  47. }
  48. static ExpandToEvent(
  49. tree: IssuesTraceTree,
  50. eventId: string,
  51. options: {
  52. api: Client;
  53. organization: Organization;
  54. preferences: Pick<TracePreferencesState, 'autogroup' | 'missing_instrumentation'>;
  55. }
  56. ): Promise<void> {
  57. const node = TraceTree.Find(tree.root, n => {
  58. if (isTraceErrorNode(n)) {
  59. return n.value.event_id === eventId;
  60. }
  61. if (isTransactionNode(n)) {
  62. if (n.value.event_id === eventId) {
  63. return true;
  64. }
  65. for (const e of n.errors) {
  66. if (e.event_id === eventId) {
  67. return true;
  68. }
  69. }
  70. for (const p of n.performance_issues) {
  71. if (p.event_id === eventId) {
  72. return true;
  73. }
  74. }
  75. }
  76. return false;
  77. });
  78. if (node && isTransactionNode(node)) {
  79. return tree.zoom(node, true, options).then(() => {});
  80. }
  81. return Promise.resolve();
  82. }
  83. collapseList(preserveLeafNodes: TraceTreeNode[]) {
  84. const preserveNodes = new Set(preserveLeafNodes);
  85. for (const node of preserveLeafNodes) {
  86. const index = this.list.indexOf(node);
  87. if (index === -1) {
  88. continue;
  89. }
  90. // Preserve the previous 3 nodes
  91. let i = Math.max(index - 1, 0);
  92. while (i > index - 4) {
  93. if (this.list[i]) {
  94. preserveNodes.add(this.list[i]);
  95. }
  96. i--;
  97. }
  98. // Preserve the next 2 nodes
  99. let j = Math.min(index + 1, this.list.length - 1);
  100. while (j < index + 3) {
  101. if (this.list[j]) {
  102. preserveNodes.add(this.list[j]);
  103. }
  104. j++;
  105. }
  106. }
  107. let i = 0;
  108. while (i < this.list.length) {
  109. const start = i;
  110. while (this.list[i] && !preserveNodes.has(this.list[i])) {
  111. i++;
  112. }
  113. if (i - start > 0) {
  114. const collapsedNode = new CollapsedNode(
  115. this.list[start].parent!,
  116. {type: 'collapsed'},
  117. this.list[start].metadata
  118. );
  119. const removed = this.list.splice(start, i - start, collapsedNode);
  120. collapsedNode.children = removed;
  121. i = start + 1;
  122. continue;
  123. }
  124. i++;
  125. }
  126. return this;
  127. }
  128. build() {
  129. super.build();
  130. return this;
  131. }
  132. }