useProjectRawWebVitalsValuesTimeseriesQuery.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import {getInterval} from 'sentry/components/charts/utils';
  2. import type {PageFilters} from 'sentry/types/core';
  3. import type {SeriesDataUnit} from 'sentry/types/echarts';
  4. import type {MetaType} from 'sentry/utils/discover/eventView';
  5. import EventView from 'sentry/utils/discover/eventView';
  6. import type {DiscoverQueryProps} from 'sentry/utils/discover/genericDiscoverQuery';
  7. import {useGenericDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
  8. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  9. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import usePageFilters from 'sentry/utils/usePageFilters';
  13. import {DEFAULT_QUERY_FILTER} from 'sentry/views/insights/browser/webVitals/settings';
  14. import type {BrowserType} from 'sentry/views/insights/browser/webVitals/utils/queryParameterDecoders/browserType';
  15. import {SpanIndexedField, type SubregionCode} from 'sentry/views/insights/types';
  16. type Props = {
  17. browserTypes?: BrowserType[];
  18. datetime?: PageFilters['datetime'];
  19. subregions?: SubregionCode[];
  20. transaction?: string | null;
  21. };
  22. export const useProjectRawWebVitalsValuesTimeseriesQuery = ({
  23. transaction,
  24. datetime,
  25. browserTypes,
  26. subregions,
  27. }: Props) => {
  28. const pageFilters = usePageFilters();
  29. const location = useLocation();
  30. const organization = useOrganization();
  31. const search = new MutableSearch([]);
  32. if (transaction) {
  33. search.addFilterValue('transaction', transaction);
  34. }
  35. if (browserTypes) {
  36. search.addDisjunctionFilterValues(SpanIndexedField.BROWSER_NAME, browserTypes);
  37. }
  38. if (subregions) {
  39. search.addDisjunctionFilterValues(SpanIndexedField.USER_GEO_SUBREGION, subregions);
  40. }
  41. const projectTimeSeriesEventView = EventView.fromNewQueryWithPageFilters(
  42. {
  43. yAxis: [
  44. 'p75(measurements.lcp)',
  45. 'p75(measurements.fcp)',
  46. 'p75(measurements.cls)',
  47. 'p75(measurements.ttfb)',
  48. 'p75(measurements.inp)',
  49. 'count()',
  50. 'count_scores(measurements.score.inp)',
  51. ],
  52. name: 'Web Vitals',
  53. query: [DEFAULT_QUERY_FILTER, search.formatString()].join(' ').trim(),
  54. version: 2,
  55. fields: [],
  56. interval: getInterval(pageFilters.selection.datetime, 'low'),
  57. dataset: DiscoverDatasets.METRICS,
  58. },
  59. {
  60. ...pageFilters.selection,
  61. datetime: datetime ?? pageFilters.selection.datetime,
  62. }
  63. );
  64. const result = useGenericDiscoverQuery<
  65. {
  66. data: any[];
  67. meta: MetaType;
  68. },
  69. DiscoverQueryProps
  70. >({
  71. route: 'events-stats',
  72. eventView: projectTimeSeriesEventView,
  73. location,
  74. orgSlug: organization.slug,
  75. getRequestPayload: () => ({
  76. ...projectTimeSeriesEventView.getEventsAPIPayload(location),
  77. yAxis: projectTimeSeriesEventView.yAxis,
  78. topEvents: projectTimeSeriesEventView.topEvents,
  79. excludeOther: 0,
  80. partial: 1,
  81. orderby: undefined,
  82. interval: projectTimeSeriesEventView.interval,
  83. }),
  84. options: {
  85. refetchOnWindowFocus: false,
  86. },
  87. referrer: 'api.performance.browser.web-vitals.timeseries',
  88. });
  89. const data: {
  90. cls: SeriesDataUnit[];
  91. count: SeriesDataUnit[];
  92. countInp: SeriesDataUnit[];
  93. fcp: SeriesDataUnit[];
  94. inp: SeriesDataUnit[];
  95. lcp: SeriesDataUnit[];
  96. ttfb: SeriesDataUnit[];
  97. } = {
  98. lcp: [],
  99. fcp: [],
  100. cls: [],
  101. ttfb: [],
  102. inp: [],
  103. count: [],
  104. countInp: [],
  105. };
  106. result?.data?.['p75(measurements.lcp)']?.data.forEach((interval, index) => {
  107. const map: {key: string; series: SeriesDataUnit[]}[] = [
  108. {key: 'p75(measurements.cls)', series: data.cls},
  109. {key: 'p75(measurements.lcp)', series: data.lcp},
  110. {key: 'p75(measurements.fcp)', series: data.fcp},
  111. {key: 'p75(measurements.ttfb)', series: data.ttfb},
  112. {key: 'p75(measurements.inp)', series: data.inp},
  113. {key: 'count()', series: data.count},
  114. {key: 'count_scores(measurements.score.inp)', series: data.countInp},
  115. ];
  116. map.forEach(({key, series}) => {
  117. if (result?.data?.[key].data[index][1][0].count !== null) {
  118. series.push({
  119. value: result?.data?.[key].data[index][1][0].count,
  120. name: interval[0] * 1000,
  121. });
  122. }
  123. });
  124. });
  125. return {data, isLoading: result.isPending};
  126. };