allEventsTable.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import {useEffect, useState} from 'react';
  2. import {Location} from 'history';
  3. import LoadingError from 'sentry/components/loadingError';
  4. import {
  5. PlatformCategory,
  6. PlatformKey,
  7. profiling as PROFILING_PLATFORMS,
  8. } from 'sentry/data/platformCategories';
  9. import {t} from 'sentry/locale';
  10. import {Group, IssueCategory, Organization} from 'sentry/types';
  11. import EventView, {decodeSorts} from 'sentry/utils/discover/eventView';
  12. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  13. import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
  14. import {platformToCategory} from 'sentry/utils/platform';
  15. import {useRoutes} from 'sentry/utils/useRoutes';
  16. import EventsTable from 'sentry/views/performance/transactionSummary/transactionEvents/eventsTable';
  17. export interface Props {
  18. group: Group;
  19. issueId: string;
  20. location: Location;
  21. organization: Organization;
  22. excludedTags?: string[];
  23. }
  24. function AllEventsTable(props: Props) {
  25. const {location, organization, issueId, excludedTags, group} = props;
  26. const config = getConfigForIssueType(props.group);
  27. const [error, setError] = useState<string>('');
  28. const routes = useRoutes();
  29. const {fields, columnTitles} = getColumns(group, organization);
  30. const eventView: EventView = EventView.fromLocation(props.location);
  31. if (config.usesIssuePlatform) {
  32. eventView.dataset = DiscoverDatasets.ISSUE_PLATFORM;
  33. }
  34. eventView.fields = fields.map(fieldName => ({field: fieldName}));
  35. eventView.sorts = decodeSorts(location).filter(sort => fields.includes(sort.field));
  36. useEffect(() => {
  37. setError('');
  38. }, [eventView.query]);
  39. if (!eventView.sorts.length) {
  40. eventView.sorts = [{field: 'timestamp', kind: 'desc'}];
  41. }
  42. const idQuery =
  43. group.issueCategory === IssueCategory.PERFORMANCE
  44. ? `performance.issue_ids:${issueId} event.type:transaction`
  45. : `issue.id:${issueId}`;
  46. eventView.project = [parseInt(group.project.id, 10)];
  47. eventView.query = `${idQuery} ${props.location.query.query || ''}`;
  48. eventView.statsPeriod = '90d';
  49. if (error) {
  50. return <LoadingError message={error} onRetry={() => setError('')} />;
  51. }
  52. return (
  53. <EventsTable
  54. eventView={eventView}
  55. location={location}
  56. issueId={issueId}
  57. organization={organization}
  58. routes={routes}
  59. excludedTags={excludedTags}
  60. projectSlug={group.project.slug}
  61. customColumns={['minidump']}
  62. setError={(msg: string | undefined) => setError(msg ?? '')}
  63. transactionName=""
  64. columnTitles={columnTitles.slice()}
  65. referrer="api.issues.issue_events"
  66. />
  67. );
  68. }
  69. type ColumnInfo = {columnTitles: string[]; fields: string[]};
  70. const getColumns = (group: Group, organization: Organization): ColumnInfo => {
  71. const isPerfIssue = group.issueCategory === IssueCategory.PERFORMANCE;
  72. const isReplayEnabled = organization.features.includes('session-replay');
  73. // profiles only exist on transactions, so this only works with
  74. // performance issues, and not errors
  75. const isProfilingEnabled = isPerfIssue && organization.features.includes('profiling');
  76. const {fields: platformSpecificFields, columnTitles: platformSpecificColumnTitles} =
  77. getPlatformColumns(group.project.platform ?? group.platform, {
  78. isProfilingEnabled,
  79. isReplayEnabled,
  80. });
  81. const fields: string[] = [
  82. 'id',
  83. 'transaction',
  84. 'title',
  85. 'release',
  86. 'environment',
  87. 'user.display',
  88. 'device',
  89. 'os',
  90. ...platformSpecificFields,
  91. ...(isPerfIssue ? ['transaction.duration'] : []),
  92. 'timestamp',
  93. ];
  94. const columnTitles: string[] = [
  95. t('event id'),
  96. t('transaction'),
  97. t('title'),
  98. t('release'),
  99. t('environment'),
  100. t('user'),
  101. t('device'),
  102. t('os'),
  103. ...platformSpecificColumnTitles,
  104. ...(isPerfIssue ? [t('total duration')] : []),
  105. t('timestamp'),
  106. t('minidump'),
  107. ];
  108. return {
  109. fields,
  110. columnTitles,
  111. };
  112. };
  113. const getPlatformColumns = (
  114. platform: PlatformKey | undefined,
  115. options: {isProfilingEnabled: boolean; isReplayEnabled: boolean}
  116. ): ColumnInfo => {
  117. const backendServerlessColumnInfo = {
  118. fields: ['url', 'runtime'],
  119. columnTitles: [t('url'), t('runtime')],
  120. };
  121. const categoryToColumnMap: Record<PlatformCategory, ColumnInfo> = {
  122. [PlatformCategory.BACKEND]: backendServerlessColumnInfo,
  123. [PlatformCategory.SERVERLESS]: backendServerlessColumnInfo,
  124. [PlatformCategory.FRONTEND]: {
  125. fields: ['url', 'browser'],
  126. columnTitles: [t('url'), t('browser')],
  127. },
  128. [PlatformCategory.MOBILE]: {
  129. fields: ['url'],
  130. columnTitles: [t('url')],
  131. },
  132. [PlatformCategory.DESKTOP]: {
  133. fields: [],
  134. columnTitles: [],
  135. },
  136. [PlatformCategory.OTHER]: {
  137. fields: [],
  138. columnTitles: [],
  139. },
  140. };
  141. const platformCategory = platformToCategory(platform);
  142. const platformColumns = categoryToColumnMap[platformCategory];
  143. if (options.isReplayEnabled) {
  144. platformColumns.fields.push('replayId');
  145. platformColumns.columnTitles.push(t('replay'));
  146. }
  147. if (options.isProfilingEnabled && platform && PROFILING_PLATFORMS.includes(platform)) {
  148. platformColumns.columnTitles.push(t('profile'));
  149. platformColumns.fields.push('profile.id');
  150. }
  151. return platformColumns;
  152. };
  153. export default AllEventsTable;