data.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import {t} from 'sentry/locale';
  2. import ConfigStore from 'sentry/stores/configStore';
  3. import {TOP_N} from 'sentry/utils/discover/types';
  4. import type {Widget} from '../types';
  5. import {DisplayType, WidgetType} from '../types';
  6. export type WidgetTemplate = Widget & {
  7. description: string;
  8. };
  9. export const getDefaultWidgets = () => {
  10. const isSelfHostedErrorsOnly = ConfigStore.get('isSelfHostedErrorsOnly');
  11. const transactionsWidgets = [
  12. {
  13. id: 'duration-distribution',
  14. title: t('Duration Distribution'),
  15. description: t('Compare transaction durations across different percentiles.'),
  16. displayType: DisplayType.LINE,
  17. widgetType: WidgetType.DISCOVER,
  18. interval: '5m',
  19. queries: [
  20. {
  21. name: '',
  22. conditions: 'event.type:transaction',
  23. fields: [
  24. 'p50(transaction.duration)',
  25. 'p75(transaction.duration)',
  26. 'p95(transaction.duration)',
  27. ],
  28. aggregates: [
  29. 'p50(transaction.duration)',
  30. 'p75(transaction.duration)',
  31. 'p95(transaction.duration)',
  32. ],
  33. columns: [],
  34. orderby: '',
  35. },
  36. ],
  37. },
  38. {
  39. id: 'high-throughput-transactions',
  40. title: t('High Throughput Transactions'),
  41. description: t('Top 5 transactions with the largest volume.'),
  42. displayType: DisplayType.TOP_N,
  43. widgetType: WidgetType.DISCOVER,
  44. interval: '5m',
  45. queries: [
  46. {
  47. name: '',
  48. conditions: 'event.type:transaction',
  49. fields: ['transaction', 'count()'],
  50. aggregates: ['count()'],
  51. columns: ['transaction'],
  52. orderby: '-count()',
  53. },
  54. ],
  55. },
  56. {
  57. id: 'crash-rates-recent-releases',
  58. title: t('Crash Rates for Recent Releases'),
  59. description: t('Percentage of crashed sessions for latest releases.'),
  60. displayType: DisplayType.LINE,
  61. widgetType: WidgetType.RELEASE,
  62. interval: '5m',
  63. limit: 8,
  64. queries: [
  65. {
  66. name: '',
  67. conditions: '',
  68. fields: ['crash_rate(session)', 'release'],
  69. aggregates: ['crash_rate(session)'],
  70. columns: ['release'],
  71. orderby: '-release',
  72. },
  73. ],
  74. },
  75. {
  76. id: 'session-health',
  77. title: t('Session Health'),
  78. description: t('Number of abnormal, crashed, errored and healthy sessions.'),
  79. displayType: DisplayType.TABLE,
  80. widgetType: WidgetType.RELEASE,
  81. interval: '5m',
  82. queries: [
  83. {
  84. name: '',
  85. conditions: '',
  86. fields: ['session.status', 'sum(session)'],
  87. aggregates: ['sum(session)'],
  88. columns: ['session.status'],
  89. orderby: '-sum(session)',
  90. },
  91. ],
  92. },
  93. {
  94. id: 'lcp-country',
  95. title: t('LCP by Country'),
  96. description: t('Table showing page load times by country.'),
  97. displayType: DisplayType.TABLE,
  98. widgetType: WidgetType.DISCOVER,
  99. interval: '5m',
  100. queries: [
  101. {
  102. name: '',
  103. conditions: 'has:geo.country_code',
  104. fields: ['geo.country_code', 'geo.region', 'p75(measurements.lcp)'],
  105. aggregates: ['p75(measurements.lcp)'],
  106. columns: ['geo.country_code', 'geo.region'],
  107. orderby: '-p75(measurements.lcp)',
  108. },
  109. ],
  110. },
  111. {
  112. id: 'miserable-users',
  113. title: t('Miserable Users'),
  114. description: t('Unique users who have experienced slow load times.'),
  115. displayType: DisplayType.BIG_NUMBER,
  116. widgetType: WidgetType.DISCOVER,
  117. interval: '5m',
  118. queries: [
  119. {
  120. name: '',
  121. conditions: '',
  122. fields: ['count_miserable(user,300)'],
  123. aggregates: ['count_miserable(user,300)'],
  124. columns: [],
  125. orderby: '',
  126. },
  127. ],
  128. },
  129. {
  130. id: 'slow-vs-fast',
  131. title: t('Slow vs. Fast Transactions'),
  132. description: t(
  133. 'Percentage breakdown of transaction durations over and under 300ms.'
  134. ),
  135. displayType: DisplayType.BAR,
  136. widgetType: WidgetType.DISCOVER,
  137. interval: '5m',
  138. queries: [
  139. {
  140. name: '',
  141. conditions: 'event.type:transaction',
  142. fields: [
  143. 'equation|(count_if(transaction.duration,greater,300) / count()) * 100',
  144. 'equation|(count_if(transaction.duration,lessOrEquals,300) / count()) * 100',
  145. ],
  146. aggregates: [
  147. 'equation|(count_if(transaction.duration,greater,300) / count()) * 100',
  148. 'equation|(count_if(transaction.duration,lessOrEquals,300) / count()) * 100',
  149. ],
  150. columns: [],
  151. orderby: '',
  152. },
  153. ],
  154. },
  155. ];
  156. const errorsWidgets = [
  157. {
  158. id: 'issue-for-review',
  159. title: t('Issues For Review'),
  160. description: t('Most recently seen unresolved issues for review.'),
  161. displayType: DisplayType.TABLE,
  162. widgetType: WidgetType.ISSUE,
  163. interval: '5m',
  164. queries: [
  165. {
  166. name: '',
  167. conditions: 'is:unresolved is:for_review',
  168. fields: ['issue', 'assignee', 'events', 'title'],
  169. aggregates: [],
  170. columns: ['issue', 'assignee', 'events', 'title'],
  171. orderby: 'date',
  172. },
  173. ],
  174. },
  175. {
  176. id: 'top-unhandled',
  177. title: t('Top Unhandled Error Types'),
  178. description: t('Most frequently encountered unhandled errors.'),
  179. displayType: DisplayType.TOP_N,
  180. widgetType: WidgetType.DISCOVER,
  181. interval: '5m',
  182. queries: [
  183. {
  184. name: '',
  185. conditions: 'error.unhandled:true',
  186. fields: ['error.type', 'count()'],
  187. aggregates: ['count()'],
  188. columns: ['error.type'],
  189. orderby: '-count()',
  190. },
  191. ],
  192. },
  193. {
  194. id: 'users-affected',
  195. title: t('Users Affected by Errors'),
  196. description: t('Footprint of unique users affected by errors.'),
  197. displayType: DisplayType.LINE,
  198. widgetType: WidgetType.DISCOVER,
  199. interval: '5m',
  200. queries: [
  201. {
  202. name: '',
  203. conditions: 'event.type:error',
  204. fields: ['count_unique(user)', 'count()'],
  205. aggregates: ['count_unique(user)', 'count()'],
  206. columns: [],
  207. orderby: '',
  208. },
  209. ],
  210. },
  211. ];
  212. return isSelfHostedErrorsOnly
  213. ? errorsWidgets
  214. : [...transactionsWidgets, ...errorsWidgets];
  215. };
  216. export function getTopNConvertedDefaultWidgets(): Readonly<Array<WidgetTemplate>> {
  217. return getDefaultWidgets().map(widget => {
  218. if (widget.displayType === DisplayType.TOP_N) {
  219. return {
  220. ...widget,
  221. displayType: DisplayType.AREA,
  222. limit: TOP_N,
  223. };
  224. }
  225. return widget;
  226. });
  227. }