slowestProfileFunctions.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import {useCallback, useMemo, useState} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import Pagination from 'sentry/components/pagination';
  4. import {useProfileFunctions} from 'sentry/utils/profiling/hooks/useProfileFunctions';
  5. import {formatSort} from 'sentry/utils/profiling/hooks/utils';
  6. import {decodeScalar} from 'sentry/utils/queryString';
  7. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. const FUNCTIONS_CURSOR_NAME = 'functionsCursor';
  10. const functionsFields = [
  11. 'package',
  12. 'function',
  13. 'count()',
  14. 'p75()',
  15. 'sum()',
  16. 'examples()',
  17. ] as const;
  18. type FunctionsField = (typeof functionsFields)[number];
  19. interface SlowestProfileFunctionsProps {
  20. transaction: string;
  21. }
  22. export function SlowestProfileFunctions(props: SlowestProfileFunctionsProps) {
  23. const [functionType, setFunctionType] = useState<'application' | 'system' | 'all'>(
  24. 'application'
  25. );
  26. const location = useLocation();
  27. const functionsCursor = useMemo(
  28. () => decodeScalar(location.query[FUNCTIONS_CURSOR_NAME]),
  29. [location.query]
  30. );
  31. const functionsSort = useMemo(
  32. () =>
  33. formatSort<FunctionsField>(
  34. decodeScalar(location.query.functionsSort),
  35. functionsFields,
  36. {
  37. key: 'sum()',
  38. order: 'desc',
  39. }
  40. ),
  41. [location.query.functionsSort]
  42. );
  43. const handleFunctionsCursor = useCallback((cursor, pathname, query) => {
  44. browserHistory.push({
  45. pathname,
  46. query: {...query, [FUNCTIONS_CURSOR_NAME]: cursor},
  47. });
  48. }, []);
  49. const query = useMemo(() => {
  50. const conditions = new MutableSearch('');
  51. conditions.setFilterValues('transaction', [props.transaction]);
  52. if (functionType === 'application') {
  53. conditions.setFilterValues('is_application', ['1']);
  54. } else if (functionType === 'system') {
  55. conditions.setFilterValues('is_application', ['0']);
  56. }
  57. return conditions.formatString();
  58. }, [functionType, props.transaction]);
  59. const functionsQuery = useProfileFunctions<FunctionsField>({
  60. fields: functionsFields,
  61. referrer: 'api.profiling.profile-summary-functions-table',
  62. sort: functionsSort,
  63. query,
  64. limit: 5,
  65. cursor: functionsCursor,
  66. });
  67. return (
  68. <div>
  69. <button onClick={() => setFunctionType('all')}>Type</button>
  70. <Pagination
  71. pageLinks={functionsQuery.getResponseHeader?.('Link')}
  72. onCursor={handleFunctionsCursor}
  73. size="xs"
  74. />
  75. <div>{functionsQuery.isLoading && 'Loading...'}</div>
  76. <div>{functionsQuery.error && 'Error'}</div>
  77. <div>
  78. {functionsQuery.data?.data?.map((fn, i) => (
  79. <div key={i}>
  80. {fn.function} {fn['sum()']}
  81. </div>
  82. ))}
  83. </div>
  84. </div>
  85. );
  86. }