useInpSpanSamplesWebVitalsQuery.tsx 2.8 KB

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