fields.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import invert from 'lodash/invert';
  2. import {
  3. SelectValue,
  4. SessionAggregationColumn,
  5. SessionField,
  6. SessionsMeta,
  7. SessionsOperation,
  8. SessionStatus,
  9. } from 'sentry/types';
  10. import {defined} from 'sentry/utils';
  11. import {SessionMetric} from 'sentry/utils/metrics/fields';
  12. import {FieldValue, FieldValueKind} from 'sentry/views/eventsV2/table/types';
  13. export const DERIVED_STATUS_METRICS_PATTERN =
  14. /count_(abnormal|errored|crashed|healthy)\((user|session)\)/;
  15. export enum DerivedStatusFields {
  16. HEALTHY_SESSIONS = 'count_healthy(session)',
  17. HEALTHY_USERS = 'count_healthy(user)',
  18. ABNORMAL_SESSIONS = 'count_abnormal(session)',
  19. ABNORMAL_USERS = 'count_abnormal(user)',
  20. CRASHED_SESSIONS = 'count_crashed(session)',
  21. CRASHED_USERS = 'count_crashed(user)',
  22. ERRORED_SESSIONS = 'count_errored(session)',
  23. ERRORED_USERS = 'count_errored(user)',
  24. }
  25. export const FIELD_TO_METRICS_EXPRESSION = {
  26. 'count_healthy(session)': SessionMetric.SESSION_HEALTHY,
  27. 'count_healthy(user)': SessionMetric.USER_HEALTHY,
  28. 'count_abnormal(session)': SessionMetric.SESSION_ABNORMAL,
  29. 'count_abnormal(user)': SessionMetric.USER_ABNORMAL,
  30. 'count_crashed(session)': SessionMetric.SESSION_CRASHED,
  31. 'count_crashed(user)': SessionMetric.USER_CRASHED,
  32. 'count_errored(session)': SessionMetric.SESSION_ERRORED,
  33. 'count_errored(user)': SessionMetric.USER_ERRORED,
  34. 'count_unique(user)': `count_unique(${SessionMetric.USER})`,
  35. 'sum(session)': `sum(${SessionMetric.SESSION})`,
  36. 'crash_free_rate(session)': SessionMetric.SESSION_CRASH_FREE_RATE,
  37. 'crash_free_rate(user)': SessionMetric.USER_CRASH_FREE_RATE,
  38. 'crash_rate(session)': SessionMetric.SESSION_CRASH_RATE,
  39. 'crash_rate(user)': SessionMetric.USER_CRASH_RATE,
  40. project: 'project_id',
  41. };
  42. export const METRICS_EXPRESSION_TO_FIELD = invert(FIELD_TO_METRICS_EXPRESSION);
  43. export const DISABLED_SORT = [
  44. 'count_errored(session)',
  45. 'count_errored(user)',
  46. 'count_healthy(session)',
  47. 'count_healthy(user)',
  48. 'session.status',
  49. ];
  50. export const TAG_SORT_DENY_LIST = ['project', 'environment'];
  51. export const SESSIONS_FIELDS: Readonly<Partial<Record<SessionField, SessionsMeta>>> = {
  52. [SessionField.SESSION]: {
  53. name: 'session',
  54. operations: [
  55. 'sum',
  56. 'crash_rate',
  57. 'crash_free_rate',
  58. 'count_healthy',
  59. 'count_abnormal',
  60. 'count_crashed',
  61. 'count_errored',
  62. ],
  63. type: 'integer',
  64. },
  65. [SessionField.USER]: {
  66. name: 'user',
  67. operations: [
  68. 'count_unique',
  69. 'crash_rate',
  70. 'crash_free_rate',
  71. 'count_healthy',
  72. 'count_abnormal',
  73. 'count_crashed',
  74. 'count_errored',
  75. ],
  76. type: 'string',
  77. },
  78. [SessionField.SESSION_DURATION]: {
  79. name: 'session.duration',
  80. operations: [],
  81. type: 'duration',
  82. },
  83. };
  84. export const SESSIONS_OPERATIONS: Readonly<
  85. Record<SessionsOperation, SessionAggregationColumn>
  86. > = {
  87. sum: {
  88. outputType: 'integer',
  89. parameters: [
  90. {
  91. kind: 'column',
  92. columnTypes: ['integer'],
  93. defaultValue: SessionField.SESSION,
  94. required: true,
  95. },
  96. ],
  97. },
  98. count_unique: {
  99. outputType: 'integer',
  100. parameters: [
  101. {
  102. kind: 'column',
  103. columnTypes: ['string'],
  104. defaultValue: SessionField.USER,
  105. required: true,
  106. },
  107. ],
  108. },
  109. count_healthy: {
  110. outputType: 'integer',
  111. parameters: [
  112. {
  113. kind: 'column',
  114. columnTypes: ['integer', 'string'],
  115. defaultValue: SessionField.SESSION,
  116. required: true,
  117. },
  118. ],
  119. },
  120. count_abnormal: {
  121. outputType: 'integer',
  122. parameters: [
  123. {
  124. kind: 'column',
  125. columnTypes: ['integer', 'string'],
  126. defaultValue: SessionField.SESSION,
  127. required: true,
  128. },
  129. ],
  130. },
  131. count_crashed: {
  132. outputType: 'integer',
  133. parameters: [
  134. {
  135. kind: 'column',
  136. columnTypes: ['integer', 'string'],
  137. defaultValue: SessionField.SESSION,
  138. required: true,
  139. },
  140. ],
  141. },
  142. count_errored: {
  143. outputType: 'integer',
  144. parameters: [
  145. {
  146. kind: 'column',
  147. columnTypes: ['integer', 'string'],
  148. defaultValue: SessionField.SESSION,
  149. required: true,
  150. },
  151. ],
  152. },
  153. crash_rate: {
  154. outputType: 'percentage',
  155. parameters: [
  156. {
  157. kind: 'column',
  158. columnTypes: ['integer', 'string'],
  159. defaultValue: SessionField.SESSION,
  160. required: true,
  161. },
  162. ],
  163. },
  164. crash_free_rate: {
  165. outputType: 'percentage',
  166. parameters: [
  167. {
  168. kind: 'column',
  169. columnTypes: ['integer', 'string'],
  170. defaultValue: SessionField.SESSION,
  171. required: true,
  172. },
  173. ],
  174. },
  175. };
  176. export const SESSIONS_TAGS = ['environment', 'project', 'release', 'session.status'];
  177. export const SESSIONS_FILTER_TAGS = ['environment', 'project', 'release'];
  178. export const SESSION_STATUSES = Object.values(SessionStatus);
  179. export function generateReleaseWidgetFieldOptions(
  180. fields: SessionsMeta[] = Object.values(SESSIONS_FIELDS),
  181. tagKeys?: string[]
  182. ) {
  183. const fieldOptions: Record<string, SelectValue<FieldValue>> = {};
  184. const operations = new Set<SessionsOperation>();
  185. const knownOperations = Object.keys(SESSIONS_OPERATIONS);
  186. fields
  187. .sort((a, b) => a.name.localeCompare(b.name))
  188. .forEach(field => {
  189. field.operations.forEach(operation => operations.add(operation));
  190. fieldOptions[`field:${field.name}`] = {
  191. label: field.name,
  192. value: {
  193. kind: FieldValueKind.METRICS,
  194. meta: {
  195. name: field.name,
  196. dataType: field.type,
  197. },
  198. },
  199. };
  200. });
  201. Array.from(operations)
  202. .filter(operation => knownOperations.includes(operation))
  203. .sort((a, b) => a.localeCompare(b))
  204. .forEach(operation => {
  205. fieldOptions[`function:${operation}`] = {
  206. label: `${operation}(${'\u2026'})`,
  207. value: {
  208. kind: FieldValueKind.FUNCTION,
  209. meta: {
  210. name: operation,
  211. parameters: SESSIONS_OPERATIONS[operation].parameters.map(param => param),
  212. },
  213. },
  214. };
  215. });
  216. if (defined(tagKeys)) {
  217. // Expose environment. session.status, project etc. as fields.
  218. tagKeys
  219. .sort((a, b) => a.localeCompare(b))
  220. .forEach(tag => {
  221. fieldOptions[`field:${tag}`] = {
  222. label: tag,
  223. value: {
  224. kind: FieldValueKind.FIELD,
  225. meta: {name: tag, dataType: 'string'},
  226. },
  227. };
  228. });
  229. }
  230. return fieldOptions;
  231. }