Repository: getsentry/sentry
Pull request: feat(replays): Emit has hydration error analytic
fixes #61847


Problem statement:
Add a hydration breadcrumb presence analytic event
We're trying to find examples of replays that were viewed and would've had the hydration breadcrumb.

ACs:
When they do not have the feature hydration modal feature flag, emit an analytic event if the hydration error breadcrumb is present in the replay.

Hints from issue discussion:

Commit message: feat(replays): Emit has hydration error analytic

fixes #61847

Patch to review:
diff --git a/static/app/utils/analytics/replayAnalyticsEvents.tsx b/static/app/utils/analytics/replayAnalyticsEvents.tsx
index 0ee053572b1219..c2e5e072d50c7f 100644
--- a/static/app/utils/analytics/replayAnalyticsEvents.tsx
+++ b/static/app/utils/analytics/replayAnalyticsEvents.tsx
@@ -17,6 +17,10 @@ export type ReplayEventParameters = {
     started_at_delta: number; // Log the change (negative number==earlier date) in started_at
     total_errors: number;
   };
+  'replay.details-has-hydration-error': {
+    num_errors: number;
+    replay_id: string;
+  };
   'replay.details-layout-changed': {
     chosen_layout: LayoutKey;
     default_layout: LayoutKey;
@@ -106,6 +110,7 @@ export type ReplayEventKey = keyof ReplayEventParameters;
 export const replayEventMap: Record<ReplayEventKey, string | null> = {
   'replay.accessibility-issue-clicked': 'Clicked Replay Accessibility Issue',
   'replay.details-data-loaded': 'Replay Details Data Loaded',
+  'replay.details-has-hydration-error': 'Replay Details Has Hydration Error',
   'replay.details-layout-changed': 'Changed Replay Details Layout',
   'replay.details-network-panel-closed': 'Closed Replay Network Details Panel',
   'replay.details-network-panel-opened': 'Opened Replay Network Details Panel',
diff --git a/static/app/utils/replays/hooks/useLogReplayDataLoaded.tsx b/static/app/utils/replays/hooks/useLogReplayDataLoaded.tsx
index 05ad03d752fe83..c2620c54560e59 100644
--- a/static/app/utils/replays/hooks/useLogReplayDataLoaded.tsx
+++ b/static/app/utils/replays/hooks/useLogReplayDataLoaded.tsx
@@ -45,6 +45,23 @@ function useLogReplayDataLoaded({fetchError, fetching, projectSlug, replay}: Pro
       finished_at_delta: replay.timestampDeltas.finishedAtDelta,
       replay_id: replayRecord.id,
     });
+
+    // TODO(session-replay-show-hydration-errors): remove this analytic on GA
+    if (!organization.features.includes('session-replay-show-hydration-errors')) {
+      // @ts-expect-error the hydration frames are filtered when the flag is off
+      const allFrames = replay._sortedBreadcrumbFrames;
+      const hydrationErrorFrames = allFrames.filter(
+        frame => frame.category === 'replay.hydrate-error'
+      );
+      if (hydrationErrorFrames.length > 0) {
+        // Track when a hydration breadcrumb is present but unable to be viewed
+        trackAnalytics('replay.details-has-hydration-error', {
+          organization,
+          num_errors: hydrationErrorFrames.length,
+          replay_id: replayRecord.id,
+        });
+      }
+    }
   }, [organization, project, fetchError, fetching, projectSlug, replay]);
 }
 


Code review comments:
diff_hunk: @@ -45,6 +45,23 @@ function useLogReplayDataLoaded({fetchError, fetching, projectSlug, replay}: Pro
       finished_at_delta: replay.timestampDeltas.finishedAtDelta,
       replay_id: replayRecord.id,
     });
+
+    // TODO(session-replay-show-hydration-errors): remove this analytic on GA
+    if (!organization.features.includes('session-replay-show-hydration-errors')) {
+      // @ts-expect-error the hydration frames are filtered when the flag is off
+      const allFrames = replay._sortedBreadcrumbFrames;
path: static/app/utils/replays/hooks/useLogReplayDataLoaded.tsx
text: @user1:
This is meant to be a private field, so a) i'm surprised typescript isn't complaining b) can we call `getChapterFrames` instead



@author:
getChapterFrames is filtering out the frames i want https://github.com/getsentry/sentry/blob/615d9f558639b13cae5f023d463aeee152bc2875/static/app/utils/replays/replayReader.tsx#L298

@user1:
oh right, the other feature flag

why is TS not complaining though?

@author:
ts-expect-error?

@user1:
what if the ReplayReader class had a public method `hasHydrationCrumb(): () => boolean`

something like:
`replay._sortedBreadcrumbFrames.some(...);`