groupEventDetailsContent.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import Feature from 'sentry/components/acl/feature';
  4. import {CommitRow} from 'sentry/components/commitRow';
  5. import ErrorBoundary from 'sentry/components/errorBoundary';
  6. import {EventContexts} from 'sentry/components/events/contexts';
  7. import {EventDevice} from 'sentry/components/events/device';
  8. import {EventAttachments} from 'sentry/components/events/eventAttachments';
  9. import {EventDataSection} from 'sentry/components/events/eventDataSection';
  10. import {EventEntry} from 'sentry/components/events/eventEntry';
  11. import {EventEvidence} from 'sentry/components/events/eventEvidence';
  12. import {EventExtraData} from 'sentry/components/events/eventExtraData';
  13. import EventReplay from 'sentry/components/events/eventReplay';
  14. import {EventSdk} from 'sentry/components/events/eventSdk';
  15. import AggregateSpanDiff from 'sentry/components/events/eventStatisticalDetector/aggregateSpanDiff';
  16. import EventBreakpointChart from 'sentry/components/events/eventStatisticalDetector/breakpointChart';
  17. import {EventAffectedTransactions} from 'sentry/components/events/eventStatisticalDetector/eventAffectedTransactions';
  18. import EventComparison from 'sentry/components/events/eventStatisticalDetector/eventComparison';
  19. import {EventDifferentialFlamegraph} from 'sentry/components/events/eventStatisticalDetector/eventDifferentialFlamegraph';
  20. import {EventFunctionComparisonList} from 'sentry/components/events/eventStatisticalDetector/eventFunctionComparisonList';
  21. import {EventRegressionSummary} from 'sentry/components/events/eventStatisticalDetector/eventRegressionSummary';
  22. import {EventFunctionBreakpointChart} from 'sentry/components/events/eventStatisticalDetector/functionBreakpointChart';
  23. import {TransactionsDeltaProvider} from 'sentry/components/events/eventStatisticalDetector/transactionsDeltaProvider';
  24. import {EventTagsAndScreenshot} from 'sentry/components/events/eventTagsAndScreenshot';
  25. import {EventViewHierarchy} from 'sentry/components/events/eventViewHierarchy';
  26. import {EventGroupingInfo} from 'sentry/components/events/groupingInfo';
  27. import {ActionableItems} from 'sentry/components/events/interfaces/crashContent/exception/actionableItems';
  28. import {actionableItemsEnabled} from 'sentry/components/events/interfaces/crashContent/exception/useActionableItems';
  29. import {CronTimelineSection} from 'sentry/components/events/interfaces/crons/cronTimelineSection';
  30. import {AnrRootCause} from 'sentry/components/events/interfaces/performance/anrRootCause';
  31. import {SpanEvidenceSection} from 'sentry/components/events/interfaces/performance/spanEvidence';
  32. import {EventPackageData} from 'sentry/components/events/packageData';
  33. import {EventRRWebIntegration} from 'sentry/components/events/rrwebIntegration';
  34. import {DataSection} from 'sentry/components/events/styles';
  35. import {SuspectCommits} from 'sentry/components/events/suspectCommits';
  36. import {EventUserFeedback} from 'sentry/components/events/userFeedback';
  37. import Panel from 'sentry/components/panels/panel';
  38. import {t} from 'sentry/locale';
  39. import {space} from 'sentry/styles/space';
  40. import {Event, Group, IssueCategory, IssueType, Project} from 'sentry/types';
  41. import {EntryType, EventTransaction} from 'sentry/types/event';
  42. import {useLocation} from 'sentry/utils/useLocation';
  43. import useOrganization from 'sentry/utils/useOrganization';
  44. import {ResourcesAndMaybeSolutions} from 'sentry/views/issueDetails/resourcesAndMaybeSolutions';
  45. type GroupEventDetailsContentProps = {
  46. group: Group;
  47. project: Project;
  48. event?: Event;
  49. };
  50. type GroupEventEntryProps = {
  51. entryType: EntryType;
  52. event: Event;
  53. group: Group;
  54. project: Project;
  55. };
  56. function GroupEventEntry({event, entryType, group, project}: GroupEventEntryProps) {
  57. const organization = useOrganization();
  58. const matchingEntry = event.entries.find(entry => entry.type === entryType);
  59. if (!matchingEntry) {
  60. return null;
  61. }
  62. return (
  63. <EventEntry
  64. projectSlug={project.slug}
  65. group={group}
  66. entry={matchingEntry}
  67. {...{organization, event}}
  68. />
  69. );
  70. }
  71. function DefaultGroupEventDetailsContent({
  72. group,
  73. event,
  74. project,
  75. }: Required<GroupEventDetailsContentProps>) {
  76. const organization = useOrganization();
  77. const location = useLocation();
  78. const projectSlug = project.slug;
  79. const hasReplay = Boolean(event.tags?.find(({key}) => key === 'replayId')?.value);
  80. const mechanism = event.tags?.find(({key}) => key === 'mechanism')?.value;
  81. const isANR = mechanism === 'ANR' || mechanism === 'AppExitInfo';
  82. const hasAnrImprovementsFeature = organization.features.includes('anr-improvements');
  83. const eventEntryProps = {group, event, project};
  84. const hasActionableItems = actionableItemsEnabled({
  85. eventId: event.id,
  86. organization,
  87. projectSlug,
  88. });
  89. return (
  90. <Fragment>
  91. {hasActionableItems && (
  92. <ActionableItems event={event} project={project} isShare={false} />
  93. )}
  94. <SuspectCommits
  95. project={project}
  96. eventId={event.id}
  97. group={group}
  98. commitRow={CommitRow}
  99. />
  100. {event.userReport && (
  101. <EventDataSection title="User Feedback" type="user-feedback">
  102. <EventUserFeedback
  103. report={event.userReport}
  104. orgSlug={organization.slug}
  105. issueId={group.id}
  106. />
  107. </EventDataSection>
  108. )}
  109. {group.issueCategory === IssueCategory.CRON && (
  110. <CronTimelineSection event={event} organization={organization} />
  111. )}
  112. <EventTagsAndScreenshot
  113. event={event}
  114. organization={organization}
  115. projectSlug={project.slug}
  116. location={location}
  117. />
  118. <EventEvidence event={event} group={group} projectSlug={project.slug} />
  119. <GroupEventEntry entryType={EntryType.MESSAGE} {...eventEntryProps} />
  120. <GroupEventEntry entryType={EntryType.EXCEPTION} {...eventEntryProps} />
  121. <GroupEventEntry entryType={EntryType.STACKTRACE} {...eventEntryProps} />
  122. <GroupEventEntry entryType={EntryType.THREADS} {...eventEntryProps} />
  123. {hasAnrImprovementsFeature && isANR && (
  124. <AnrRootCause event={event} organization={organization} />
  125. )}
  126. {group.issueCategory === IssueCategory.PERFORMANCE && (
  127. <SpanEvidenceSection
  128. event={event as EventTransaction}
  129. organization={organization}
  130. projectSlug={project.slug}
  131. />
  132. )}
  133. <EventReplay event={event} group={group} projectSlug={project.slug} />
  134. <GroupEventEntry entryType={EntryType.HPKP} {...eventEntryProps} />
  135. <GroupEventEntry entryType={EntryType.CSP} {...eventEntryProps} />
  136. <GroupEventEntry entryType={EntryType.EXPECTCT} {...eventEntryProps} />
  137. <GroupEventEntry entryType={EntryType.EXPECTSTAPLE} {...eventEntryProps} />
  138. <GroupEventEntry entryType={EntryType.TEMPLATE} {...eventEntryProps} />
  139. <GroupEventEntry entryType={EntryType.BREADCRUMBS} {...eventEntryProps} />
  140. <ResourcesAndMaybeSolutions
  141. event={event}
  142. projectSlug={project.slug}
  143. group={group}
  144. />
  145. <GroupEventEntry entryType={EntryType.DEBUGMETA} {...eventEntryProps} />
  146. <GroupEventEntry entryType={EntryType.REQUEST} {...eventEntryProps} />
  147. <EventContexts group={group} event={event} />
  148. <EventExtraData event={event} />
  149. <EventPackageData event={event} />
  150. <EventDevice event={event} />
  151. <EventViewHierarchy event={event} project={project} />
  152. <EventAttachments event={event} projectSlug={project.slug} />
  153. <EventSdk sdk={event.sdk} meta={event._meta?.sdk} />
  154. {event.groupID && (
  155. <EventGroupingInfo
  156. projectSlug={project.slug}
  157. event={event}
  158. showGroupingConfig={
  159. organization.features.includes('set-grouping-config') &&
  160. 'groupingConfig' in event
  161. }
  162. group={group}
  163. />
  164. )}
  165. {!hasReplay && (
  166. <EventRRWebIntegration
  167. event={event}
  168. orgId={organization.slug}
  169. projectSlug={project.slug}
  170. />
  171. )}
  172. </Fragment>
  173. );
  174. }
  175. function PerformanceDurationRegressionIssueDetailsContent({
  176. group,
  177. event,
  178. project,
  179. }: Required<GroupEventDetailsContentProps>) {
  180. return (
  181. <Fragment>
  182. <ErrorBoundary mini>
  183. <EventRegressionSummary event={event} group={group} />
  184. </ErrorBoundary>
  185. <ErrorBoundary mini>
  186. <EventBreakpointChart event={event} />
  187. </ErrorBoundary>
  188. <ErrorBoundary mini>
  189. <AggregateSpanDiff event={event} project={project} />
  190. </ErrorBoundary>
  191. <ErrorBoundary mini>
  192. <EventComparison event={event} project={project} />
  193. </ErrorBoundary>
  194. </Fragment>
  195. );
  196. }
  197. function ProfilingDurationRegressionIssueDetailsContent({
  198. group,
  199. event,
  200. project,
  201. }: Required<GroupEventDetailsContentProps>) {
  202. const organization = useOrganization();
  203. return (
  204. <TransactionsDeltaProvider event={event} project={project}>
  205. <Fragment>
  206. <ErrorBoundary mini>
  207. <EventRegressionSummary event={event} group={group} />
  208. </ErrorBoundary>
  209. <ErrorBoundary mini>
  210. <EventFunctionBreakpointChart event={event} />
  211. </ErrorBoundary>
  212. <ErrorBoundary mini>
  213. <EventAffectedTransactions event={event} group={group} project={project} />
  214. </ErrorBoundary>
  215. <Feature features="profiling-differential-flamegraph" organization={organization}>
  216. <ErrorBoundary mini>
  217. <DataSection>
  218. <b>{t('Largest Changes in Call Stack Frequency')}</b>
  219. <p>
  220. {t(`See which functions changed the most before and after the regression. The
  221. frame with the largest increase in call stack population likely
  222. contributed to the cause for the duration regression.`)}
  223. </p>
  224. <Panel>
  225. <EventDifferentialFlamegraph event={event} />
  226. </Panel>
  227. </DataSection>
  228. </ErrorBoundary>
  229. </Feature>
  230. <ErrorBoundary mini>
  231. <EventFunctionComparisonList event={event} group={group} project={project} />
  232. </ErrorBoundary>
  233. </Fragment>
  234. </TransactionsDeltaProvider>
  235. );
  236. }
  237. function GroupEventDetailsContent({
  238. group,
  239. event,
  240. project,
  241. }: GroupEventDetailsContentProps) {
  242. if (!event) {
  243. return (
  244. <NotFoundMessage>
  245. <h3>{t('Latest event not available')}</h3>
  246. </NotFoundMessage>
  247. );
  248. }
  249. switch (group.issueType) {
  250. case IssueType.PERFORMANCE_DURATION_REGRESSION:
  251. case IssueType.PERFORMANCE_ENDPOINT_REGRESSION: {
  252. return (
  253. <PerformanceDurationRegressionIssueDetailsContent
  254. group={group}
  255. event={event}
  256. project={project}
  257. />
  258. );
  259. }
  260. case IssueType.PROFILE_FUNCTION_REGRESSION_EXPERIMENTAL:
  261. case IssueType.PROFILE_FUNCTION_REGRESSION: {
  262. return (
  263. <ProfilingDurationRegressionIssueDetailsContent
  264. group={group}
  265. event={event}
  266. project={project}
  267. />
  268. );
  269. }
  270. default: {
  271. return (
  272. <DefaultGroupEventDetailsContent group={group} event={event} project={project} />
  273. );
  274. }
  275. }
  276. }
  277. const NotFoundMessage = styled('div')`
  278. padding: ${space(2)} ${space(4)};
  279. `;
  280. export default GroupEventDetailsContent;