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

chore(profiling): Remove unnecessary transaction profile id provider (#81393)

This was originally added because there was no way to map a transaction
to the profile. But with the addition of the profile context, this is no
longer an issue. So we can safely remove it and stop making 1 extra
query.
Tony Xiao 3 месяцев назад
Родитель
Сommit
0fcd485eec

+ 12 - 26
static/app/components/events/interfaces/spans/spanDetail.spec.tsx

@@ -6,7 +6,6 @@ import {SpanFixture} from 'sentry-fixture/span';
 import {render, screen} from 'sentry-test/reactTestingLibrary';
 
 import SpanDetail from 'sentry/components/events/interfaces/spans/spanDetail';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import type {EventTransaction} from 'sentry/types/event';
 
 describe('SpanDetail', function () {
@@ -36,33 +35,20 @@ describe('SpanDetail', function () {
     description: 'SELECT * FROM users;',
   });
 
-  beforeEach(function () {
-    MockApiClient.addMockResponse({
-      url: `/organizations/${organization.slug}/events/`,
-      method: 'GET',
-    });
-  });
-
   function renderSpanDetail(props: Partial<React.ComponentProps<typeof SpanDetail>>) {
     return (
-      <TransactionProfileIdProvider
-        projectId={project.id}
-        transactionId={event.id}
-        timestamp={event.dateReceived}
-      >
-        <SpanDetail
-          organization={organization}
-          event={event}
-          resetCellMeasureCache={jest.fn()}
-          scrollToHash={jest.fn()}
-          isRoot={false}
-          relatedErrors={[]}
-          trace={trace}
-          childTransactions={[]}
-          span={span}
-          {...props}
-        />
-      </TransactionProfileIdProvider>
+      <SpanDetail
+        organization={organization}
+        event={event}
+        resetCellMeasureCache={jest.fn()}
+        scrollToHash={jest.fn()}
+        isRoot={false}
+        relatedErrors={[]}
+        trace={trace}
+        childTransactions={[]}
+        span={span}
+        {...props}
+      />
     );
   }
 

+ 1 - 2
static/app/components/events/interfaces/spans/spanDetail.tsx

@@ -22,7 +22,6 @@ import {
 } from 'sentry/components/performance/waterfall/rowDetails';
 import Pill from 'sentry/components/pill';
 import Pills from 'sentry/components/pills';
-import {useTransactionProfileId} from 'sentry/components/profiling/transactionProfileIdProvider';
 import {TransactionToProfileButton} from 'sentry/components/profiling/transactionToProfileButton';
 import {
   generateIssueEventTarget,
@@ -106,7 +105,7 @@ type Props = {
 function SpanDetail(props: Props) {
   const [errorsOpened, setErrorsOpened] = useState(false);
   const location = useLocation();
-  const profileId = useTransactionProfileId();
+  const profileId = props.event.contexts.profile?.profile_id;
   const {projects} = useProjects();
   const project = projects.find(p => p.id === props.event.projectID);
 

+ 6 - 11
static/app/components/events/interfaces/spans/traceView.spec.tsx

@@ -16,7 +16,6 @@ import * as AnchorLinkManager from 'sentry/components/events/interfaces/spans/sp
 import TraceView from 'sentry/components/events/interfaces/spans/traceView';
 import {spanTargetHash} from 'sentry/components/events/interfaces/spans/utils';
 import WaterfallModel from 'sentry/components/events/interfaces/spans/waterfallModel';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import ProjectsStore from 'sentry/stores/projectsStore';
 import {QuickTraceContext} from 'sentry/utils/performance/quickTrace/quickTraceContext';
 import QuickTraceQuery from 'sentry/utils/performance/quickTrace/quickTraceQuery';
@@ -534,11 +533,9 @@ describe('TraceView', () => {
       const waterfallModel = new WaterfallModel(builder.getEventFixture());
 
       render(
-        <TransactionProfileIdProvider transactionId={undefined} timestamp={undefined}>
-          <AnchorLinkManager.Provider>
-            <TraceView organization={data.organization} waterfallModel={waterfallModel} />
-          </AnchorLinkManager.Provider>
-        </TransactionProfileIdProvider>
+        <AnchorLinkManager.Provider>
+          <TraceView organization={data.organization} waterfallModel={waterfallModel} />
+        </AnchorLinkManager.Provider>
       );
 
       expect(await screen.findByText(/0000000000000003/i)).toBeInTheDocument();
@@ -562,11 +559,9 @@ describe('TraceView', () => {
       const waterfallModel = new WaterfallModel(builder.getEventFixture());
 
       render(
-        <TransactionProfileIdProvider transactionId={undefined} timestamp={undefined}>
-          <AnchorLinkManager.Provider>
-            <TraceView organization={data.organization} waterfallModel={waterfallModel} />
-          </AnchorLinkManager.Provider>
-        </TransactionProfileIdProvider>
+        <AnchorLinkManager.Provider>
+          <TraceView organization={data.organization} waterfallModel={waterfallModel} />
+        </AnchorLinkManager.Provider>
       );
 
       expect(await screen.findByText(/0000000000000003/i)).toBeInTheDocument();

+ 0 - 83
static/app/components/profiling/transactionProfileIdProvider.tsx

@@ -1,83 +0,0 @@
-import {createContext, useContext, useEffect, useMemo} from 'react';
-import * as Sentry from '@sentry/react';
-
-import type {PageFilters} from 'sentry/types/core';
-import {useProfileEvents} from 'sentry/utils/profiling/hooks/useProfileEvents';
-
-const TransactionProfileContext = createContext<string | null | undefined>(undefined);
-
-interface TransactionToProfileIdProviderProps {
-  children: React.ReactNode;
-  timestamp: string | undefined;
-  transactionId: string | undefined;
-  projectId?: string | undefined;
-}
-
-export function TransactionProfileIdProvider({
-  projectId,
-  timestamp,
-  transactionId,
-  children,
-}: TransactionToProfileIdProviderProps) {
-  // create a 24h timeframe relative from the transaction timestamp to use for
-  // the profile events query
-  const datetime: PageFilters['datetime'] | undefined = useMemo(() => {
-    if (!timestamp) {
-      return undefined;
-    }
-    const ts = new Date(timestamp);
-    const start = new Date(new Date(ts).setHours(ts.getHours() - 12));
-    const end = new Date(new Date(ts).setHours(ts.getHours() + 12));
-
-    return {
-      start,
-      end,
-      period: null,
-      utc: true,
-    };
-  }, [timestamp]);
-
-  const transactionIdColumn = 'id';
-
-  const {status, data, error} = useProfileEvents({
-    projects: projectId ? [projectId] : undefined,
-    fields: ['profile.id'],
-    referrer: 'transactionToProfileProvider',
-    limit: 1,
-    sort: {
-      key: 'id',
-      order: 'asc',
-    },
-    query: `${transactionIdColumn}:${transactionId}`,
-    enabled: Boolean(transactionId),
-    datetime,
-  });
-
-  useEffect(() => {
-    if (status !== 'error') {
-      return;
-    }
-
-    if (error.status !== 404) {
-      Sentry.captureException(error);
-    }
-  }, [status, error]);
-
-  const profileId = (data?.data[0]?.['profile.id'] as string | undefined) ?? null;
-
-  return (
-    <TransactionProfileContext.Provider value={profileId}>
-      {children}
-    </TransactionProfileContext.Provider>
-  );
-}
-TransactionProfileIdProvider.Context = TransactionProfileContext;
-
-export function useTransactionProfileId() {
-  const ctx = useContext(TransactionProfileContext);
-  if (typeof ctx === 'undefined') {
-    throw new Error(`useTransactionProfile called outside of TransactionProfileProvider`);
-  }
-
-  return ctx;
-}

+ 0 - 106
static/app/components/profiling/transactonProfileIdProvider.spec.tsx

@@ -1,106 +0,0 @@
-import {render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
-
-import * as useProfileEventsModule from 'sentry/utils/profiling/hooks/useProfileEvents';
-import * as useApiModule from 'sentry/utils/useApi';
-
-import * as TransactionProfileIdProviderModule from './transactionProfileIdProvider';
-
-const useApiSpy = jest.spyOn(useApiModule, 'default');
-
-// this order matters; create the spy before dereferencing below
-const useTransactionProfileIdSpy = jest.spyOn(
-  TransactionProfileIdProviderModule,
-  'useTransactionProfileId'
-);
-
-const {TransactionProfileIdProvider, useTransactionProfileId} =
-  TransactionProfileIdProviderModule;
-
-const useProfileEventsSpy = jest.spyOn(useProfileEventsModule, 'useProfileEvents');
-
-function MockComponent() {
-  const profileId = useTransactionProfileId();
-  return <div data-test-id={profileId} />;
-}
-
-const MOCK_TRX_ID = '123';
-const MOCK_PROFILE_ID = '456';
-
-describe('TransactionProfileIdProvider', () => {
-  afterEach(() => {
-    jest.clearAllMocks();
-  });
-  it('provides default profileId state as null', () => {
-    render(
-      <TransactionProfileIdProvider transactionId={undefined} timestamp={undefined}>
-        <MockComponent />
-      </TransactionProfileIdProvider>
-    );
-
-    expect(useProfileEventsSpy).toHaveBeenCalledWith(
-      expect.objectContaining({
-        enabled: false,
-      })
-    );
-    expect(useTransactionProfileIdSpy).toHaveReturnedWith(null);
-  });
-
-  it('does not query the events endpoint when transactionId is undefined', () => {
-    const requestPromiseMock = jest.fn();
-    // @ts-expect-error
-    useApiSpy.mockReturnValueOnce({
-      requestPromise: requestPromiseMock,
-    });
-    render(
-      <TransactionProfileIdProvider transactionId={undefined} timestamp={undefined}>
-        <MockComponent />
-      </TransactionProfileIdProvider>
-    );
-
-    expect(useProfileEventsSpy).toHaveBeenCalledWith(
-      expect.objectContaining({
-        enabled: false,
-      })
-    );
-    expect(requestPromiseMock).not.toHaveBeenCalled();
-    expect(useTransactionProfileIdSpy).toHaveReturnedWith(null);
-  });
-
-  it('queries the events endpoint for a profile id when given a transactionId', async () => {
-    MockApiClient.addMockResponse({
-      method: 'GET',
-      url: '/organizations/org-slug/events/',
-      body: {
-        data: [
-          {
-            'profile.id': MOCK_PROFILE_ID,
-          },
-        ],
-      },
-    });
-
-    render(
-      <TransactionProfileIdProvider
-        transactionId={MOCK_TRX_ID}
-        timestamp="2022-12-19T16:00:00.000Z"
-      >
-        <MockComponent />
-      </TransactionProfileIdProvider>
-    );
-
-    await waitFor(() => screen.findAllByTestId(MOCK_PROFILE_ID));
-
-    expect(useProfileEventsSpy).toHaveBeenCalledWith(
-      expect.objectContaining({
-        query: 'id:' + MOCK_TRX_ID,
-        datetime: {
-          end: new Date('2022-12-20T04:00:00.000Z'),
-          period: null,
-          start: new Date('2022-12-19T04:00:00.000Z'),
-          utc: true,
-        },
-      })
-    );
-    expect(useTransactionProfileIdSpy).toHaveReturnedWith(MOCK_PROFILE_ID);
-  });
-});

+ 3 - 8
static/app/views/discover/eventDetails/content.tsx

@@ -1,4 +1,4 @@
-import {useState} from 'react';
+import {Fragment, useState} from 'react';
 import styled from '@emotion/styled';
 
 import Feature from 'sentry/components/acl/feature';
@@ -16,7 +16,6 @@ import FileSize from 'sentry/components/fileSize';
 import * as Layout from 'sentry/components/layouts/thirds';
 import LoadingError from 'sentry/components/loadingError';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import {TransactionToProfileButton} from 'sentry/components/profiling/transactionToProfileButton';
 import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import {TagsTable} from 'sentry/components/tagsTable';
@@ -133,11 +132,7 @@ function EventDetailsContent(props: Props) {
       metaResults?: TraceMetaQueryChildrenProps
     ) => {
       return (
-        <TransactionProfileIdProvider
-          projectId={event.projectID}
-          transactionId={event.type === 'transaction' ? event.id : undefined}
-          timestamp={event.dateReceived}
-        >
+        <Fragment>
           <Layout.Header>
             <Layout.HeaderContent>
               <DiscoverBreadcrumb
@@ -281,7 +276,7 @@ function EventDetailsContent(props: Props) {
               </Layout.Side>
             )}
           </Layout.Body>
-        </TransactionProfileIdProvider>
+        </Fragment>
       );
     };
 

+ 42 - 52
static/app/views/issueDetails/groupEventDetails/groupEventDetails.tsx

@@ -10,7 +10,6 @@ import {withMeta} from 'sentry/components/events/meta/metaProxy';
 import * as Layout from 'sentry/components/layouts/thirds';
 import LoadingError from 'sentry/components/loadingError';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import ResolutionBox from 'sentry/components/resolutionBox';
 import useSentryAppComponentsData from 'sentry/stores/useSentryAppComponentsData';
 import {space} from 'sentry/styles/space';
@@ -193,59 +192,50 @@ function GroupEventDetails() {
 
   return (
     <AnalyticsArea name="issue_details">
-      <TransactionProfileIdProvider
-        projectId={event?.projectID}
-        transactionId={event?.type === 'transaction' ? event.id : undefined}
-        timestamp={event?.dateReceived}
+      <VisuallyCompleteWithData
+        id="IssueDetails-EventBody"
+        hasData={!isLoadingEvent && !isEventError && defined(eventWithMeta)}
+        isLoading={isLoadingEvent}
       >
-        <VisuallyCompleteWithData
-          id="IssueDetails-EventBody"
-          hasData={!isLoadingEvent && !isEventError && defined(eventWithMeta)}
-          isLoading={isLoadingEvent}
-        >
-          <LayoutBody data-test-id="group-event-details">
-            {groupReprocessingStatus === ReprocessingStatus.REPROCESSING ? (
-              <ReprocessingProgress
-                totalEvents={
-                  (getGroupMostRecentActivity(group.activity) as GroupActivityReprocess)
-                    .data.eventCount
-                }
-                pendingEvents={
-                  (group.statusDetails as GroupReprocessing['statusDetails'])
-                    .pendingEvents
-                }
-              />
-            ) : (
-              <Fragment>
-                <MainLayoutComponent>
-                  {!hasStreamlinedUI && renderGroupStatusBanner()}
-                  {eventWithMeta &&
-                    issueTypeConfig.stats.enabled &&
-                    !hasStreamlinedUI && (
-                      <GroupEventHeader
-                        group={group}
-                        event={eventWithMeta}
-                        project={project}
-                      />
-                    )}
-                  {renderContent()}
-                </MainLayoutComponent>
-                {hasStreamlinedUI ? null : (
-                  <StyledLayoutSide hasStreamlinedUi={hasStreamlinedUI}>
-                    <GroupSidebar
-                      organization={organization}
-                      project={project}
-                      group={group}
-                      event={eventWithMeta}
-                      environments={environments}
-                    />
-                  </StyledLayoutSide>
+        <LayoutBody data-test-id="group-event-details">
+          {groupReprocessingStatus === ReprocessingStatus.REPROCESSING ? (
+            <ReprocessingProgress
+              totalEvents={
+                (getGroupMostRecentActivity(group.activity) as GroupActivityReprocess)
+                  .data.eventCount
+              }
+              pendingEvents={
+                (group.statusDetails as GroupReprocessing['statusDetails']).pendingEvents
+              }
+            />
+          ) : (
+            <Fragment>
+              <MainLayoutComponent>
+                {!hasStreamlinedUI && renderGroupStatusBanner()}
+                {eventWithMeta && issueTypeConfig.stats.enabled && !hasStreamlinedUI && (
+                  <GroupEventHeader
+                    group={group}
+                    event={eventWithMeta}
+                    project={project}
+                  />
                 )}
-              </Fragment>
-            )}
-          </LayoutBody>
-        </VisuallyCompleteWithData>
-      </TransactionProfileIdProvider>
+                {renderContent()}
+              </MainLayoutComponent>
+              {hasStreamlinedUI ? null : (
+                <StyledLayoutSide hasStreamlinedUi={hasStreamlinedUI}>
+                  <GroupSidebar
+                    organization={organization}
+                    project={project}
+                    group={group}
+                    event={eventWithMeta}
+                    environments={environments}
+                  />
+                </StyledLayoutSide>
+              )}
+            </Fragment>
+          )}
+        </LayoutBody>
+      </VisuallyCompleteWithData>
     </AnalyticsArea>
   );
 }

+ 38 - 47
static/app/views/performance/traceDetails/newTraceDetailsTransactionBar.tsx

@@ -56,7 +56,6 @@ import {
   getDurationDisplay,
   getHumanDuration,
 } from 'sentry/components/performance/waterfall/utils';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import {generateIssueEventTarget} from 'sentry/components/quickTrace/utils';
 import {Tooltip} from 'sentry/components/tooltip';
 import {IconZoom} from 'sentry/icons/iconZoom';
@@ -495,52 +494,44 @@ function NewTraceDetailsTransactionBar(props: Props) {
                     input={profiles?.type === 'resolved' ? profiles.data : null}
                     traceID={profileId || ''}
                   >
-                    <TransactionProfileIdProvider
-                      projectId={embeddedChildren.projectID}
-                      timestamp={embeddedChildren.dateReceived}
-                      transactionId={embeddedChildren.id}
-                    >
-                      <SpanContext.Provider>
-                        <SpanContext.Consumer>
-                          {spanContextProps => (
-                            <Observer>
-                              {() => (
-                                <NewTraceDetailsSpanTree
-                                  measurements={props.measurements}
-                                  quickTrace={results}
-                                  location={props.location}
-                                  onRowClick={props.onRowClick}
-                                  traceInfo={traceInfo}
-                                  traceViewHeaderRef={traceViewRef}
-                                  traceViewRef={traceViewRef}
-                                  parentContinuingDepths={props.continuingDepths}
-                                  traceHasMultipleRoots={props.continuingDepths.some(
-                                    c => c.depth === 0 && c.isOrphanDepth
-                                  )}
-                                  parentIsOrphan={props.isOrphan}
-                                  parentIsLast={isLast}
-                                  parentGeneration={transaction.generation ?? 0}
-                                  organization={organization}
-                                  waterfallModel={waterfallModel}
-                                  filterSpans={waterfallModel.filterSpans}
-                                  spans={waterfallModel
-                                    .getWaterfall({
-                                      viewStart: 0,
-                                      viewEnd: 1,
-                                    })
-                                    .slice(1)}
-                                  focusedSpanIds={waterfallModel.focusedSpanIds}
-                                  spanContextProps={spanContextProps}
-                                  operationNameFilters={
-                                    waterfallModel.operationNameFilters
-                                  }
-                                />
-                              )}
-                            </Observer>
-                          )}
-                        </SpanContext.Consumer>
-                      </SpanContext.Provider>
-                    </TransactionProfileIdProvider>
+                    <SpanContext.Provider>
+                      <SpanContext.Consumer>
+                        {spanContextProps => (
+                          <Observer>
+                            {() => (
+                              <NewTraceDetailsSpanTree
+                                measurements={props.measurements}
+                                quickTrace={results}
+                                location={props.location}
+                                onRowClick={props.onRowClick}
+                                traceInfo={traceInfo}
+                                traceViewHeaderRef={traceViewRef}
+                                traceViewRef={traceViewRef}
+                                parentContinuingDepths={props.continuingDepths}
+                                traceHasMultipleRoots={props.continuingDepths.some(
+                                  c => c.depth === 0 && c.isOrphanDepth
+                                )}
+                                parentIsOrphan={props.isOrphan}
+                                parentIsLast={isLast}
+                                parentGeneration={transaction.generation ?? 0}
+                                organization={organization}
+                                waterfallModel={waterfallModel}
+                                filterSpans={waterfallModel.filterSpans}
+                                spans={waterfallModel
+                                  .getWaterfall({
+                                    viewStart: 0,
+                                    viewEnd: 1,
+                                  })
+                                  .slice(1)}
+                                focusedSpanIds={waterfallModel.focusedSpanIds}
+                                spanContextProps={spanContextProps}
+                                operationNameFilters={waterfallModel.operationNameFilters}
+                              />
+                            )}
+                          </Observer>
+                        )}
+                      </SpanContext.Consumer>
+                    </SpanContext.Provider>
                   </ProfileGroupProvider>
                 )}
               </ProfileContext.Consumer>

+ 2 - 9
static/app/views/performance/transactionDetails/content.tsx

@@ -18,7 +18,6 @@ import FileSize from 'sentry/components/fileSize';
 import * as Layout from 'sentry/components/layouts/thirds';
 import LoadingError from 'sentry/components/loadingError';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
-import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
 import {TransactionToProfileButton} from 'sentry/components/profiling/transactionToProfileButton';
 import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import {TagsTable} from 'sentry/components/tagsTable';
@@ -139,13 +138,7 @@ function EventDetailsContent(props: Props) {
             skipLight={false}
           >
             {results => (
-              <TransactionProfileIdProvider
-                projectId={transaction.projectID}
-                transactionId={
-                  transaction.type === 'transaction' ? transaction.id : undefined
-                }
-                timestamp={transaction.dateReceived}
-              >
+              <Fragment>
                 <Layout.Header>
                   <Layout.HeaderContent>
                     <Breadcrumb
@@ -299,7 +292,7 @@ function EventDetailsContent(props: Props) {
                     </Layout.Side>
                   )}
                 </Layout.Body>
-              </TransactionProfileIdProvider>
+              </Fragment>
             )}
           </QuickTraceQuery>
         )}