metricIssuesSection.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {LinkButton} from 'sentry/components/button';
  2. import {t} from 'sentry/locale';
  3. import type {Group} from 'sentry/types/group';
  4. import type {Organization} from 'sentry/types/organization';
  5. import type {Project} from 'sentry/types/project';
  6. import {useLocation} from 'sentry/utils/useLocation';
  7. import RelatedIssues from 'sentry/views/alerts/rules/metric/details/relatedIssues';
  8. import RelatedTransactions from 'sentry/views/alerts/rules/metric/details/relatedTransactions';
  9. import {Dataset} from 'sentry/views/alerts/rules/metric/types';
  10. import {extractEventTypeFilterFromRule} from 'sentry/views/alerts/rules/metric/utils/getEventTypeFilter';
  11. import {isCrashFreeAlert} from 'sentry/views/alerts/rules/metric/utils/isCrashFreeAlert';
  12. import {useMetricRule} from 'sentry/views/alerts/rules/metric/utils/useMetricRule';
  13. import {
  14. useMetricIssueAlertId,
  15. useMetricTimePeriod,
  16. } from 'sentry/views/issueDetails/metricIssues/utils';
  17. import {SectionKey} from 'sentry/views/issueDetails/streamline/context';
  18. import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection';
  19. interface MetricIssuesSectionProps {
  20. group: Group;
  21. organization: Organization;
  22. project: Project;
  23. }
  24. export function MetricIssuesSection({
  25. organization,
  26. group,
  27. project,
  28. }: MetricIssuesSectionProps) {
  29. const location = useLocation();
  30. const ruleId = useMetricIssueAlertId({groupId: group.id});
  31. const {data: rule} = useMetricRule(
  32. {
  33. orgSlug: organization.slug,
  34. ruleId: ruleId ?? '',
  35. query: {
  36. expand: 'latestIncident',
  37. },
  38. },
  39. {
  40. staleTime: Infinity,
  41. retry: false,
  42. enabled: !!ruleId,
  43. }
  44. );
  45. const timePeriod = useMetricTimePeriod({openPeriod: group.openPeriods?.[0]});
  46. if (!rule || !timePeriod) {
  47. return null;
  48. }
  49. const {dataset, query} = rule;
  50. if ([Dataset.METRICS, Dataset.SESSIONS, Dataset.ERRORS].includes(dataset)) {
  51. const queryParams = {
  52. start: timePeriod.start,
  53. end: timePeriod.end,
  54. groupStatsPeriod: 'auto',
  55. ...(rule.environment ? {environment: rule.environment} : {}),
  56. sort: rule.aggregate === 'count_unique(user)' ? 'user' : 'freq',
  57. query,
  58. project: [project.id],
  59. };
  60. const issueSearch = {
  61. pathname: `/organizations/${organization.slug}/issues/`,
  62. query: queryParams,
  63. };
  64. const actions = (
  65. <LinkButton data-test-id="issues-open" size="xs" to={issueSearch}>
  66. {t('Open in Issues')}
  67. </LinkButton>
  68. );
  69. return (
  70. <InterimSection
  71. title={t('Correlated Issues')}
  72. type={SectionKey.CORRELATED_ISSUES}
  73. help={t('A list of issues that are correlated with this event')}
  74. actions={actions}
  75. >
  76. <RelatedIssues
  77. organization={organization}
  78. rule={rule}
  79. projects={[project]}
  80. timePeriod={timePeriod}
  81. query={
  82. dataset === Dataset.ERRORS
  83. ? // Not using (query) AND (event.type:x) because issues doesn't support it yet
  84. `${extractEventTypeFilterFromRule(rule)} ${query}`.trim()
  85. : isCrashFreeAlert(dataset)
  86. ? `${query} error.unhandled:true`.trim()
  87. : undefined
  88. }
  89. skipHeader
  90. />
  91. </InterimSection>
  92. );
  93. }
  94. if ([Dataset.TRANSACTIONS, Dataset.GENERIC_METRICS].includes(dataset)) {
  95. return (
  96. <InterimSection
  97. title={t('Correlated Transactions')}
  98. type={SectionKey.CORRELATED_TRANSACTIONS}
  99. help={t('A list of transactions that are correlated with this event')}
  100. >
  101. <RelatedTransactions
  102. organization={organization}
  103. location={location}
  104. rule={rule}
  105. projects={[project]}
  106. timePeriod={timePeriod}
  107. filter={extractEventTypeFilterFromRule(rule)}
  108. />
  109. </InterimSection>
  110. );
  111. }
  112. return null;
  113. }