getMetricRuleDiscoverUrl.tsx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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 discoverView = getMetricRuleDiscoverQuery(rest);
  34. if (!discoverView || !rest.rule) {
  35. return '';
  36. }
  37. const {query, ...toObject} = discoverView.getResultsViewUrlTarget(
  38. organization,
  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. }