Browse Source

feat(trace-explorer): add analytics (#72614)

Analytics for trace explorer, excluding the search_result analytics.
Kevin Liu 9 months ago
parent
commit
a59afdf2a4

+ 4 - 3
static/app/utils/analytics/tracingEventMap.tsx

@@ -42,7 +42,9 @@ export type TracingEventParameters = {
     has_data: boolean;
     queries: string[];
   };
-  'trace_explorer.toggle_trace_table_spans': {};
+  'trace_explorer.toggle_trace_details': {
+    expanded: boolean;
+  };
 };
 
 export type TracingEventKey = keyof TracingEventParameters;
@@ -68,8 +70,7 @@ export const tracingEventMap: Record<TracingEventKey, string | null> = {
   'trace_explorer.open_trace': 'Trace Explorer: Open Trace in Trace Viewer',
   'trace_explorer.open_trace_span': 'Trace Explorer: Open Trace Span in Trace Viewer',
   'trace_explorer.remove_span_condition': 'Trace Explorer: Remove Span Condition',
-  'trace_explorer.toggle_trace_table_spans':
-    'Trace Explorer: Toggle Spans in Trace Table',
+  'trace_explorer.toggle_trace_details': 'Trace Explorer: Toggle Trace Details in Table',
   'trace_explorer.search_failure': 'Trace Explorer: Search Failure',
   'trace_explorer.search_request': 'Trace Explorer: Search Request',
   'trace_explorer.search_success': 'Trace Explorer: Search Success',

+ 30 - 1
static/app/views/traces/content.tsx

@@ -24,6 +24,7 @@ import {t, tct} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {PageFilters} from 'sentry/types/core';
 import type {MRI} from 'sentry/types/metrics';
+import type {Organization} from 'sentry/types/organization';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {browserHistory} from 'sentry/utils/browserHistory';
 import {getFormattedMQL} from 'sentry/utils/metrics';
@@ -253,6 +254,7 @@ function TraceRow({
   const [expanded, setExpanded] = useState<boolean>(defaultExpanded);
   const [highlightedSliceName, _setHighlightedSliceName] = useState('');
   const location = useLocation();
+  const organization = useOrganization();
   const queries = useMemo(() => {
     return decodeList(location.query.query);
   }, [location.query.query]);
@@ -276,10 +278,21 @@ function TraceRow({
           aria-expanded={expanded}
           size="zero"
           borderless
+          onClick={() =>
+            trackAnalytics('trace_explorer.toggle_trace_details', {
+              organization,
+              expanded,
+            })
+          }
         />
         <TraceIdRenderer
           traceId={trace.trace}
           timestamp={trace.spans[0].timestamp}
+          onClick={() =>
+            trackAnalytics('trace_explorer.open_trace', {
+              organization,
+            })
+          }
           location={location}
         />
       </StyledPanelItem>
@@ -323,7 +336,14 @@ function TraceRow({
         <SpanTimeRenderer timestamp={trace.end} tooltipShowSeconds />
       </StyledPanelItem>
       <StyledPanelItem align="right">
-        <TraceIssuesRenderer trace={trace} />
+        <TraceIssuesRenderer
+          trace={trace}
+          onClick={() =>
+            trackAnalytics('trace_explorer.open_in_issues', {
+              organization,
+            })
+          }
+        />
       </StyledPanelItem>
       {expanded && (
         <SpanTable
@@ -346,6 +366,7 @@ function SpanTable({
   trace: TraceResult<Field>;
 }) {
   const location = useLocation();
+  const organization = useOrganization();
   const queries = useMemo(() => {
     return decodeList(location.query.query);
   }, [location.query.query]);
@@ -369,6 +390,7 @@ function SpanTable({
           </StyledPanelHeader>
           {spans.map(span => (
             <SpanRow
+              organization={organization}
               key={span.id}
               span={span}
               trace={trace}
@@ -391,10 +413,12 @@ function SpanTable({
 }
 
 function SpanRow({
+  organization,
   span,
   trace,
   setHighlightedSliceName,
 }: {
+  organization: Organization;
   setHighlightedSliceName: (sliceName: string) => void;
   span: SpanResult<Field>;
 
@@ -410,6 +434,11 @@ function SpanRow({
           spanId={span.id}
           traceId={trace.trace}
           timestamp={span.timestamp}
+          onClick={() =>
+            trackAnalytics('trace_explorer.open_trace_span', {
+              organization,
+            })
+          }
         />
       </StyledSpanPanelItem>
       <StyledSpanPanelItem align="left" overflow>

+ 18 - 3
static/app/views/traces/fieldRenderers.tsx

@@ -267,6 +267,7 @@ interface SpanIdRendererProps {
   timestamp: string;
   traceId: string;
   transactionId: string;
+  onClick?: () => void;
 }
 
 export function SpanIdRenderer({
@@ -275,6 +276,7 @@ export function SpanIdRenderer({
   timestamp,
   traceId,
   transactionId,
+  onClick,
 }: SpanIdRendererProps) {
   const location = useLocation();
   const organization = useOrganization();
@@ -290,12 +292,17 @@ export function SpanIdRenderer({
     source: TraceViewSources.TRACES,
   });
 
-  return <Link to={target}>{getShortEventId(spanId)}</Link>;
+  return (
+    <Link to={target} onClick={onClick}>
+      {getShortEventId(spanId)}
+    </Link>
+  );
 }
 
 interface TraceIdRendererProps {
   location: Location;
   traceId: string;
+  onClick?: () => void;
   timestamp?: DateString;
   transactionId?: string;
 }
@@ -305,6 +312,7 @@ export function TraceIdRenderer({
   timestamp,
   transactionId,
   location,
+  onClick,
 }: TraceIdRendererProps) {
   const organization = useOrganization();
   const {selection} = usePageFilters();
@@ -326,7 +334,7 @@ export function TraceIdRenderer({
   });
 
   return (
-    <Link to={target} style={{minWidth: '66px', textAlign: 'right'}}>
+    <Link to={target} style={{minWidth: '66px', textAlign: 'right'}} onClick={onClick}>
       {getShortEventId(traceId)}
     </Link>
   );
@@ -358,7 +366,13 @@ export function TransactionRenderer({
   return <Link to={target}>{transaction}</Link>;
 }
 
-export function TraceIssuesRenderer({trace}: {trace: TraceResult<Field>}) {
+export function TraceIssuesRenderer({
+  trace,
+  onClick,
+}: {
+  trace: TraceResult<Field>;
+  onClick?: () => void;
+}) {
   const organization = useOrganization();
 
   const issueCount = trace.numErrors + trace.numOccurrences;
@@ -373,6 +387,7 @@ export function TraceIssuesRenderer({trace}: {trace: TraceResult<Field>}) {
           query: `trace:"${trace.trace}"`,
         },
       })}
+      onClick={onClick}
       size="xs"
       icon={<IconIssues size="xs" />}
       disabled={issueCount === 0}

+ 15 - 2
static/app/views/traces/tracesSearchBar.tsx

@@ -5,6 +5,7 @@ import SearchBar from 'sentry/components/events/searchBar';
 import {IconAdd, IconClose} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
+import {trackAnalytics} from 'sentry/utils/analytics';
 import {DiscoverDatasets} from 'sentry/utils/discover/types';
 import useOrganization from 'sentry/utils/useOrganization';
 import {useSpanFieldSupportedTags} from 'sentry/views/performance/utils/useSpanFieldSupportedTags';
@@ -61,7 +62,14 @@ export function TracesSearchBar({
             aria-label={t('Remove span')}
             icon={<IconClose size="sm" />}
             size="sm"
-            onClick={() => (queries.length === 0 ? false : handleClearSearch(index))}
+            onClick={() => {
+              trackAnalytics('trace_explorer.remove_span_condition', {
+                organization,
+              });
+              if (queries.length >= 0) {
+                handleClearSearch(index);
+              }
+            }}
           />
         </TraceBar>
       ))}
@@ -71,7 +79,12 @@ export function TracesSearchBar({
           aria-label={t('Add query')}
           icon={<IconAdd size="xs" isCircled />}
           size="sm"
-          onClick={() => handleSearch(localQueries.length, '')}
+          onClick={() => {
+            trackAnalytics('trace_explorer.add_span_condition', {
+              organization,
+            });
+            handleSearch(localQueries.length, '');
+          }}
         >
           {t('Add Span Condition')}
         </Button>