Browse Source

(all-events) fix duplicated events call in all events tab (#41224)

fixes PERF-1781

This solves two issues,
1) previously if a projectId was not in the URL, the api call for the
discover query would go out twice one with and one without the
projectId, this also causes an akward reload. Can be replicated by
having the project selector unlocked, with no projects selected, and
then navigating to any issue, then clicking on the all events tab.

2) If multiple projectIds were in the URL (for example if the user has
selected multiple in the /issues/ page), then multiple projects would be
sent to the discover query.

As projectId is a sort key in the transaction and errors dataset, having
the correct projectId leads to efficiency improvements too.

The PR also refactors projectId -> projectSlug, as looking back on this,
the variable was incorrectly named
Dominik Buszowiecki 2 years ago
parent
commit
f837f4b973

+ 5 - 5
static/app/utils/discover/fieldRenderers.tsx

@@ -73,7 +73,7 @@ export type RenderFunctionBaggage = {
   location: Location;
   organization: Organization;
   eventView?: EventView;
-  projectId?: string;
+  projectSlug?: string;
   unit?: string;
 };
 
@@ -342,7 +342,7 @@ const SPECIAL_FIELDS: SpecialFields = {
   // TODO - refactor code and remove from this file or add ability to query for attachments in Discover
   attachments: {
     sortField: null,
-    renderFunc: (data, {organization, projectId}) => {
+    renderFunc: (data, {organization, projectSlug}) => {
       const attachments: Array<IssueAttachment> = data.attachments;
 
       const items: MenuItemProps[] = attachments
@@ -352,7 +352,7 @@ const SPECIAL_FIELDS: SpecialFields = {
           label: attachment.name,
           onAction: () =>
             window.open(
-              `/api/0/projects/${organization.slug}/${projectId}/events/${attachment.event_id}/attachments/${attachment.id}/?download=1`
+              `/api/0/projects/${organization.slug}/${projectSlug}/events/${attachment.event_id}/attachments/${attachment.id}/?download=1`
             ),
         }));
 
@@ -378,7 +378,7 @@ const SPECIAL_FIELDS: SpecialFields = {
   },
   minidump: {
     sortField: null,
-    renderFunc: (data, {organization, projectId}) => {
+    renderFunc: (data, {organization, projectSlug}) => {
       const attachments: Array<IssueAttachment & {url: string}> = data.attachments;
 
       const minidump = attachments.find(
@@ -394,7 +394,7 @@ const SPECIAL_FIELDS: SpecialFields = {
               minidump
                 ? () => {
                     window.open(
-                      `/api/0/projects/${organization.slug}/${projectId}/events/${minidump.event_id}/attachments/${minidump.id}/?download=1`
+                      `/api/0/projects/${organization.slug}/${projectSlug}/events/${minidump.event_id}/attachments/${minidump.id}/?download=1`
                     );
                   }
                 : undefined

+ 5 - 1
static/app/views/organizationGroupDetails/allEventsTable.tsx

@@ -14,6 +14,7 @@ export interface Props {
   location: Location;
   organization: Organization;
   projectId: string;
+  projectSlug: string;
   excludedTags?: string[];
   totalEventCount?: string;
 }
@@ -25,6 +26,7 @@ const AllEventsTable = (props: Props) => {
     issueId,
     isPerfIssue,
     excludedTags,
+    projectSlug,
     projectId,
     totalEventCount,
   } = props;
@@ -32,6 +34,7 @@ const AllEventsTable = (props: Props) => {
   const routes = useRoutes();
 
   const isReplayEnabled = organization.features.includes('session-replay-ui');
+
   const fields: string[] = [
     'id',
     'transaction',
@@ -56,6 +59,7 @@ const AllEventsTable = (props: Props) => {
   const idQuery = isPerfIssue
     ? `performance.issue_ids:${issueId} event.type:transaction`
     : `issue.id:${issueId}`;
+  eventView.project = [parseInt(projectId, 10)];
   eventView.query = `${idQuery} ${props.location.query.query || ''}`;
   eventView.statsPeriod = '90d';
 
@@ -84,7 +88,7 @@ const AllEventsTable = (props: Props) => {
       organization={organization}
       routes={routes}
       excludedTags={excludedTags}
-      projectId={projectId}
+      projectSlug={projectSlug}
       totalEventCount={totalEventCount}
       customColumns={['minidump']}
       setError={(msg: string | undefined) => setError(msg ?? '')}

+ 25 - 0
static/app/views/organizationGroupDetails/groupEvents.spec.jsx

@@ -415,6 +415,31 @@ describe('groupEvents', function () {
       );
     });
 
+    it('only request for a single projectId', function () {
+      render(
+        <GroupEvents
+          organization={org.organization}
+          api={new MockApiClient()}
+          params={{orgId: 'orgId', projectId: 'projectId', groupId: '1'}}
+          group={group}
+          location={{
+            query: {
+              environment: ['prod', 'staging'],
+              sort: 'user',
+              project: [group.project.id, '456'],
+            },
+          }}
+        />,
+        {context: routerContext, organization}
+      );
+      expect(discoverRequest).toHaveBeenCalledWith(
+        '/organizations/org-slug/events/',
+        expect.objectContaining({
+          query: expect.objectContaining({project: [group.project.id]}),
+        })
+      );
+    });
+
     it('shows discover query error message', async () => {
       discoverRequest = MockApiClient.addMockResponse({
         url: '/organizations/org-slug/events/',

+ 2 - 1
static/app/views/organizationGroupDetails/groupEvents.tsx

@@ -145,7 +145,8 @@ class GroupEvents extends Component<Props, State> {
         isPerfIssue={this.props.group.issueCategory === IssueCategory.PERFORMANCE}
         location={this.props.location}
         organization={this.props.organization}
-        projectId={this.props.group.project.slug}
+        projectId={this.props.group.project.id}
+        projectSlug={this.props.group.project.slug}
         totalEventCount={this.props.group.count}
         excludedTags={excludedTags}
       />

+ 3 - 3
static/app/views/performance/transactionSummary/transactionEvents/eventsTable.tsx

@@ -89,7 +89,7 @@ type Props = {
   customColumns?: ('attachments' | 'minidump')[];
   excludedTags?: string[];
   issueId?: string;
-  projectId?: string;
+  projectSlug?: string;
   referrer?: string;
   showReplayCol?: boolean;
   totalEventCount?: string;
@@ -150,7 +150,7 @@ class EventsTable extends Component<Props, State> {
     column: TableColumn<keyof TableDataRow>,
     dataRow: TableDataRow
   ): React.ReactNode {
-    const {eventView, organization, location, transactionName, projectId} = this.props;
+    const {eventView, organization, location, transactionName, projectSlug} = this.props;
 
     if (!tableData || !tableData.meta) {
       return dataRow[column.key];
@@ -162,7 +162,7 @@ class EventsTable extends Component<Props, State> {
       organization,
       location,
       eventView,
-      projectId,
+      projectSlug,
     });
 
     const allowActions = [