getMetricRuleDiscoverUrl.tsx 3.0 KB

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