landingWidgetSelector.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import {useCallback, useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import omit from 'lodash/omit';
  4. import type {SelectOption} from 'sentry/components/compactSelect';
  5. import {CompactSelect} from 'sentry/components/compactSelect';
  6. import {t} from 'sentry/locale';
  7. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  8. import useRouter from 'sentry/utils/useRouter';
  9. import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
  10. import {FunctionTrendsWidget} from './functionTrendsWidget';
  11. import {SlowestFunctionsWidget} from './slowestFunctionsWidget';
  12. export type WidgetOption =
  13. | 'slowest functions avg'
  14. | 'slowest functions p50'
  15. | 'slowest functions' // kept for backwards compatibility as the p75
  16. | 'slowest functions p95'
  17. | 'slowest functions p99'
  18. | 'regressed functions'
  19. | 'improved functions';
  20. interface LandingWidgetSelectorProps {
  21. cursorName: string;
  22. defaultWidget: WidgetOption;
  23. storageKey: string;
  24. widgetHeight?: string;
  25. }
  26. export function LandingWidgetSelector({
  27. cursorName,
  28. defaultWidget,
  29. storageKey,
  30. widgetHeight,
  31. }: LandingWidgetSelectorProps) {
  32. const router = useRouter();
  33. const [selectedWidget, setSelectedWidget] = useSyncedLocalStorageState<WidgetOption>(
  34. storageKey,
  35. defaultWidget
  36. );
  37. const onWidgetChange = useCallback(
  38. (opt: any) => {
  39. const newQuery = omit(router.location.query, [cursorName]);
  40. router.push({
  41. pathname: router.location.pathname,
  42. query: newQuery,
  43. });
  44. setSelectedWidget(opt.value);
  45. },
  46. [cursorName, router, setSelectedWidget]
  47. );
  48. const functionQuery = useMemo(() => {
  49. const conditions = new MutableSearch('');
  50. conditions.setFilterValues('is_application', ['1']);
  51. return conditions.formatString();
  52. }, []);
  53. const header = (
  54. <StyledCompactSelect
  55. value={selectedWidget}
  56. options={WIDGET_OPTIONS}
  57. onChange={onWidgetChange}
  58. triggerProps={{borderless: true, size: 'zero'}}
  59. offset={4}
  60. />
  61. );
  62. switch (selectedWidget) {
  63. case 'regressed functions':
  64. return (
  65. <FunctionTrendsWidget
  66. cursorName={cursorName}
  67. header={header}
  68. trendFunction="p95()"
  69. trendType="regression"
  70. userQuery={functionQuery}
  71. widgetHeight={widgetHeight}
  72. />
  73. );
  74. case 'improved functions':
  75. return (
  76. <FunctionTrendsWidget
  77. cursorName={cursorName}
  78. header={header}
  79. trendFunction="p95()"
  80. trendType="improvement"
  81. userQuery={functionQuery}
  82. widgetHeight={widgetHeight}
  83. />
  84. );
  85. case 'slowest functions avg':
  86. return (
  87. <SlowestFunctionsWidget
  88. breakdownFunction="avg()"
  89. cursorName={cursorName}
  90. header={header}
  91. userQuery={functionQuery}
  92. widgetHeight={widgetHeight}
  93. />
  94. );
  95. case 'slowest functions p50':
  96. return (
  97. <SlowestFunctionsWidget
  98. breakdownFunction="p50()"
  99. cursorName={cursorName}
  100. header={header}
  101. userQuery={functionQuery}
  102. widgetHeight={widgetHeight}
  103. />
  104. );
  105. case 'slowest functions p95':
  106. return (
  107. <SlowestFunctionsWidget
  108. breakdownFunction="p95()"
  109. cursorName={cursorName}
  110. header={header}
  111. userQuery={functionQuery}
  112. widgetHeight={widgetHeight}
  113. />
  114. );
  115. case 'slowest functions p99':
  116. return (
  117. <SlowestFunctionsWidget
  118. breakdownFunction="p99()"
  119. cursorName={cursorName}
  120. header={header}
  121. userQuery={functionQuery}
  122. widgetHeight={widgetHeight}
  123. />
  124. );
  125. case 'slowest functions':
  126. default:
  127. return (
  128. <SlowestFunctionsWidget
  129. breakdownFunction="p75()"
  130. cursorName={cursorName}
  131. header={header}
  132. userQuery={functionQuery}
  133. widgetHeight={widgetHeight}
  134. />
  135. );
  136. }
  137. }
  138. const WIDGET_OPTIONS: Array<SelectOption<WidgetOption>> = [
  139. {
  140. label: t('Slowest Functions (breakdown by AVG)'),
  141. value: 'slowest functions avg' as const,
  142. },
  143. {
  144. label: t('Slowest Functions (breakdown by P50)'),
  145. value: 'slowest functions p50' as const,
  146. },
  147. {
  148. label: t('Slowest Functions (breakdown by P75)'),
  149. value: 'slowest functions' as const,
  150. },
  151. {
  152. label: t('Slowest Functions (breakdown by P95)'),
  153. value: 'slowest functions p95' as const,
  154. },
  155. {
  156. label: t('Slowest Functions (breakdown by P99)'),
  157. value: 'slowest functions p99' as const,
  158. },
  159. {
  160. label: t('Most Regressed Functions'),
  161. value: 'regressed functions' as const,
  162. },
  163. {
  164. label: t('Most Improved Functions'),
  165. value: 'improved functions' as const,
  166. },
  167. ];
  168. const StyledCompactSelect = styled(CompactSelect)`
  169. > button {
  170. border: None;
  171. padding: 0;
  172. }
  173. `;