Browse Source

feat(insights): add additional trace analytics (#73030)

more analytics for trace viewer/explorer.
Kevin Liu 8 months ago
parent
commit
9796ade3a4

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

@@ -1,6 +1,8 @@
 export type TracingEventParameters = {
   'trace.metadata': {
+    num_nodes: number;
     num_root_children: number;
+    project_platforms: string[];
     shape: string;
     trace_duration_seconds: number;
   };
@@ -54,6 +56,7 @@ export type TracingEventParameters = {
   };
   'trace_explorer.search_success': {
     has_data: boolean;
+    num_missing_trace_root: number;
     num_traces: number;
     queries: string[];
   };

+ 9 - 4
static/app/views/performance/newTraceDetails/index.tsx

@@ -25,6 +25,7 @@ import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {EventTransaction} from 'sentry/types/event';
 import type {Organization} from 'sentry/types/organization';
+import type {Project} from 'sentry/types/project';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {browserHistory} from 'sentry/utils/browserHistory';
 import EventView from 'sentry/utils/discover/eventView';
@@ -91,7 +92,11 @@ function decodeScrollQueue(maybePath: unknown): TraceTree.NodePath[] | null {
   return null;
 }
 
-function logTraceMetadata(tree: TraceTree, organization: Organization) {
+function logTraceMetadata(
+  tree: TraceTree,
+  projects: Project[],
+  organization: Organization
+) {
   switch (tree.shape) {
     case TraceType.BROKEN_SUBTRACES:
     case TraceType.EMPTY_TRACE:
@@ -100,7 +105,7 @@ function logTraceMetadata(tree: TraceTree, organization: Organization) {
     case TraceType.NO_ROOT:
     case TraceType.ONLY_ERRORS:
     case TraceType.BROWSER_MULTIPLE_ROOTS:
-      traceAnalytics.trackTraceMetadata(tree, organization);
+      traceAnalytics.trackTraceMetadata(tree, projects, organization);
       break;
     default: {
       Sentry.captureMessage('Unknown trace type');
@@ -822,8 +827,8 @@ export function TraceViewWaterfall(props: TraceViewWaterfallProps) {
       return;
     }
 
-    logTraceMetadata(tree, props.organization);
-  }, [tree, props.organization]);
+    logTraceMetadata(tree, projects, props.organization);
+  }, [tree, projects, props.organization]);
 
   useLayoutEffect(() => {
     if (!tree.root?.space || tree.type !== 'trace') {

+ 19 - 1
static/app/views/performance/newTraceDetails/traceAnalytics.tsx

@@ -1,19 +1,37 @@
 import * as Sentry from '@sentry/react';
 
 import type {Organization} from 'sentry/types/organization';
+import type {Project} from 'sentry/types/project';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import type {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
 import type {TraceType} from 'sentry/views/performance/newTraceDetails/traceType';
 
-const trackTraceMetadata = (tree: TraceTree, organization: Organization) => {
+const trackTraceMetadata = (
+  tree: TraceTree,
+  projects: Project[],
+  organization: Organization
+) => {
   Sentry.metrics.increment(`trace.trace_shape.${tree.shape}`);
+
   // space[1] represents the node duration (in milliseconds)
   const trace_duration_seconds = (tree.root.space?.[1] ?? 0) / 1000;
+  const projectSlugs = [
+    ...new Set(
+      tree.list.map(node => node.metadata.project_slug).filter(slug => slug !== undefined)
+    ),
+  ];
+
+  const projectPlatforms = projects
+    .filter(p => projectSlugs.includes(p.slug))
+    .map(project => project?.platform ?? '');
+
   trackAnalytics('trace.metadata', {
     shape: tree.shape,
     // round trace_duration_seconds to nearest two decimal places
     trace_duration_seconds: Math.round(trace_duration_seconds * 100) / 100,
     num_root_children: tree.root.children.length,
+    num_nodes: tree.list.length,
+    project_platforms: projectPlatforms,
     organization,
   });
 };

+ 2 - 0
static/app/views/traces/content.tsx

@@ -670,6 +670,8 @@ function useTraces<F extends string>({
         queries,
         has_data: result.data.data.length > 0,
         num_traces: result.data.data.length,
+        num_missing_trace_root: result.data.data.filter(trace => trace.name === null)
+          .length,
       });
     } else if (result.status === 'error') {
       const response = result.error.responseJSON;