Browse Source

feat(starfish): Fetch better releases in the selector (#60563)

The release selector is currently an intersection of results from the
release endpoint and events endpoint.
This PR switches it to consecutive http requests, so that we fetch the
top 50 releases and pass those
as filters to the events requests to ensure we get numbers for those
releases. This is way better in
cases of large time periods or a large number of releases.
Shruthi 1 year ago
parent
commit
172efea3f3

+ 58 - 21
static/app/views/starfish/queries/useReleases.tsx

@@ -1,17 +1,23 @@
+import chunk from 'lodash/chunk';
+
 import {NewQuery, Release} from 'sentry/types';
+import {TableData} from 'sentry/utils/discover/discoverQuery';
 import EventView from 'sentry/utils/discover/eventView';
 import {DiscoverDatasets} from 'sentry/utils/discover/types';
-import {useApiQuery} from 'sentry/utils/queryClient';
+import {ApiQueryKey, useApiQuery, useQueries} from 'sentry/utils/queryClient';
 import {decodeScalar} from 'sentry/utils/queryString';
+import {escapeFilterValue} from 'sentry/utils/tokenizeSearch';
+import useApi from 'sentry/utils/useApi';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import {useTableQuery} from 'sentry/views/starfish/views/screens/screensTable';
 
 export function useReleases(searchTerm?: string) {
   const organization = useOrganization();
+  const location = useLocation();
   const {selection, isReady} = usePageFilters();
   const {environments, projects} = selection;
+  const api = useApi();
 
   const releaseResults = useApiQuery<Release[]>(
     [
@@ -19,7 +25,7 @@ export function useReleases(searchTerm?: string) {
       {
         query: {
           project: projects,
-          per_page: 100,
+          per_page: 50,
           environment: environments,
           query: searchTerm,
           sort: 'date',
@@ -29,33 +35,63 @@ export function useReleases(searchTerm?: string) {
     {staleTime: Infinity, enabled: isReady}
   );
 
-  const newQuery: NewQuery = {
-    name: '',
-    fields: ['release', 'count()'],
-    query: `transaction.op:ui.load ${searchTerm ? `release:*${searchTerm}*` : ''}`,
-    dataset: DiscoverDatasets.METRICS,
-    version: 2,
-    projects: selection.projects,
-  };
-  const eventView = EventView.fromNewQueryWithPageFilters(newQuery, selection);
-  const {data: metricsResult, isLoading: isMetricsStatsLoading} = useTableQuery({
-    eventView,
-    limit: 100,
-    staleTime: Infinity,
-    referrer: 'api.starfish.mobile-release-selector',
+  const chunks =
+    releaseResults.data && releaseResults.data.length
+      ? chunk(releaseResults.data, 10)
+      : [];
+
+  const releaseMetrics = useQueries({
+    queries: chunks.map(releases => {
+      const newQuery: NewQuery = {
+        name: '',
+        fields: ['release', 'count()'],
+        query: `transaction.op:ui.load ${escapeFilterValue(
+          `release:[${releases.map(r => `"${r.version}"`).join()}]`
+        )}`,
+        dataset: DiscoverDatasets.METRICS,
+        version: 2,
+        projects: selection.projects,
+      };
+      const eventView = EventView.fromNewQueryWithPageFilters(newQuery, selection);
+      const queryKey = [
+        `/organizations/${organization.slug}/events/`,
+        {
+          query: {
+            ...eventView.getEventsAPIPayload(location),
+            referrer: 'api.starfish.mobile-release-selector',
+          },
+        },
+      ] as ApiQueryKey;
+      return {
+        queryKey,
+        queryFn: () =>
+          api.requestPromise(queryKey[0], {
+            method: 'GET',
+            query: queryKey[1]?.query,
+          }) as Promise<TableData>,
+        ...{staleTime: Infinity, enabled: isReady && !releaseResults.isLoading},
+      };
+    }),
   });
 
+  const metricsFetched = releaseMetrics.every(result => result.isFetched);
+
   const metricsStats: {[version: string]: {count: number}} = {};
-  metricsResult?.data?.forEach(release => {
-    metricsStats[release.release] = {count: release['count()'] as number};
-  });
+  if (metricsFetched) {
+    releaseMetrics.forEach(
+      c =>
+        c.data?.data?.forEach(release => {
+          metricsStats[release.release] = {count: release['count()'] as number};
+        })
+    );
+  }
 
   const releaseStats: {
     dateCreated: string;
     version: string;
     count?: number;
   }[] =
-    releaseResults.data && releaseResults.data.length && !isMetricsStatsLoading
+    releaseResults.data && releaseResults.data.length && metricsFetched
       ? releaseResults.data.flatMap(release => {
           const releaseVersion = release.version;
           const dateCreated = release.dateCreated;
@@ -73,6 +109,7 @@ export function useReleases(searchTerm?: string) {
   return {
     ...releaseResults,
     data: releaseStats,
+    isLoading: !metricsFetched || releaseResults.isLoading,
   };
 }
 

+ 1 - 1
static/app/views/starfish/views/screens/index.tsx

@@ -215,7 +215,7 @@ export function ScreensView({yAxes, additionalFilters, chartHeight}: Props) {
     return (
       <Alert type="warning" showIcon>
         {t(
-          'No screens found on recent releases. Please try a single iOS or Android project or a smaller date range.'
+          'No screens found on recent releases. Please try a single iOS or Android project, a single environment or a smaller date range.'
         )}
       </Alert>
     );