error.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import {useMemo} from 'react';
  2. import {useTheme} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import {LinkButton} from 'sentry/components/button';
  5. import {
  6. getStacktrace,
  7. StackTracePreviewContent,
  8. } from 'sentry/components/groupPreviewTooltip/stackTracePreview';
  9. import LoadingIndicator from 'sentry/components/loadingIndicator';
  10. import {generateIssueEventTarget} from 'sentry/components/quickTrace/utils';
  11. import {t} from 'sentry/locale';
  12. import type {EventError} from 'sentry/types/event';
  13. import {useApiQuery} from 'sentry/utils/queryClient';
  14. import {TraceIcons} from 'sentry/views/performance/newTraceDetails/icons';
  15. import type {TraceTreeNodeDetailsProps} from 'sentry/views/performance/newTraceDetails/traceDrawer/tabs/traceTreeNodeDetails';
  16. import {getTraceTabTitle} from 'sentry/views/performance/newTraceDetails/traceState/traceTabs';
  17. import {
  18. makeTraceNodeBarColor,
  19. type TraceTree,
  20. type TraceTreeNode,
  21. } from '../../traceModels/traceTree';
  22. import {IssueList} from './issues/issues';
  23. import {type SectionCardKeyValueList, TraceDrawerComponents} from './styles';
  24. export function ErrorNodeDetails({
  25. node,
  26. organization,
  27. onTabScrollToNode,
  28. onParentClick,
  29. }: TraceTreeNodeDetailsProps<TraceTreeNode<TraceTree.TraceError>>) {
  30. const issues = useMemo(() => {
  31. return [...node.errors];
  32. }, [node.errors]);
  33. const {isPending, data} = useApiQuery<EventError>(
  34. [
  35. `/organizations/${organization.slug}/events/${node.value.project_slug}:${node.value.event_id}/`,
  36. ],
  37. {
  38. staleTime: 2 * 60 * 1000,
  39. }
  40. );
  41. const stackTrace = useMemo(() => {
  42. if (data) {
  43. return getStacktrace(data);
  44. }
  45. return null;
  46. }, [data]);
  47. const theme = useTheme();
  48. const parentTransaction = node.parent_transaction;
  49. const items: SectionCardKeyValueList = [
  50. {
  51. key: 'title',
  52. subject: t('Title'),
  53. value: <TraceDrawerComponents.CopyableCardValueWithLink value={node.value.title} />,
  54. },
  55. ];
  56. if (parentTransaction) {
  57. items.push({
  58. key: 'parent_transaction',
  59. subject: t('Parent Transaction'),
  60. value: (
  61. <a onClick={() => onParentClick(parentTransaction)}>
  62. {getTraceTabTitle(parentTransaction)}
  63. </a>
  64. ),
  65. });
  66. }
  67. return isPending ? (
  68. <LoadingIndicator />
  69. ) : data ? (
  70. <TraceDrawerComponents.DetailContainer>
  71. <TraceDrawerComponents.HeaderContainer>
  72. <TraceDrawerComponents.Title>
  73. <TraceDrawerComponents.IconBorder
  74. backgroundColor={makeTraceNodeBarColor(theme, node)}
  75. >
  76. <TraceIcons.Icon event={node.value} />
  77. </TraceDrawerComponents.IconBorder>
  78. <TraceDrawerComponents.TitleText>
  79. <div>{node.value.level ?? t('error')}</div>
  80. <TraceDrawerComponents.TitleOp
  81. text={node.value.message ?? node.value.title ?? 'Error'}
  82. />
  83. </TraceDrawerComponents.TitleText>
  84. </TraceDrawerComponents.Title>
  85. <TraceDrawerComponents.Actions>
  86. <TraceDrawerComponents.NodeActions
  87. node={node}
  88. organization={organization}
  89. onTabScrollToNode={onTabScrollToNode}
  90. />
  91. <LinkButton size="xs" to={generateIssueEventTarget(node.value, organization)}>
  92. {t('Go to Issue')}
  93. </LinkButton>
  94. </TraceDrawerComponents.Actions>
  95. </TraceDrawerComponents.HeaderContainer>
  96. <IssueList issues={issues} node={node} organization={organization} />
  97. <TraceDrawerComponents.SectionCard
  98. items={[
  99. {
  100. key: 'stack_trace',
  101. subject: t('Stack Trace'),
  102. subjectNode: null,
  103. value:
  104. stackTrace && data ? (
  105. <StackTraceWrapper>
  106. <StackTracePreviewContent event={data} stacktrace={stackTrace} />
  107. </StackTraceWrapper>
  108. ) : (
  109. t('No stack trace has been reported with this error')
  110. ),
  111. },
  112. ]}
  113. title={t('Stack Trace')}
  114. />
  115. <TraceDrawerComponents.SectionCard items={items} title={t('General')} />
  116. <TraceDrawerComponents.EventTags
  117. projectSlug={node.value.project_slug}
  118. event={data}
  119. />
  120. </TraceDrawerComponents.DetailContainer>
  121. ) : null;
  122. }
  123. const StackTraceWrapper = styled('div')`
  124. .traceback {
  125. margin-bottom: 0;
  126. border: 0;
  127. }
  128. `;