Browse Source

feat(profiling): add differential flamegraph boilerplate to statistical issue (#59905)

Add component boilerplate for differential flamegraph
Jonas 1 year ago
parent
commit
b88add8473

+ 45 - 0
static/app/components/events/eventStatisticalDetector/eventDifferentialFlamegraph.tsx

@@ -0,0 +1,45 @@
+import {useEffect} from 'react';
+import * as Sentry from '@sentry/react';
+
+import {Event} from 'sentry/types';
+
+interface EventDifferenialFlamegraphProps {
+  event: Event;
+}
+
+export function EventDifferenialFlamegraph(props: EventDifferenialFlamegraphProps) {
+  const evidenceData = props.event.occurrence?.evidenceData;
+
+  const fingerprint = evidenceData?.fingerprint;
+  const breakpoint = evidenceData?.breakpoint;
+
+  const isValid = fingerprint !== undefined && breakpoint !== undefined;
+
+  useEffect(() => {
+    if (isValid) {
+      return;
+    }
+
+    Sentry.withScope(scope => {
+      scope.setContext('evidence data fields', {
+        fingerprint,
+        breakpoint,
+      });
+
+      Sentry.captureException(
+        new Error('Missing required evidence data on function regression issue.')
+      );
+    });
+  }, [isValid, fingerprint, breakpoint]);
+
+  if (!isValid) {
+    return null;
+  }
+
+  return (
+    <div>
+      <h3>EventDifferenialFlamegraph</h3>
+      <p>TODO: Implement</p>
+    </div>
+  );
+}

+ 8 - 1
static/app/components/profiling/aggregateFlamegraphPanel.tsx

@@ -13,15 +13,22 @@ import {FlamegraphThemeProvider} from 'sentry/utils/profiling/flamegraph/flamegr
 import {Frame} from 'sentry/utils/profiling/frame';
 import {useAggregateFlamegraphQuery} from 'sentry/utils/profiling/hooks/useAggregateFlamegraphQuery';
 import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
+import usePageFilters from 'sentry/utils/usePageFilters';
 import {ProfileGroupProvider} from 'sentry/views/profiling/profileGroupProvider';
 
 export function AggregateFlamegraphPanel({transaction}: {transaction: string}) {
+  const {selection} = usePageFilters();
   const [hideSystemFrames, setHideSystemFrames] = useLocalStorageState(
     'profiling-flamegraph-collapsed-frames',
     true
   );
 
-  const {data, isLoading} = useAggregateFlamegraphQuery({transaction});
+  const {data, isLoading} = useAggregateFlamegraphQuery({
+    transaction,
+    environments: selection.environments,
+    projects: selection.projects,
+    datetime: selection.datetime,
+  });
   const isEmpty = data?.shared.frames.length === 0;
 
   return (

+ 16 - 9
static/app/utils/profiling/hooks/useAggregateFlamegraphQuery.ts

@@ -1,15 +1,23 @@
 import {useMemo} from 'react';
 
 import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
+import {PageFilters} from 'sentry/types';
 import {useApiQuery} from 'sentry/utils/queryClient';
 import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import useOrganization from 'sentry/utils/useOrganization';
-import usePageFilters from 'sentry/utils/usePageFilters';
 
-export function useAggregateFlamegraphQuery({transaction}: {transaction: string}) {
+export function useAggregateFlamegraphQuery({
+  projects,
+  datetime,
+  environments,
+  transaction,
+}: {
+  datetime: Partial<PageFilters['datetime']>;
+  environments: string[];
+  projects: number[];
+  transaction: string;
+}) {
   const organization = useOrganization();
-  const {selection} = usePageFilters();
-
   const path = `/organizations/${organization.slug}/profiling/flamegraph/`;
 
   const query = useMemo(() => {
@@ -20,14 +28,13 @@ export function useAggregateFlamegraphQuery({transaction}: {transaction: string}
     return conditions.formatString();
   }, [transaction]);
 
-  const enabled =
-    !!transaction && Array.isArray(selection.projects) && selection.projects.length > 0;
+  const enabled = !!transaction && Array.isArray(projects) && projects.length > 0;
 
   const endpointOptions = {
     query: {
-      project: selection.projects,
-      environment: selection.environments,
-      ...normalizeDateTimeParams(selection.datetime),
+      project: projects,
+      environment: environments,
+      ...normalizeDateTimeParams(datetime),
       query,
     },
   };

+ 9 - 0
static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx

@@ -17,6 +17,7 @@ import AggregateSpanDiff from 'sentry/components/events/eventStatisticalDetector
 import EventBreakpointChart from 'sentry/components/events/eventStatisticalDetector/breakpointChart';
 import {EventAffectedTransactions} from 'sentry/components/events/eventStatisticalDetector/eventAffectedTransactions';
 import EventComparison from 'sentry/components/events/eventStatisticalDetector/eventComparison';
+import {EventDifferenialFlamegraph} from 'sentry/components/events/eventStatisticalDetector/eventDifferentialFlamegraph';
 import {EventFunctionComparisonList} from 'sentry/components/events/eventStatisticalDetector/eventFunctionComparisonList';
 import {EventRegressionSummary} from 'sentry/components/events/eventStatisticalDetector/eventRegressionSummary';
 import {EventFunctionBreakpointChart} from 'sentry/components/events/eventStatisticalDetector/functionBreakpointChart';
@@ -231,6 +232,14 @@ function ProfilingDurationRegressionIssueDetailsContent({
         <ErrorBoundary mini>
           <EventFunctionBreakpointChart event={event} />
         </ErrorBoundary>
+        <Feature
+          features={['profiling-differential-flamegraph']}
+          organization={organization}
+        >
+          <ErrorBoundary mini>
+            <EventDifferenialFlamegraph event={event} />
+          </ErrorBoundary>
+        </Feature>
         <ErrorBoundary mini>
           <EventAffectedTransactions event={event} group={group} project={project} />
         </ErrorBoundary>

+ 8 - 1
static/app/views/profiling/profileSummary/index.tsx

@@ -60,6 +60,7 @@ import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
+import usePageFilters from 'sentry/utils/usePageFilters';
 import {transactionSummaryRouteWithQuery} from 'sentry/views/performance/transactionSummary/utils';
 import {
   FlamegraphProvider,
@@ -290,6 +291,7 @@ interface ProfileSummaryPageProps {
 function ProfileSummaryPage(props: ProfileSummaryPageProps) {
   const organization = useOrganization();
   const project = useCurrentProjectFromRouteParam();
+  const {selection} = usePageFilters();
 
   const profilingUsingTransactions = organization.features.includes(
     'profiling-using-transactions'
@@ -342,7 +344,12 @@ function ProfileSummaryPage(props: ProfileSummaryPageProps) {
     return search.formatString();
   }, [rawQuery, transaction]);
 
-  const {data, isLoading, isError} = useAggregateFlamegraphQuery({transaction});
+  const {data, isLoading, isError} = useAggregateFlamegraphQuery({
+    transaction,
+    environments: selection.environments,
+    projects: selection.projects,
+    datetime: selection.datetime,
+  });
 
   const [visualization, setVisualization] = useLocalStorageState<
     'flamegraph' | 'call tree'