landingWidgetSelector.tsx 4.8 KB

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