quickTraceMeta.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import type {Location} from 'history';
  2. import Feature from 'sentry/components/acl/feature';
  3. import FeatureDisabled from 'sentry/components/acl/featureDisabled';
  4. import ErrorBoundary from 'sentry/components/errorBoundary';
  5. import {Hovercard} from 'sentry/components/hovercard';
  6. import ExternalLink from 'sentry/components/links/externalLink';
  7. import Placeholder from 'sentry/components/placeholder';
  8. import QuickTrace from 'sentry/components/quickTrace';
  9. import {t} from 'sentry/locale';
  10. import type {Event} from 'sentry/types/event';
  11. import type {AvatarProject} from 'sentry/types/project';
  12. import {getConfigurePerformanceDocsLink} from 'sentry/utils/docs';
  13. import type {
  14. QuickTraceQueryChildrenProps,
  15. TraceMeta,
  16. } from 'sentry/utils/performance/quickTrace/types';
  17. import useOrganization from 'sentry/utils/useOrganization';
  18. import {MetaData} from './styles';
  19. import {TraceLink} from './traceLink';
  20. interface Props
  21. extends Pick<React.ComponentProps<typeof QuickTrace>, 'errorDest' | 'transactionDest'> {
  22. anchor: 'left' | 'right';
  23. event: Event;
  24. location: Location;
  25. quickTrace: QuickTraceQueryChildrenProps | null;
  26. traceMeta: TraceMeta | null;
  27. project?: AvatarProject;
  28. }
  29. export default function QuickTraceMeta({
  30. event,
  31. location,
  32. quickTrace,
  33. traceMeta,
  34. anchor,
  35. errorDest,
  36. transactionDest,
  37. project,
  38. }: Props) {
  39. const organization = useOrganization();
  40. const features = ['performance-view'];
  41. const noFeatureMessage = t('Requires tracing.');
  42. const docsLink = getConfigurePerformanceDocsLink(project);
  43. const traceId = event.contexts?.trace?.trace_id ?? null;
  44. let body: React.ReactNode;
  45. let footer: React.ReactNode;
  46. if (
  47. !traceId ||
  48. !quickTrace ||
  49. (quickTrace.trace === null && !quickTrace.orphanErrors)
  50. ) {
  51. // this platform doesn't support performance don't show anything here
  52. if (docsLink === null) {
  53. return null;
  54. }
  55. body = t('Missing Trace');
  56. // need to configure tracing
  57. footer = <ExternalLink href={docsLink}>{t('Read the docs')}</ExternalLink>;
  58. } else {
  59. if (quickTrace.isLoading) {
  60. body = <Placeholder height="20px" />;
  61. } else if (quickTrace.error) {
  62. body = '\u2014';
  63. } else {
  64. body = (
  65. <ErrorBoundary mini>
  66. <QuickTrace
  67. event={event}
  68. quickTrace={quickTrace}
  69. location={location}
  70. organization={organization}
  71. anchor={anchor}
  72. errorDest={errorDest}
  73. transactionDest={transactionDest}
  74. />
  75. </ErrorBoundary>
  76. );
  77. }
  78. footer = (
  79. <TraceLink
  80. quickTrace={quickTrace}
  81. event={event}
  82. traceMeta={traceMeta}
  83. source="events"
  84. />
  85. );
  86. }
  87. return (
  88. <Feature hookName="feature-disabled:performance-quick-trace" features={features}>
  89. {({hasFeature}) => {
  90. // also need to enable the performance feature
  91. if (!hasFeature) {
  92. footer = (
  93. <Hovercard
  94. body={
  95. <FeatureDisabled
  96. features={features}
  97. hideHelpToggle
  98. message={noFeatureMessage}
  99. featureName={noFeatureMessage}
  100. />
  101. }
  102. >
  103. {footer}
  104. </Hovercard>
  105. );
  106. }
  107. return <QuickTraceMetaBase body={body} footer={footer} />;
  108. }}
  109. </Feature>
  110. );
  111. }
  112. export function QuickTraceMetaBase({
  113. body,
  114. footer,
  115. }: {
  116. body: React.ReactNode;
  117. footer: React.ReactNode;
  118. }) {
  119. return (
  120. <MetaData
  121. headingText={t('Trace Navigator')}
  122. tooltipText={t(
  123. 'An abbreviated version of the full trace. Related frontend and backend services can be added to provide further visibility.'
  124. )}
  125. bodyText={<div data-test-id="quick-trace-body">{body}</div>}
  126. subtext={<div data-test-id="quick-trace-footer">{footer}</div>}
  127. />
  128. );
  129. }