useInpSpanSamplesWebVitalsQuery.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  2. import {
  3. DEFAULT_INDEXED_INTERACTION_SORT,
  4. type InteractionSpanSampleRowWithScore,
  5. SORTABLE_INDEXED_INTERACTION_FIELDS,
  6. } from 'sentry/views/performance/browser/webVitals/utils/types';
  7. import {useWebVitalsSort} from 'sentry/views/performance/browser/webVitals/utils/useWebVitalsSort';
  8. import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
  9. import {SpanIndexedField} from 'sentry/views/starfish/types';
  10. export function useInpSpanSamplesWebVitalsQuery({
  11. transaction,
  12. limit,
  13. enabled,
  14. filters = {},
  15. sortName,
  16. }: {
  17. limit: number;
  18. enabled?: boolean;
  19. filters?: {[key: string]: string[] | string | number | undefined};
  20. sortName?: string;
  21. transaction?: string;
  22. }) {
  23. const filteredSortableFields = SORTABLE_INDEXED_INTERACTION_FIELDS;
  24. const sort = useWebVitalsSort({
  25. sortName,
  26. defaultSort: DEFAULT_INDEXED_INTERACTION_SORT,
  27. sortableFields: filteredSortableFields as unknown as string[],
  28. });
  29. const {data, isLoading, ...rest} = useIndexedSpans({
  30. search: MutableSearch.fromQueryObject({
  31. 'span.op': 'ui.interaction.click',
  32. 'measurements.score.weight.inp': '>0',
  33. ...(transaction !== undefined
  34. ? {[SpanIndexedField.ORIGIN_TRANSACTION]: transaction}
  35. : {}),
  36. ...filters,
  37. }),
  38. sorts: [sort],
  39. fields: [
  40. SpanIndexedField.INP,
  41. SpanIndexedField.INP_SCORE,
  42. SpanIndexedField.INP_SCORE_WEIGHT,
  43. SpanIndexedField.TOTAL_SCORE,
  44. SpanIndexedField.ID,
  45. SpanIndexedField.TIMESTAMP,
  46. SpanIndexedField.PROFILE_ID,
  47. SpanIndexedField.REPLAY_ID,
  48. SpanIndexedField.USER,
  49. SpanIndexedField.ORIGIN_TRANSACTION,
  50. SpanIndexedField.PROJECT,
  51. SpanIndexedField.BROWSER_NAME,
  52. SpanIndexedField.SPAN_SELF_TIME,
  53. SpanIndexedField.SPAN_DESCRIPTION,
  54. ],
  55. enabled,
  56. limit,
  57. referrer: 'api.performance.browser.web-vitals.spans',
  58. });
  59. const tableData: InteractionSpanSampleRowWithScore[] =
  60. !isLoading && data?.length
  61. ? data.map(row => {
  62. return {
  63. ...row,
  64. 'measurements.inp': row[SpanIndexedField.INP],
  65. 'user.display': row[SpanIndexedField.USER],
  66. replayId: row[SpanIndexedField.REPLAY_ID],
  67. 'profile.id': row[SpanIndexedField.PROFILE_ID],
  68. inpScore: Math.round(
  69. ((row[`measurements.score.inp`] ?? 0) /
  70. (row[`measurements.score.weight.inp`] ?? 0)) *
  71. 100
  72. ),
  73. totalScore: Math.round(row[`measurements.score.total`] ?? 0),
  74. projectSlug: row[SpanIndexedField.PROJECT],
  75. };
  76. })
  77. : [];
  78. return {
  79. data: tableData,
  80. isLoading,
  81. ...rest,
  82. };
  83. }