Просмотр исходного кода

fix(replay): transaction replay tab should filter by proj (#79136)

- previously in the transaction tab, we didn't pass in the project ID
for our replay query, which resulted in replays from the wrong project
showing up in the tab.
- also, if no replays were related to the transaction, we were
accidentally returning ALL replays for that proj rather than no replays.
this was a bug introduced in
https://github.com/getsentry/sentry/pull/73407
- fixes https://github.com/getsentry/team-replay/issues/486

before: query for `project:-1` and empty query string, resulting in all
replays being returned.

<img width="509" alt="SCR-20241015-kpcy"
src="https://github.com/user-attachments/assets/dc4f01b3-5920-4c67-b1e8-d8057a1d5dec">

results in replays from a diff project:

<img width="848" alt="SCR-20241015-kmsi"
src="https://github.com/user-attachments/assets/50cc20a5-e445-4d35-860f-523bf9246047">
<img width="527" alt="SCR-20241015-kmyh"
src="https://github.com/user-attachments/assets/0336853e-8f68-438b-93f3-ebd7704a5c9b">


after: query for a specific project based on page filters:

<img width="537" alt="SCR-20241015-koil"
src="https://github.com/user-attachments/assets/91ea78fe-4ab3-4d9f-bd8d-9d4efc0a8e35">

<img width="753" alt="SCR-20241015-knco"
src="https://github.com/user-attachments/assets/9a87413a-2dd5-4991-b319-52c7c1132377">
<img width="882" alt="SCR-20241015-kodn"
src="https://github.com/user-attachments/assets/7d9f1c82-fa9c-4108-b749-f2e4e40287fa">
Michelle Zhang 4 месяцев назад
Родитель
Сommit
6294b28a5d

+ 14 - 3
static/app/utils/replays/fetchReplayList.tsx

@@ -3,6 +3,7 @@ import type {Location} from 'history';
 
 import type {Client} from 'sentry/api';
 import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
+import type {PageFilters} from 'sentry/types/core';
 import type {Organization} from 'sentry/types/organization';
 import type EventView from 'sentry/utils/discover/eventView';
 import {mapResponseToReplayRecord} from 'sentry/utils/replays/replayDataUtils';
@@ -24,6 +25,7 @@ type Props = {
   eventView: EventView;
   location: Location;
   organization: Organization;
+  selection: PageFilters;
   perPage?: number;
   queryReferrer?: ReplayListQueryReferrer;
 };
@@ -35,6 +37,7 @@ async function fetchReplayList({
   eventView,
   queryReferrer,
   perPage,
+  selection,
 }: Props): Promise<Result> {
   try {
     const path = `/organizations/${organization.slug}/replays/`;
@@ -60,9 +63,11 @@ async function fetchReplayList({
         // we also require a project param otherwise we won't yield results
         queryReferrer,
         project:
-          queryReferrer === 'issueReplays' || queryReferrer === 'transactionReplays'
+          queryReferrer === 'issueReplays'
             ? ALL_ACCESS_PROJECTS
-            : payload.project,
+            : queryReferrer === 'transactionReplays'
+              ? selection.projects
+              : payload.project,
       },
     });
 
@@ -71,7 +76,13 @@ async function fetchReplayList({
     return {
       fetchError: undefined,
       pageLinks,
-      replays: data.map(mapResponseToReplayRecord),
+      replays: payload.query ? data.map(mapResponseToReplayRecord) : [],
+      // for the replay tab in transactions, if payload.query is undefined,
+      // this means the transaction has no related replays.
+      // but because we cannot query for an empty list of IDs (e.g. `id:[]` breaks our search endpoint),
+      // and leaving query empty results in ALL replays being returned for a specified project
+      // (which doesn't make sense as we want to show no replays),
+      // we essentially want to hardcode no replays being returned.
     };
   } catch (error) {
     if (error.responseJSON?.detail) {

+ 4 - 1
static/app/utils/replays/hooks/useReplayList.tsx

@@ -5,6 +5,7 @@ import type {Organization} from 'sentry/types/organization';
 import type EventView from 'sentry/utils/discover/eventView';
 import fetchReplayList from 'sentry/utils/replays/fetchReplayList';
 import useApi from 'sentry/utils/useApi';
+import usePageFilters from 'sentry/utils/usePageFilters';
 import type {
   ReplayListLocationQuery,
   ReplayListQueryReferrer,
@@ -30,6 +31,7 @@ function useReplayList({
   perPage,
 }: Options): Result {
   const api = useApi();
+  const {selection} = usePageFilters();
 
   const [data, setData] = useState<State>({
     fetchError: undefined,
@@ -51,10 +53,11 @@ function useReplayList({
       eventView,
       queryReferrer,
       perPage,
+      selection,
     });
 
     setData({...response, isFetching: false});
-  }, [api, organization, location, eventView, queryReferrer, perPage]);
+  }, [api, organization, location, eventView, queryReferrer, perPage, selection]);
 
   useEffect(() => {
     loadReplays();

+ 4 - 3
static/app/views/performance/transactionSummary/transactionReplays/index.spec.tsx

@@ -47,11 +47,12 @@ const renderComponent = ({
       ],
       location: {
         pathname: '/organizations/org-slug/replays/',
+        ...location,
         query: {
           project: '1',
           transaction: 'Settings Page',
+          ...location?.query,
         },
-        ...location,
       },
     },
   });
@@ -216,7 +217,7 @@ describe('TransactionReplays', () => {
     // Mock the system date to be 2022-09-28
     setMockDate(new Date('Sep 28, 2022 11:29:13 PM UTC'));
 
-    renderComponent();
+    renderComponent({location: {query: {query: 'test'}}});
 
     await waitFor(() => {
       expect(mockApi).toHaveBeenCalledTimes(1);
@@ -226,7 +227,7 @@ describe('TransactionReplays', () => {
     expect(screen.getAllByText('testDisplayName')).toHaveLength(2);
 
     const expectedQuery =
-      'project=1&query=&referrer=%2Forganizations%2F%3AorgId%2Fperformance%2Fsummary%2Freplays%2F&statsPeriod=14d&yAxis=count%28%29';
+      'project=1&query=test&referrer=%2Forganizations%2F%3AorgId%2Fperformance%2Fsummary%2Freplays%2F&statsPeriod=14d&yAxis=count%28%29';
     // Expect the first row to have the correct href
     expect(screen.getAllByRole('link', {name: 'testDisplayName'})[0]).toHaveAttribute(
       'href',

+ 11 - 2
static/app/views/performance/transactionSummary/transactionReplays/transactionReplays.tsx

@@ -137,13 +137,22 @@ function ReplaysContent({
   organization: Organization;
   pageLinks: string | null;
 }) {
-  const location = useMemo(() => ({query: {}}) as Location<ReplayListLocationQuery>, []);
+  const location = useLocation();
+
+  if (!eventView.query) {
+    eventView.query = String(location.query.query ?? '');
+  }
+
+  const newLocation = useMemo(
+    () => ({query: {}}) as Location<ReplayListLocationQuery>,
+    []
+  );
   const theme = useTheme();
   const hasRoomForColumns = useMedia(`(min-width: ${theme.breakpoints.small})`);
 
   const {replays, isFetching, fetchError} = useReplayList({
     eventView,
-    location,
+    location: newLocation,
     organization,
     queryReferrer: 'transactionReplays',
   });