focusArea.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {useMemo} from 'react';
  2. import Feature from 'sentry/components/acl/feature';
  3. import FeatureDisabled from 'sentry/components/acl/featureDisabled';
  4. import Placeholder from 'sentry/components/placeholder';
  5. import {useReplayContext} from 'sentry/components/replays/replayContext';
  6. import {t} from 'sentry/locale';
  7. import type {Crumb} from 'sentry/types/breadcrumbs';
  8. import {isBreadcrumbTypeDefault} from 'sentry/types/breadcrumbs';
  9. import useActiveReplayTab from 'sentry/utils/replays/hooks/useActiveReplayTab';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import Console from 'sentry/views/replays/detail/console';
  12. import DomMutations from 'sentry/views/replays/detail/domMutations';
  13. import IssueList from 'sentry/views/replays/detail/issueList';
  14. import MemoryChart from 'sentry/views/replays/detail/memoryChart';
  15. import NetworkList from 'sentry/views/replays/detail/network';
  16. import Trace from 'sentry/views/replays/detail/trace';
  17. type Props = {};
  18. function getBreadcrumbsByCategory(breadcrumbs: Crumb[], categories: string[]) {
  19. return breadcrumbs
  20. .filter(isBreadcrumbTypeDefault)
  21. .filter(breadcrumb => categories.includes(breadcrumb.category || ''));
  22. }
  23. function FocusArea({}: Props) {
  24. const {getActiveTab} = useActiveReplayTab();
  25. const {currentTime, currentHoverTime, replay, setCurrentTime, setCurrentHoverTime} =
  26. useReplayContext();
  27. const organization = useOrganization();
  28. // Memoize this because re-renders will interfere with the mouse state of the
  29. // chart (e.g. on mouse over and out)
  30. const memorySpans = useMemo(() => {
  31. return replay?.getRawSpans().filter(replay.isMemorySpan);
  32. }, [replay]);
  33. if (!replay || !memorySpans) {
  34. return <Placeholder height="150px" />;
  35. }
  36. const replayRecord = replay.getReplay();
  37. const startTimestampMs = replayRecord.startedAt.getTime();
  38. const getNetworkSpans = () => {
  39. return replay.getRawSpans().filter(replay.isNetworkSpan);
  40. };
  41. switch (getActiveTab()) {
  42. case 'console':
  43. const consoleMessages = getBreadcrumbsByCategory(replay?.getRawCrumbs(), [
  44. 'console',
  45. 'exception',
  46. ]);
  47. return (
  48. <Console
  49. breadcrumbs={consoleMessages ?? []}
  50. startTimestampMs={replayRecord.startedAt.getTime()}
  51. />
  52. );
  53. case 'network':
  54. return <NetworkList replayRecord={replayRecord} networkSpans={getNetworkSpans()} />;
  55. case 'trace':
  56. const features = ['organizations:performance-view'];
  57. const renderDisabled = () => (
  58. <FeatureDisabled
  59. featureName={t('Performance Monitoring')}
  60. features={features}
  61. message={t('Requires performance monitoring.')}
  62. hideHelpToggle
  63. />
  64. );
  65. return (
  66. <Feature
  67. organization={organization}
  68. hookName="feature-disabled:configure-distributed-tracing"
  69. features={features}
  70. renderDisabled={renderDisabled}
  71. >
  72. <Trace organization={organization} replayRecord={replayRecord} />
  73. </Feature>
  74. );
  75. case 'issues':
  76. return <IssueList replayId={replayRecord.id} projectId={replayRecord.projectId} />;
  77. case 'dom':
  78. return <DomMutations replay={replay} />;
  79. case 'memory':
  80. return (
  81. <MemoryChart
  82. currentTime={currentTime}
  83. currentHoverTime={currentHoverTime}
  84. memorySpans={memorySpans}
  85. setCurrentTime={setCurrentTime}
  86. setCurrentHoverTime={setCurrentHoverTime}
  87. startTimestampMs={startTimestampMs}
  88. />
  89. );
  90. default:
  91. return null;
  92. }
  93. }
  94. export default FocusArea;