profilesTable.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import Pagination from 'sentry/components/pagination';
  4. import {ProfileEventsTable} from 'sentry/components/profiling/profileEventsTable';
  5. import {t} from 'sentry/locale';
  6. import {space} from 'sentry/styles/space';
  7. import {useProfileEvents} from 'sentry/utils/profiling/hooks/useProfileEvents';
  8. import {formatSort} from 'sentry/utils/profiling/hooks/utils';
  9. import {decodeScalar} from 'sentry/utils/queryString';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. const FIELDS = [
  12. 'profile.id',
  13. 'trace',
  14. 'trace.transaction',
  15. 'profile.duration',
  16. 'timestamp',
  17. 'release',
  18. 'environment',
  19. 'os.name',
  20. 'os.version',
  21. ] as const;
  22. type FieldType = (typeof FIELDS)[number];
  23. export function ProfilesTable() {
  24. const location = useLocation();
  25. const sort = useMemo(() => {
  26. return formatSort<FieldType>(decodeScalar(location.query.sort), FIELDS, {
  27. key: 'timestamp',
  28. order: 'desc',
  29. });
  30. }, [location.query.sort]);
  31. const query = useMemo(() => {
  32. return decodeScalar(location.query.query, '');
  33. }, [location.query.query]);
  34. const profilesCursor = useMemo(
  35. () => decodeScalar(location.query.cursor),
  36. [location.query.cursor]
  37. );
  38. const profiles = useProfileEvents<FieldType>({
  39. cursor: profilesCursor,
  40. fields: FIELDS,
  41. query,
  42. sort,
  43. limit: 20,
  44. referrer: 'api.profiling.profile-summary-table',
  45. });
  46. const eventsTableProps = useMemo(() => {
  47. return {columns: FIELDS.slice(), sortableColumns: new Set(FIELDS)};
  48. }, []);
  49. return (
  50. <ProfileEvents>
  51. <ProfileEventsTableContainer>
  52. <ProfileEventsTable
  53. sort={sort}
  54. data={profiles.status === 'success' ? profiles.data : null}
  55. error={profiles.status === 'error' ? t('Unable to load profiles') : null}
  56. isLoading={profiles.status === 'loading'}
  57. {...eventsTableProps}
  58. />
  59. </ProfileEventsTableContainer>
  60. <StyledPagination pageLinks={profiles.getResponseHeader?.('Link')} />
  61. </ProfileEvents>
  62. );
  63. }
  64. const ProfileEvents = styled('div')``;
  65. const StyledPagination = styled(Pagination)`
  66. margin-top: ${space(1)};
  67. margin-right: ${space(1)};
  68. margin-bottom: ${space(2)};
  69. `;
  70. const ProfileEventsTableContainer = styled('div')`
  71. th,
  72. tr {
  73. border-radius: 0 !important;
  74. }
  75. > div {
  76. border-radius: 0;
  77. border-top: none;
  78. margin-bottom: 0;
  79. }
  80. `;