useInpSpanSamplesWebVitalsQuery.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 {useSpansIndexed} from 'sentry/views/starfish/queries/useDiscover';
  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} = useSpansIndexed(
  30. {
  31. search: MutableSearch.fromQueryObject({
  32. 'span.op': 'ui.interaction.click',
  33. 'measurements.score.weight.inp': '>0',
  34. ...(transaction !== undefined
  35. ? {[SpanIndexedField.ORIGIN_TRANSACTION]: transaction}
  36. : {}),
  37. ...filters,
  38. }),
  39. sorts: [sort],
  40. fields: [
  41. SpanIndexedField.INP,
  42. SpanIndexedField.INP_SCORE,
  43. SpanIndexedField.INP_SCORE_WEIGHT,
  44. SpanIndexedField.TOTAL_SCORE,
  45. SpanIndexedField.ID,
  46. SpanIndexedField.TIMESTAMP,
  47. SpanIndexedField.PROFILE_ID,
  48. SpanIndexedField.REPLAY_ID,
  49. SpanIndexedField.USER,
  50. SpanIndexedField.ORIGIN_TRANSACTION,
  51. SpanIndexedField.PROJECT,
  52. SpanIndexedField.BROWSER_NAME,
  53. SpanIndexedField.SPAN_SELF_TIME,
  54. SpanIndexedField.SPAN_DESCRIPTION,
  55. ],
  56. enabled,
  57. limit,
  58. },
  59. 'api.performance.browser.web-vitals.spans'
  60. );
  61. const tableData: InteractionSpanSampleRowWithScore[] =
  62. !isLoading && data?.length
  63. ? data.map(row => {
  64. return {
  65. ...row,
  66. 'measurements.inp': row[SpanIndexedField.INP],
  67. 'user.display': row[SpanIndexedField.USER],
  68. replayId: row[SpanIndexedField.REPLAY_ID],
  69. 'profile.id': row[SpanIndexedField.PROFILE_ID],
  70. inpScore: Math.round(
  71. ((row[`measurements.score.inp`] ?? 0) /
  72. (row[`measurements.score.weight.inp`] ?? 0)) *
  73. 100
  74. ),
  75. totalScore: Math.round(row[`measurements.score.total`] ?? 0),
  76. projectSlug: row[SpanIndexedField.PROJECT],
  77. };
  78. })
  79. : [];
  80. return {
  81. data: tableData,
  82. isLoading,
  83. ...rest,
  84. };
  85. }