useReleases.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import chunk from 'lodash/chunk';
  2. import {NewQuery, Release} from 'sentry/types';
  3. import {TableData} from 'sentry/utils/discover/discoverQuery';
  4. import EventView from 'sentry/utils/discover/eventView';
  5. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  6. import {ApiQueryKey, useApiQuery, useQueries} from 'sentry/utils/queryClient';
  7. import {decodeScalar} from 'sentry/utils/queryString';
  8. import {escapeFilterValue} from 'sentry/utils/tokenizeSearch';
  9. import useApi from 'sentry/utils/useApi';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import usePageFilters from 'sentry/utils/usePageFilters';
  13. export function useReleases(searchTerm?: string) {
  14. const organization = useOrganization();
  15. const location = useLocation();
  16. const {selection, isReady} = usePageFilters();
  17. const {environments, projects} = selection;
  18. const api = useApi();
  19. const releaseResults = useApiQuery<Release[]>(
  20. [
  21. `/organizations/${organization.slug}/releases/`,
  22. {
  23. query: {
  24. project: projects,
  25. per_page: 50,
  26. environment: environments,
  27. query: searchTerm,
  28. sort: 'date',
  29. },
  30. },
  31. ],
  32. {staleTime: Infinity, enabled: isReady}
  33. );
  34. const chunks =
  35. releaseResults.data && releaseResults.data.length
  36. ? chunk(releaseResults.data, 10)
  37. : [];
  38. const releaseMetrics = useQueries({
  39. queries: chunks.map(releases => {
  40. const newQuery: NewQuery = {
  41. name: '',
  42. fields: ['release', 'count()'],
  43. query: `transaction.op:ui.load ${escapeFilterValue(
  44. `release:[${releases.map(r => `"${r.version}"`).join()}]`
  45. )}`,
  46. dataset: DiscoverDatasets.METRICS,
  47. version: 2,
  48. projects: selection.projects,
  49. };
  50. const eventView = EventView.fromNewQueryWithPageFilters(newQuery, selection);
  51. const queryKey = [
  52. `/organizations/${organization.slug}/events/`,
  53. {
  54. query: {
  55. ...eventView.getEventsAPIPayload(location),
  56. referrer: 'api.starfish.mobile-release-selector',
  57. },
  58. },
  59. ] as ApiQueryKey;
  60. return {
  61. queryKey,
  62. queryFn: () =>
  63. api.requestPromise(queryKey[0], {
  64. method: 'GET',
  65. query: queryKey[1]?.query,
  66. }) as Promise<TableData>,
  67. ...{staleTime: Infinity, enabled: isReady && !releaseResults.isLoading},
  68. };
  69. }),
  70. });
  71. const metricsFetched = releaseMetrics.every(result => result.isFetched);
  72. const metricsStats: {[version: string]: {count: number}} = {};
  73. if (metricsFetched) {
  74. releaseMetrics.forEach(
  75. c =>
  76. c.data?.data?.forEach(release => {
  77. metricsStats[release.release] = {count: release['count()'] as number};
  78. })
  79. );
  80. }
  81. const releaseStats: {
  82. dateCreated: string;
  83. version: string;
  84. count?: number;
  85. }[] =
  86. releaseResults.data && releaseResults.data.length && metricsFetched
  87. ? releaseResults.data.flatMap(release => {
  88. const releaseVersion = release.version;
  89. const dateCreated = release.dateCreated;
  90. if (metricsStats[releaseVersion]?.count) {
  91. return {
  92. dateCreated,
  93. version: releaseVersion,
  94. count: metricsStats[releaseVersion]?.count,
  95. };
  96. }
  97. return [];
  98. })
  99. : [];
  100. return {
  101. ...releaseResults,
  102. data: releaseStats,
  103. isLoading: !metricsFetched || releaseResults.isLoading,
  104. };
  105. }
  106. export function useReleaseSelection(): {
  107. isLoading: boolean;
  108. primaryRelease: string | undefined;
  109. secondaryRelease: string | undefined;
  110. } {
  111. const location = useLocation();
  112. const {data: releases, isLoading} = useReleases();
  113. const primaryRelease =
  114. decodeScalar(location.query.primaryRelease) ?? releases?.[0]?.version ?? undefined;
  115. const secondaryRelease =
  116. decodeScalar(location.query.secondaryRelease) ??
  117. (releases && releases.length > 1 ? releases?.[1]?.version : undefined);
  118. return {primaryRelease, secondaryRelease, isLoading};
  119. }