quickTraceQuery.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import {Fragment} from 'react';
  2. import {Event} from 'sentry/types/event';
  3. import {DiscoverQueryProps} from 'sentry/utils/discover/genericDiscoverQuery';
  4. import {TraceFullQuery} from 'sentry/utils/performance/quickTrace/traceFullQuery';
  5. import TraceLiteQuery from 'sentry/utils/performance/quickTrace/traceLiteQuery';
  6. import {QuickTraceQueryChildrenProps} from 'sentry/utils/performance/quickTrace/types';
  7. import {
  8. flattenRelevantPaths,
  9. getTraceTimeRangeFromEvent,
  10. isCurrentEvent,
  11. } from 'sentry/utils/performance/quickTrace/utils';
  12. type QueryProps = Omit<DiscoverQueryProps, 'api' | 'eventView'> & {
  13. children: (props: QuickTraceQueryChildrenProps) => React.ReactNode;
  14. event: Event | undefined;
  15. };
  16. export default function QuickTraceQuery({children, event, ...props}: QueryProps) {
  17. const renderEmpty = () => (
  18. <Fragment>
  19. {children({
  20. isLoading: false,
  21. error: null,
  22. trace: [],
  23. type: 'empty',
  24. currentEvent: null,
  25. })}
  26. </Fragment>
  27. );
  28. if (!event) {
  29. return renderEmpty();
  30. }
  31. const traceId = event.contexts?.trace?.trace_id;
  32. if (!traceId) {
  33. return renderEmpty();
  34. }
  35. const {start, end} = getTraceTimeRangeFromEvent(event);
  36. return (
  37. <TraceLiteQuery
  38. eventId={event.id}
  39. traceId={traceId}
  40. start={start}
  41. end={end}
  42. {...props}
  43. >
  44. {traceLiteResults => (
  45. <TraceFullQuery
  46. eventId={event.id}
  47. traceId={traceId}
  48. start={start}
  49. end={end}
  50. {...props}
  51. >
  52. {traceFullResults => {
  53. if (
  54. !traceFullResults.isLoading &&
  55. traceFullResults.error === null &&
  56. traceFullResults.traces !== null
  57. ) {
  58. for (const subtrace of traceFullResults.traces) {
  59. try {
  60. const trace = flattenRelevantPaths(event, subtrace);
  61. return children({
  62. ...traceFullResults,
  63. trace,
  64. currentEvent: trace.find(e => isCurrentEvent(e, event)) ?? null,
  65. });
  66. } catch {
  67. // let this fall through and check the next subtrace
  68. // or use the trace lite results
  69. }
  70. }
  71. }
  72. if (
  73. !traceLiteResults.isLoading &&
  74. traceLiteResults.error === null &&
  75. traceLiteResults.trace !== null
  76. ) {
  77. const {trace} = traceLiteResults;
  78. return children({
  79. ...traceLiteResults,
  80. currentEvent: trace.find(e => isCurrentEvent(e, event)) ?? null,
  81. });
  82. }
  83. return children({
  84. // only use the light results loading state if it didn't error
  85. // if it did, we should rely on the full results
  86. isLoading: traceLiteResults.error
  87. ? traceFullResults.isLoading
  88. : traceLiteResults.isLoading || traceFullResults.isLoading,
  89. // swallow any errors from the light results because we
  90. // should rely on the full results in this situations
  91. error: traceFullResults.error,
  92. trace: [],
  93. // if we reach this point but there were some traces in the full results,
  94. // that means there were other transactions in the trace, but the current
  95. // event could not be found
  96. type: traceFullResults.traces?.length ? 'missing' : 'empty',
  97. currentEvent: null,
  98. });
  99. }}
  100. </TraceFullQuery>
  101. )}
  102. </TraceLiteQuery>
  103. );
  104. }