options.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import mapValues from 'lodash/mapValues';
  2. import {t} from 'sentry/locale';
  3. import {Organization, TagCollection} from 'sentry/types';
  4. import {
  5. FieldKey,
  6. makeTagCollection,
  7. MobileVital,
  8. SpanOpBreakdown,
  9. WebVital,
  10. } from 'sentry/utils/fields';
  11. import {
  12. Dataset,
  13. EventTypes,
  14. SessionsAggregate,
  15. } from 'sentry/views/alerts/rules/metric/types';
  16. export type AlertType =
  17. | 'issues'
  18. | 'num_errors'
  19. | 'users_experiencing_errors'
  20. | 'throughput'
  21. | 'trans_duration'
  22. | 'apdex'
  23. | 'failure_rate'
  24. | 'lcp'
  25. | 'fid'
  26. | 'cls'
  27. | 'custom'
  28. | 'crash_free_sessions'
  29. | 'crash_free_users';
  30. export enum MEPAlertsQueryType {
  31. ERROR = 0,
  32. PERFORMANCE = 1,
  33. CRASH_RATE = 2,
  34. }
  35. export enum MEPAlertsDataset {
  36. DISCOVER = 'discover',
  37. METRICS = 'metrics',
  38. METRICS_ENHANCED = 'metricsEnhanced',
  39. }
  40. export type MetricAlertType = Exclude<AlertType, 'issues'>;
  41. export const DatasetMEPAlertQueryTypes: Record<Dataset, MEPAlertsQueryType> = {
  42. [Dataset.ERRORS]: MEPAlertsQueryType.ERROR,
  43. [Dataset.TRANSACTIONS]: MEPAlertsQueryType.PERFORMANCE,
  44. [Dataset.GENERIC_METRICS]: MEPAlertsQueryType.PERFORMANCE,
  45. [Dataset.METRICS]: MEPAlertsQueryType.CRASH_RATE,
  46. [Dataset.SESSIONS]: MEPAlertsQueryType.CRASH_RATE,
  47. };
  48. export const AlertWizardAlertNames: Record<AlertType, string> = {
  49. issues: t('Issues'),
  50. num_errors: t('Number of Errors'),
  51. users_experiencing_errors: t('Users Experiencing Errors'),
  52. throughput: t('Throughput'),
  53. trans_duration: t('Transaction Duration'),
  54. apdex: t('Apdex'),
  55. failure_rate: t('Failure Rate'),
  56. lcp: t('Largest Contentful Paint'),
  57. fid: t('First Input Delay'),
  58. cls: t('Cumulative Layout Shift'),
  59. custom: t('Custom Metric'),
  60. crash_free_sessions: t('Crash Free Session Rate'),
  61. crash_free_users: t('Crash Free User Rate'),
  62. };
  63. type AlertWizardCategory = {
  64. categoryHeading: string;
  65. options: AlertType[];
  66. };
  67. export const getAlertWizardCategories = (org: Organization): AlertWizardCategory[] => [
  68. {
  69. categoryHeading: t('Errors'),
  70. options: ['issues', 'num_errors', 'users_experiencing_errors'],
  71. },
  72. ...(org.features.includes('crash-rate-alerts')
  73. ? [
  74. {
  75. categoryHeading: t('Sessions'),
  76. options: ['crash_free_sessions', 'crash_free_users'] as AlertType[],
  77. },
  78. ]
  79. : []),
  80. {
  81. categoryHeading: t('Performance'),
  82. options: [
  83. 'throughput',
  84. 'trans_duration',
  85. 'apdex',
  86. 'failure_rate',
  87. 'lcp',
  88. 'fid',
  89. 'cls',
  90. ],
  91. },
  92. {
  93. categoryHeading: t('Other'),
  94. options: ['custom'],
  95. },
  96. ];
  97. export type WizardRuleTemplate = {
  98. aggregate: string;
  99. dataset: Dataset;
  100. eventTypes: EventTypes;
  101. };
  102. export const AlertWizardRuleTemplates: Record<
  103. MetricAlertType,
  104. Readonly<WizardRuleTemplate>
  105. > = {
  106. num_errors: {
  107. aggregate: 'count()',
  108. dataset: Dataset.ERRORS,
  109. eventTypes: EventTypes.ERROR,
  110. },
  111. users_experiencing_errors: {
  112. aggregate: 'count_unique(user)',
  113. dataset: Dataset.ERRORS,
  114. eventTypes: EventTypes.ERROR,
  115. },
  116. throughput: {
  117. aggregate: 'count()',
  118. dataset: Dataset.TRANSACTIONS,
  119. eventTypes: EventTypes.TRANSACTION,
  120. },
  121. trans_duration: {
  122. aggregate: 'p95(transaction.duration)',
  123. dataset: Dataset.TRANSACTIONS,
  124. eventTypes: EventTypes.TRANSACTION,
  125. },
  126. apdex: {
  127. aggregate: 'apdex(300)',
  128. dataset: Dataset.TRANSACTIONS,
  129. eventTypes: EventTypes.TRANSACTION,
  130. },
  131. failure_rate: {
  132. aggregate: 'failure_rate()',
  133. dataset: Dataset.TRANSACTIONS,
  134. eventTypes: EventTypes.TRANSACTION,
  135. },
  136. lcp: {
  137. aggregate: 'p95(measurements.lcp)',
  138. dataset: Dataset.TRANSACTIONS,
  139. eventTypes: EventTypes.TRANSACTION,
  140. },
  141. fid: {
  142. aggregate: 'p95(measurements.fid)',
  143. dataset: Dataset.TRANSACTIONS,
  144. eventTypes: EventTypes.TRANSACTION,
  145. },
  146. cls: {
  147. aggregate: 'p95(measurements.cls)',
  148. dataset: Dataset.TRANSACTIONS,
  149. eventTypes: EventTypes.TRANSACTION,
  150. },
  151. custom: {
  152. aggregate: 'p95(measurements.fp)',
  153. dataset: Dataset.TRANSACTIONS,
  154. eventTypes: EventTypes.TRANSACTION,
  155. },
  156. crash_free_sessions: {
  157. aggregate: SessionsAggregate.CRASH_FREE_SESSIONS,
  158. // TODO(scttcper): Use Dataset.Metric on GA of alert-crash-free-metrics
  159. dataset: Dataset.SESSIONS,
  160. eventTypes: EventTypes.SESSION,
  161. },
  162. crash_free_users: {
  163. aggregate: SessionsAggregate.CRASH_FREE_USERS,
  164. // TODO(scttcper): Use Dataset.Metric on GA of alert-crash-free-metrics
  165. dataset: Dataset.SESSIONS,
  166. eventTypes: EventTypes.USER,
  167. },
  168. };
  169. export const DEFAULT_WIZARD_TEMPLATE = AlertWizardRuleTemplates.num_errors;
  170. export const hidePrimarySelectorSet = new Set<AlertType>([
  171. 'num_errors',
  172. 'users_experiencing_errors',
  173. 'throughput',
  174. 'apdex',
  175. 'failure_rate',
  176. 'crash_free_sessions',
  177. 'crash_free_users',
  178. ]);
  179. export const hideParameterSelectorSet = new Set<AlertType>([
  180. 'trans_duration',
  181. 'lcp',
  182. 'fid',
  183. 'cls',
  184. ]);
  185. const TRANSACTION_SUPPORTED_TAGS = [
  186. FieldKey.RELEASE,
  187. FieldKey.TRANSACTION,
  188. FieldKey.TRANSACTION_OP,
  189. FieldKey.TRANSACTION_STATUS,
  190. FieldKey.HTTP_METHOD,
  191. ];
  192. const SESSION_SUPPORTED_TAGS = [FieldKey.RELEASE];
  193. // Some data sets support a very limited number of tags. For these cases,
  194. // define all supported tags explicitly
  195. export const DATASET_SUPPORTED_TAGS: Record<Dataset, TagCollection | undefined> =
  196. mapValues(
  197. {
  198. [Dataset.ERRORS]: undefined,
  199. [Dataset.TRANSACTIONS]: TRANSACTION_SUPPORTED_TAGS,
  200. [Dataset.METRICS]: SESSION_SUPPORTED_TAGS,
  201. [Dataset.GENERIC_METRICS]: TRANSACTION_SUPPORTED_TAGS,
  202. [Dataset.SESSIONS]: SESSION_SUPPORTED_TAGS,
  203. },
  204. value => {
  205. return value ? makeTagCollection(value) : undefined;
  206. }
  207. );
  208. // Some data sets support all tags except some. For these cases, define the
  209. // omissions only
  210. export const DATASET_OMITTED_TAGS: Record<
  211. Dataset,
  212. Array<FieldKey | WebVital | MobileVital | SpanOpBreakdown> | undefined
  213. > = {
  214. [Dataset.ERRORS]: [
  215. FieldKey.EVENT_TYPE,
  216. FieldKey.RELEASE_VERSION,
  217. FieldKey.RELEASE_STAGE,
  218. FieldKey.RELEASE_BUILD,
  219. FieldKey.PROJECT,
  220. ...Object.values(WebVital),
  221. ...Object.values(MobileVital),
  222. ...Object.values(SpanOpBreakdown),
  223. FieldKey.TRANSACTION,
  224. FieldKey.TRANSACTION_DURATION,
  225. FieldKey.TRANSACTION_OP,
  226. FieldKey.TRANSACTION_STATUS,
  227. ],
  228. [Dataset.TRANSACTIONS]: undefined,
  229. [Dataset.METRICS]: undefined,
  230. [Dataset.GENERIC_METRICS]: undefined,
  231. [Dataset.SESSIONS]: undefined,
  232. };
  233. export function getMEPAlertsDataset(
  234. dataset: Dataset,
  235. newAlert: boolean
  236. ): MEPAlertsDataset {
  237. // Dataset.ERRORS overrides all cases
  238. if (dataset === Dataset.ERRORS) {
  239. return MEPAlertsDataset.DISCOVER;
  240. }
  241. if (newAlert) {
  242. return MEPAlertsDataset.METRICS_ENHANCED;
  243. }
  244. if (dataset === Dataset.GENERIC_METRICS) {
  245. return MEPAlertsDataset.METRICS;
  246. }
  247. return MEPAlertsDataset.DISCOVER;
  248. }