fields.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import invert from 'lodash/invert';
  2. import {ColumnType} from '../discover/fields';
  3. export enum SessionMetric {
  4. SENTRY_SESSIONS_SESSION = 'sentry.sessions.session',
  5. SENTRY_SESSIONS_SESSION_DURATION = 'sentry.sessions.session.duration',
  6. SENTRY_SESSIONS_SESSION_ERROR = 'sentry.sessions.session.error',
  7. SENTRY_SESSIONS_USER = 'sentry.sessions.user',
  8. }
  9. export enum TransactionMetric {
  10. SENTRY_TRANSACTIONS_MEASUREMENTS_FP = 'sentry.transactions.measurements.fp',
  11. SENTRY_TRANSACTIONS_MEASUREMENTS_FCP = 'sentry.transactions.measurements.fcp',
  12. SENTRY_TRANSACTIONS_MEASUREMENTS_LCP = 'sentry.transactions.measurements.lcp',
  13. SENTRY_TRANSACTIONS_MEASUREMENTS_FID = 'sentry.transactions.measurements.fid',
  14. SENTRY_TRANSACTIONS_MEASUREMENTS_CLS = 'sentry.transactions.measurements.cls',
  15. SENTRY_TRANSACTIONS_MEASUREMENTS_TTFB = 'sentry.transactions.measurements.ttfb',
  16. SENTRY_TRANSACTIONS_MEASUREMENTS_TTFB_REQUESTTIME = 'sentry.transactions.measurements.ttfb.requesttime',
  17. SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_COLD = 'sentry.transactions.measurements.app_start_cold',
  18. SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_WARM = 'sentry.transactions.measurements.app_start_warm',
  19. SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_TOTAL = 'sentry.transactions.measurements.frames_total',
  20. SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_SLOW = 'sentry.transactions.measurements.frames_slow',
  21. SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_FROZEN = 'sentry.transactions.measurements.frames_frozen',
  22. SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_SLOW_RATE = 'sentry.transactions.measurements.frames_slow_rate',
  23. SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_FROZEN_RATE = 'sentry.transactions.measurements.frames_frozen_rate',
  24. SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_COUNT = 'sentry.transactions.measurements.stall_count',
  25. SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_TOTAL_TIME = 'sentry.transactions.measurements.stall_total_time',
  26. SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_LONGEST_TIME = 'sentry.transactions.measurements.stall_longest_time',
  27. SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_PERCENTAGE = 'sentry.transactions.measurements.stall_percentage',
  28. SENTRY_TRANSACTIONS_TRANSACTION_DURATION = 'sentry.transactions.transaction.duration',
  29. SENTRY_TRANSACTIONS_USER = 'sentry.transactions.user',
  30. SENTRY_TRANSACTIONS_TRANSACTION = 'transaction',
  31. }
  32. export const METRIC_TO_COLUMN_TYPE: Readonly<
  33. Record<SessionMetric | TransactionMetric, ColumnType>
  34. > = {
  35. // Session metrics
  36. [SessionMetric.SENTRY_SESSIONS_USER]: 'integer',
  37. [SessionMetric.SENTRY_SESSIONS_SESSION_ERROR]: 'integer',
  38. [SessionMetric.SENTRY_SESSIONS_SESSION_DURATION]: 'duration',
  39. [SessionMetric.SENTRY_SESSIONS_SESSION]: 'integer',
  40. // Transaction metrics
  41. [TransactionMetric.SENTRY_TRANSACTIONS_USER]: 'integer',
  42. [TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION]: 'string',
  43. [TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION]: 'duration',
  44. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FP]: 'duration',
  45. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FCP]: 'duration',
  46. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_LCP]: 'duration',
  47. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FID]: 'duration',
  48. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_CLS]: 'number',
  49. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_TTFB]: 'duration',
  50. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_TTFB_REQUESTTIME]: 'duration',
  51. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_COLD]: 'duration',
  52. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_WARM]: 'duration',
  53. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_TOTAL]: 'integer',
  54. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_SLOW]: 'integer',
  55. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_FROZEN]: 'integer',
  56. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_SLOW_RATE]: 'percentage',
  57. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_FROZEN_RATE]: 'percentage',
  58. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_COUNT]: 'integer',
  59. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_TOTAL_TIME]: 'duration',
  60. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_LONGEST_TIME]: 'duration',
  61. [TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_STALL_PERCENTAGE]: 'percentage',
  62. };
  63. // This is not the full map, just what we need for performance table.
  64. // In the future we might want something more generic that strips the aggregate functions.
  65. const DISCOVER_FIELD_TO_METRIC = {
  66. 'count_unique(user)': `count_unique(${TransactionMetric.SENTRY_TRANSACTIONS_USER})`,
  67. 'tpm()': `count(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  68. 'p75(measurements.fcp)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FCP})`,
  69. 'p75(measurements.lcp)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_LCP})`,
  70. 'p75(measurements.fid)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FID})`,
  71. 'p75(measurements.cls)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_CLS})`,
  72. 'p50()': `p50(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  73. 'p95()': `p95(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  74. 'p50(transaction.duration)': `p50(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  75. 'p75(transaction.duration)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  76. 'p95(transaction.duration)': `p95(${TransactionMetric.SENTRY_TRANSACTIONS_TRANSACTION_DURATION})`,
  77. 'p75(measurements.app_start_cold)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_COLD})`,
  78. 'p75(measurements.app_start_warm)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_APP_START_WARM})`,
  79. 'p75(measurements.frames_slow_rate)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_SLOW_RATE})`,
  80. 'p75(measurements.frames_frozen_rate)': `p75(${TransactionMetric.SENTRY_TRANSACTIONS_MEASUREMENTS_FRAMES_FROZEN_RATE})`,
  81. // TODO(metrics):
  82. // transaction.op
  83. // http.method
  84. // failure_rate()
  85. // apdex()
  86. // count_miserable(user)
  87. // user_misery()
  88. // team_key_transaction
  89. };
  90. const DISCOVER_FIELD_TO_METRIC_GROUP_BY = {
  91. transaction: 'transaction',
  92. project: 'project_id',
  93. };
  94. const METRIC_TO_DISCOVER_FIELD = invert(DISCOVER_FIELD_TO_METRIC);
  95. const METRIC_GROUP_BY_TO_DISCOVER_FIELD = invert(DISCOVER_FIELD_TO_METRIC_GROUP_BY);
  96. export function convertDiscoverFieldsToMetrics<T extends string | string[]>(
  97. discoverFields: T
  98. ): T {
  99. if (Array.isArray(discoverFields)) {
  100. return discoverFields
  101. .map(field => DISCOVER_FIELD_TO_METRIC[field])
  102. .filter(metric => metric !== undefined) as T;
  103. }
  104. return DISCOVER_FIELD_TO_METRIC[discoverFields as string] ?? '';
  105. }
  106. export function convertDiscoverFieldsToMetricsGroupBys<T extends string | string[]>(
  107. discoverFields: T
  108. ): T {
  109. if (Array.isArray(discoverFields)) {
  110. return discoverFields
  111. .map(field => DISCOVER_FIELD_TO_METRIC_GROUP_BY[field])
  112. .filter(metricGroupBy => metricGroupBy !== undefined) as T;
  113. }
  114. return DISCOVER_FIELD_TO_METRIC_GROUP_BY[discoverFields as string] ?? '';
  115. }
  116. export function convertMetricsToDiscoverFields<T extends string | string[]>(
  117. metrics: T
  118. ): T {
  119. if (Array.isArray(metrics)) {
  120. return metrics
  121. .map(metric => METRIC_TO_DISCOVER_FIELD[metric])
  122. .filter(field => field !== undefined) as T;
  123. }
  124. return (METRIC_TO_DISCOVER_FIELD[metrics as string] ?? '') as T;
  125. }
  126. export function convertMetricsGroupBysToDiscoverFields<T extends string | string[]>(
  127. metricsGroupBys: T
  128. ): T {
  129. if (Array.isArray(metricsGroupBys)) {
  130. return metricsGroupBys
  131. .map(metricGroupBy => METRIC_GROUP_BY_TO_DISCOVER_FIELD[metricGroupBy])
  132. .filter(field => field !== undefined) as T;
  133. }
  134. return (METRIC_GROUP_BY_TO_DISCOVER_FIELD[metricsGroupBys as string] ?? '') as T;
  135. }