useTransactionSamplesWebVitalsQuery.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import {ReactText} from 'react';
  2. import {useDiscoverQuery} from 'sentry/utils/discover/discoverQuery';
  3. import EventView from 'sentry/utils/discover/eventView';
  4. import {useLocation} from 'sentry/utils/useLocation';
  5. import useOrganization from 'sentry/utils/useOrganization';
  6. import usePageFilters from 'sentry/utils/usePageFilters';
  7. import {calculatePerformanceScore} from 'sentry/views/performance/browser/webVitals/utils/calculatePerformanceScore';
  8. import {mapWebVitalToOrderBy} from 'sentry/views/performance/browser/webVitals/utils/mapWebVitalToOrderBy';
  9. import {
  10. TransactionSampleRowWithScore,
  11. WebVitals,
  12. } from 'sentry/views/performance/browser/webVitals/utils/types';
  13. type Props = {
  14. transaction: string;
  15. limit?: number;
  16. orderBy?: WebVitals | null;
  17. query?: string;
  18. };
  19. export const useTransactionSamplesWebVitalsQuery = ({
  20. orderBy,
  21. limit,
  22. transaction,
  23. query,
  24. }: Props) => {
  25. const organization = useOrganization();
  26. const pageFilters = usePageFilters();
  27. const location = useLocation();
  28. const eventView = EventView.fromNewQueryWithPageFilters(
  29. {
  30. fields: [
  31. 'id',
  32. 'user.display',
  33. 'transaction',
  34. 'transaction.op',
  35. 'measurements.lcp',
  36. 'measurements.fcp',
  37. 'measurements.cls',
  38. 'measurements.ttfb',
  39. 'measurements.fid',
  40. 'transaction.duration',
  41. 'replayId',
  42. 'timestamp',
  43. ],
  44. name: 'Web Vitals',
  45. query: `transaction.op:pageload transaction:"${transaction}" ${query ? query : ''}`,
  46. orderby: mapWebVitalToOrderBy(orderBy),
  47. version: 2,
  48. },
  49. pageFilters.selection
  50. );
  51. const {data, isLoading, ...rest} = useDiscoverQuery({
  52. eventView,
  53. limit: limit ?? 50,
  54. location,
  55. orgSlug: organization.slug,
  56. options: {
  57. enabled: pageFilters.isReady,
  58. refetchOnWindowFocus: false,
  59. },
  60. });
  61. const toInt = (item: ReactText) => (item ? parseInt(item.toString(), 10) : null);
  62. const tableData: TransactionSampleRowWithScore[] =
  63. !isLoading && data?.data.length
  64. ? data.data
  65. .map(row => ({
  66. id: row.id?.toString(),
  67. 'user.display': row['user.display']?.toString(),
  68. transaction: row.transaction?.toString(),
  69. 'transaction.op': row['transaction.op']?.toString(),
  70. 'measurements.lcp': toInt(row['measurements.lcp']),
  71. 'measurements.fcp': toInt(row['measurements.fcp']),
  72. 'measurements.cls': toInt(row['measurements.cls']),
  73. 'measurements.ttfb': toInt(row['measurements.ttfb']),
  74. 'measurements.fid': toInt(row['measurements.fid']),
  75. 'transaction.duration': toInt(row['transaction.duration']),
  76. replayId: row.replayId?.toString(),
  77. timestamp: row.timestamp?.toString(),
  78. }))
  79. .map(row => {
  80. const {totalScore, clsScore, fcpScore, lcpScore, ttfbScore, fidScore} =
  81. calculatePerformanceScore({
  82. lcp: row['measurements.lcp'],
  83. fcp: row['measurements.fcp'],
  84. cls: row['measurements.cls'],
  85. ttfb: row['measurements.ttfb'],
  86. fid: row['measurements.fid'],
  87. });
  88. return {
  89. ...row,
  90. score: totalScore,
  91. clsScore,
  92. fcpScore,
  93. lcpScore,
  94. ttfbScore,
  95. fidScore,
  96. };
  97. })
  98. : [];
  99. return {
  100. data: tableData,
  101. isLoading,
  102. ...rest,
  103. };
  104. };