index.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import {useMemo} from 'react';
  2. import {Button} from 'sentry/components/button';
  3. import {EventContexts} from 'sentry/components/events/contexts';
  4. import {EventAttachments} from 'sentry/components/events/eventAttachments';
  5. import {EventEvidence} from 'sentry/components/events/eventEvidence';
  6. import {EventExtraData} from 'sentry/components/events/eventExtraData';
  7. import {EventSdk} from 'sentry/components/events/eventSdk';
  8. import {EventViewHierarchy} from 'sentry/components/events/eventViewHierarchy';
  9. import {EventRRWebIntegration} from 'sentry/components/events/rrwebIntegration';
  10. import FileSize from 'sentry/components/fileSize';
  11. import ProjectBadge from 'sentry/components/idBadge/projectBadge';
  12. import type {LazyRenderProps} from 'sentry/components/lazyRender';
  13. import LoadingError from 'sentry/components/loadingError';
  14. import LoadingIndicator from 'sentry/components/loadingIndicator';
  15. import {Tooltip} from 'sentry/components/tooltip';
  16. import {IconOpen} from 'sentry/icons';
  17. import {t} from 'sentry/locale';
  18. import type {EventTransaction, Organization, Project} from 'sentry/types';
  19. import {useLocation} from 'sentry/utils/useLocation';
  20. import useProjects from 'sentry/utils/useProjects';
  21. import {CustomMetricsEventData} from 'sentry/views/metrics/customMetricsEventData';
  22. import {useTransaction} from 'sentry/views/performance/newTraceDetails/traceApi/useTransaction';
  23. import type {TraceTreeNodeDetailsProps} from 'sentry/views/performance/newTraceDetails/traceDrawer/tabs/traceTreeNodeDetails';
  24. import type {
  25. TraceTree,
  26. TraceTreeNode,
  27. } from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
  28. import {IssueList} from '../issues/issues';
  29. import {TraceDrawerComponents} from '../styles';
  30. import {BreadCrumbs} from './sections/breadCrumbs';
  31. import {Entries} from './sections/entries';
  32. import ReplayPreview from './sections/replayPreview';
  33. import {Table} from './sections/table';
  34. import {EventTags} from './sections/tags';
  35. export const LAZY_RENDER_PROPS: Partial<LazyRenderProps> = {
  36. observerOptions: {rootMargin: '50px'},
  37. };
  38. type TransactionNodeDetailHeaderProps = {
  39. event: EventTransaction;
  40. node: TraceTreeNode<TraceTree.Transaction>;
  41. onTabScrollToNode: (node: TraceTreeNode<TraceTree.Transaction>) => void;
  42. organization: Organization;
  43. project: Project | undefined;
  44. };
  45. function TransactionNodeDetailHeader({
  46. node,
  47. organization,
  48. project,
  49. onTabScrollToNode,
  50. event,
  51. }: TransactionNodeDetailHeaderProps) {
  52. return (
  53. <TraceDrawerComponents.HeaderContainer>
  54. <TraceDrawerComponents.Title>
  55. <Tooltip title={node.value.project_slug}>
  56. <ProjectBadge
  57. project={project ? project : {slug: node.value.project_slug}}
  58. avatarSize={30}
  59. hideName
  60. />
  61. </Tooltip>
  62. <TraceDrawerComponents.TitleText>
  63. <div>{t('transaction')}</div>
  64. <TraceDrawerComponents.TitleOp>
  65. {' '}
  66. {node.value['transaction.op'] + ' - ' + node.value.transaction}
  67. </TraceDrawerComponents.TitleOp>
  68. </TraceDrawerComponents.TitleText>
  69. </TraceDrawerComponents.Title>
  70. <TraceDrawerComponents.Actions>
  71. <Button size="xs" onClick={_e => onTabScrollToNode(node)}>
  72. {t('Show in view')}
  73. </Button>
  74. <TraceDrawerComponents.EventDetailsLink node={node} organization={organization} />
  75. <Button
  76. size="xs"
  77. icon={<IconOpen />}
  78. href={`/api/0/projects/${organization.slug}/${node.value.project_slug}/events/${node.value.event_id}/json/`}
  79. external
  80. >
  81. {t('JSON')} (<FileSize bytes={event?.size} />)
  82. </Button>
  83. </TraceDrawerComponents.Actions>
  84. </TraceDrawerComponents.HeaderContainer>
  85. );
  86. }
  87. export function TransactionNodeDetails({
  88. node,
  89. organization,
  90. onTabScrollToNode,
  91. onParentClick,
  92. }: TraceTreeNodeDetailsProps<TraceTreeNode<TraceTree.Transaction>>) {
  93. const location = useLocation();
  94. const {projects} = useProjects();
  95. const issues = useMemo(() => {
  96. return [...node.errors, ...node.performance_issues];
  97. }, [node.errors, node.performance_issues]);
  98. const {
  99. data: event,
  100. isError,
  101. isLoading,
  102. } = useTransaction({
  103. node,
  104. organization,
  105. });
  106. if (isLoading) {
  107. return <LoadingIndicator />;
  108. }
  109. if (isError) {
  110. return <LoadingError message={t('Failed to fetch transaction details')} />;
  111. }
  112. const project = projects.find(proj => proj.slug === event?.projectSlug);
  113. return (
  114. <TraceDrawerComponents.DetailContainer>
  115. <TransactionNodeDetailHeader
  116. node={node}
  117. organization={organization}
  118. project={project}
  119. event={event}
  120. onTabScrollToNode={onTabScrollToNode}
  121. />
  122. <IssueList node={node} organization={organization} issues={issues} />
  123. <Table
  124. node={node}
  125. onParentClick={onParentClick}
  126. organization={organization}
  127. event={event}
  128. location={location}
  129. />
  130. <EventTags
  131. node={node}
  132. organization={organization}
  133. event={event}
  134. location={location}
  135. />
  136. <EventContexts event={event} />
  137. {project ? <EventEvidence event={event} project={project} /> : null}
  138. <ReplayPreview event={event} organization={organization} />
  139. {event.projectSlug ? (
  140. <Entries
  141. definedEvent={event}
  142. projectSlug={event.projectSlug}
  143. group={undefined}
  144. organization={organization}
  145. />
  146. ) : null}
  147. <EventExtraData event={event} />
  148. <EventSdk sdk={event.sdk} meta={event._meta?.sdk} />
  149. {event._metrics_summary ? (
  150. <CustomMetricsEventData
  151. metricsSummary={event._metrics_summary}
  152. startTimestamp={event.startTimestamp}
  153. projectId={event.projectID}
  154. />
  155. ) : null}
  156. <BreadCrumbs event={event} organization={organization} />
  157. {event.projectSlug ? (
  158. <EventAttachments event={event} projectSlug={event.projectSlug} />
  159. ) : null}
  160. {project ? <EventViewHierarchy event={event} project={project} /> : null}
  161. {event.projectSlug ? (
  162. <EventRRWebIntegration
  163. event={event}
  164. orgId={organization.slug}
  165. projectSlug={event.projectSlug}
  166. />
  167. ) : null}
  168. </TraceDrawerComponents.DetailContainer>
  169. );
  170. }