Browse Source

feat(issues): Add analytics to issue details page for timeline (#64806)

Scott Cooper 1 year ago
parent
commit
b9adc3b9a1

+ 13 - 0
static/app/views/issueDetails/traceTimeline/traceTimeline.spec.tsx

@@ -5,10 +5,13 @@ import {ProjectFixture} from 'sentry-fixture/project';
 import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
 
 import ProjectsStore from 'sentry/stores/projectsStore';
+import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
 
 import {TraceTimeline} from './traceTimeline';
 import type {TraceEventResponse} from './useTraceTimelineEvents';
 
+jest.mock('sentry/utils/routeAnalytics/useRouteAnalyticsParams');
+
 describe('TraceTimeline', () => {
   const organization = OrganizationFixture({features: ['issues-trace-timeline']});
   const event = EventFixture({
@@ -55,6 +58,7 @@ describe('TraceTimeline', () => {
 
   beforeEach(() => {
     ProjectsStore.loadInitialData([project]);
+    jest.clearAllMocks();
   });
 
   it('renders items and highlights the current event', async () => {
@@ -73,6 +77,9 @@ describe('TraceTimeline', () => {
 
     await userEvent.hover(screen.getByTestId('trace-timeline-tooltip-1'));
     expect(await screen.findByText('You are here')).toBeInTheDocument();
+    expect(useRouteAnalyticsParams).toHaveBeenCalledWith({
+      trace_timeline_status: 'shown',
+    });
   });
 
   it('displays nothing if the only event is the current event', async () => {
@@ -91,6 +98,9 @@ describe('TraceTimeline', () => {
     });
     render(<TraceTimeline event={event} />, {organization});
     expect(await screen.findByTestId('trace-timeline-empty')).toBeInTheDocument();
+    expect(useRouteAnalyticsParams).toHaveBeenCalledWith({
+      trace_timeline_status: 'empty',
+    });
   });
 
   it('displays nothing if there are no events', async () => {
@@ -112,6 +122,9 @@ describe('TraceTimeline', () => {
     });
     render(<TraceTimeline event={event} />, {organization});
     expect(await screen.findByTestId('trace-timeline-empty')).toBeInTheDocument();
+    expect(useRouteAnalyticsParams).toHaveBeenCalledWith({
+      trace_timeline_status: 'empty',
+    });
   });
 
   it('shows seconds for very short timelines', async () => {

+ 14 - 1
static/app/views/issueDetails/traceTimeline/traceTimeline.tsx

@@ -5,6 +5,7 @@ import ErrorBoundary from 'sentry/components/errorBoundary';
 import Placeholder from 'sentry/components/placeholder';
 import {space} from 'sentry/styles/space';
 import type {Event} from 'sentry/types';
+import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
 import {useDimensions} from 'sentry/utils/useDimensions';
 import useOrganization from 'sentry/utils/useOrganization';
 import {hasTraceTimelineFeature} from 'sentry/views/issueDetails/traceTimeline/utils';
@@ -23,7 +24,19 @@ export function TraceTimeline({event}: TraceTimelineProps) {
   const hasFeature = hasTraceTimelineFeature(organization);
   const {isError, isLoading, data} = useTraceTimelineEvents({event}, hasFeature);
 
-  if (!hasFeature || !event.contexts?.trace?.trace_id) {
+  const hasTraceId = !!event.contexts?.trace?.trace_id;
+
+  let timelineStatus: string | undefined;
+  if (hasFeature) {
+    if (hasTraceId && !isLoading) {
+      timelineStatus = data.length > 1 ? 'shown' : 'empty';
+    } else if (!hasTraceId) {
+      timelineStatus = 'no_trace_id';
+    }
+  }
+  useRouteAnalyticsParams(timelineStatus ? {trace_timeline_status: timelineStatus} : {});
+
+  if (!hasFeature || !hasTraceId) {
     return null;
   }