index.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import {useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import * as Sentry from '@sentry/react';
  4. import NoProjectMessage from 'sentry/components/noProjectMessage';
  5. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import useOrganization from 'sentry/utils/useOrganization';
  9. import {useParams} from 'sentry/utils/useParams';
  10. import {TraceWaterfall} from 'sentry/views/performance/newTraceDetails/traceWaterfall';
  11. import {useTrace} from './traceApi/useTrace';
  12. import {useTraceMeta} from './traceApi/useTraceMeta';
  13. import {useTraceRootEvent} from './traceApi/useTraceRootEvent';
  14. import {useTraceTree} from './traceApi/useTraceTree';
  15. import {
  16. DEFAULT_TRACE_VIEW_PREFERENCES,
  17. loadTraceViewPreferences,
  18. } from './traceState/tracePreferences';
  19. import {TraceStateProvider} from './traceState/traceStateProvider';
  20. import {TraceMetaDataHeader} from './traceHeader';
  21. import {useTraceEventView} from './useTraceEventView';
  22. import {useTraceQueryParams} from './useTraceQueryParams';
  23. function decodeTraceSlug(maybeSlug: string | undefined): string {
  24. if (!maybeSlug || maybeSlug === 'null' || maybeSlug === 'undefined') {
  25. Sentry.withScope(scope => {
  26. scope.setFingerprint(['trace-null-slug']);
  27. Sentry.captureMessage(`Trace slug is empty`);
  28. });
  29. return '';
  30. }
  31. return maybeSlug.trim();
  32. }
  33. export function TraceView() {
  34. const organization = useOrganization();
  35. const params = useParams<{traceSlug?: string}>();
  36. const traceSlug = useMemo(() => decodeTraceSlug(params.traceSlug), [params.traceSlug]);
  37. const queryParams = useTraceQueryParams();
  38. const traceEventView = useTraceEventView(traceSlug, queryParams);
  39. const preferences = useMemo(
  40. () =>
  41. loadTraceViewPreferences('trace-view-preferences') ||
  42. DEFAULT_TRACE_VIEW_PREFERENCES,
  43. []
  44. );
  45. const meta = useTraceMeta([{traceSlug, timestamp: queryParams.timestamp}]);
  46. const trace = useTrace({traceSlug, timestamp: queryParams.timestamp});
  47. const rootEvent = useTraceRootEvent(trace.data ?? null);
  48. const tree = useTraceTree({traceSlug, trace, meta, replay: null});
  49. return (
  50. <SentryDocumentTitle
  51. title={`${t('Trace Details')} - ${traceSlug}`}
  52. orgSlug={organization.slug}
  53. >
  54. <TraceStateProvider
  55. initialPreferences={preferences}
  56. preferencesStorageKey="trace-view-preferences"
  57. >
  58. <NoProjectMessage organization={organization}>
  59. <TraceExternalLayout>
  60. <TraceMetaDataHeader
  61. rootEventResults={rootEvent}
  62. tree={tree}
  63. metaResults={meta}
  64. organization={organization}
  65. traceSlug={traceSlug}
  66. traceEventView={traceEventView}
  67. />
  68. <TraceInnerLayout>
  69. <TraceWaterfall
  70. tree={tree}
  71. trace={trace}
  72. meta={meta}
  73. replay={null}
  74. source="performance"
  75. rootEvent={rootEvent}
  76. traceSlug={traceSlug}
  77. traceEventView={traceEventView}
  78. organization={organization}
  79. />
  80. </TraceInnerLayout>
  81. </TraceExternalLayout>
  82. </NoProjectMessage>
  83. </TraceStateProvider>
  84. </SentryDocumentTitle>
  85. );
  86. }
  87. const TraceExternalLayout = styled('div')`
  88. display: flex;
  89. flex-direction: column;
  90. flex: 1 1 100%;
  91. ~ footer {
  92. display: none;
  93. }
  94. `;
  95. const TraceInnerLayout = styled('div')`
  96. display: flex;
  97. flex-direction: column;
  98. flex: 1 1 100%;
  99. padding: ${space(2)};
  100. background-color: ${p => p.theme.background};
  101. `;