getMetricRuleDiscoverUrl.tsx 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import type {NewQuery, Organization} from 'sentry/types/organization';
  2. import type {Project} from 'sentry/types/project';
  3. import EventView from 'sentry/utils/discover/eventView';
  4. import {getAggregateAlias} from 'sentry/utils/discover/fields';
  5. import type {SavedQueryDatasets} from 'sentry/utils/discover/types';
  6. import type {TimePeriodType} from 'sentry/views/alerts/rules/metric/details/constants';
  7. import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
  8. import {Dataset, TimePeriod} from 'sentry/views/alerts/rules/metric/types';
  9. import {hasDatasetSelector} from 'sentry/views/dashboards/utils';
  10. import {DEFAULT_PROJECT_THRESHOLD} from 'sentry/views/performance/data';
  11. interface MetricRuleDiscoverUrlOptions {
  12. organization: Organization;
  13. projects: Project[];
  14. timePeriod: Omit<TimePeriodType, 'display' | 'label'>;
  15. extraQueryParams?: Partial<NewQuery>;
  16. openInDiscoverDataset?: SavedQueryDatasets;
  17. query?: string;
  18. rule?: MetricRule;
  19. }
  20. /**
  21. * Gets the URL for a discover view of the rule with the following default
  22. * parameters:
  23. *
  24. * - Ordered by the rule aggregate, descending
  25. * - yAxis maps to the aggregate
  26. * - Start and end are the period's values selected in the chart header
  27. */
  28. export function getMetricRuleDiscoverUrl({
  29. organization,
  30. openInDiscoverDataset,
  31. ...rest
  32. }: MetricRuleDiscoverUrlOptions) {
  33. const orgSlug = organization.slug;
  34. const discoverView = getMetricRuleDiscoverQuery(rest);
  35. if (!discoverView || !rest.rule) {
  36. return '';
  37. }
  38. const {query, ...toObject} = discoverView.getResultsViewUrlTarget(
  39. orgSlug,
  40. false,
  41. hasDatasetSelector(organization) ? openInDiscoverDataset : undefined
  42. );
  43. const timeWindowString = `${rest.rule.timeWindow}m`;
  44. return {
  45. query: {...query, interval: timeWindowString},
  46. ...toObject,
  47. };
  48. }
  49. export function getMetricRuleDiscoverQuery({
  50. projects,
  51. rule,
  52. timePeriod,
  53. query,
  54. extraQueryParams,
  55. }: Omit<MetricRuleDiscoverUrlOptions, 'organization' | 'openInDiscoverDataset'>) {
  56. if (!projects || !projects.length || !rule) {
  57. return null;
  58. }
  59. const aggregateAlias = getAggregateAlias(rule.aggregate);
  60. const timePeriodFields = timePeriod.usingPeriod
  61. ? {range: timePeriod.period === TimePeriod.SEVEN_DAYS ? '7d' : timePeriod.period}
  62. : {start: timePeriod.start, end: timePeriod.end};
  63. const fields =
  64. rule.dataset === Dataset.ERRORS
  65. ? ['issue', 'count()', 'count_unique(user)']
  66. : [
  67. 'transaction',
  68. 'project',
  69. `${rule.aggregate}`,
  70. 'count_unique(user)',
  71. `user_misery(${DEFAULT_PROJECT_THRESHOLD})`,
  72. ];
  73. const eventQuery: NewQuery = {
  74. id: undefined,
  75. name: rule?.name || 'Transactions',
  76. fields,
  77. orderby: `-${aggregateAlias}`,
  78. query: query ?? rule.query ?? '',
  79. version: 2,
  80. projects: projects
  81. .filter(({slug}) => rule.projects.includes(slug))
  82. .map(project => Number(project.id)),
  83. environment: rule.environment ? [rule.environment] : undefined,
  84. ...timePeriodFields,
  85. ...extraQueryParams,
  86. };
  87. return EventView.fromSavedQuery(eventQuery);
  88. }