Skip to content

feat(error-tracking): show mobile screenviews in the exception timeline - #89054

Closed
posthog[bot] wants to merge 4 commits into
masterfrom
posthog-self-driving/featerror-tracking-show-screenviews-in-8b8897
Closed

posthog[bot] wants to merge 4 commits into
masterfrom
posthog-self-driving/featerror-tracking-show-screenviews-in-8b8897

Conversation

@posthog

@posthog posthog Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • A user viewing a mobile exception sees no screenviews in the session timeline, so they must open the session recording separately to find where the crash happened.
  • The timeline builds its events from one CombinedEventLoader query. Its filter is or(equals(event, '$exception'), equals(event, '$pageview'), notEquals(left(event, 1), '$')).
  • $screen starts with $ and is not $pageview, so it never matches. Mobile lifecycle events carry no $ prefix, so they pass the third clause and become the only mobile context on the timeline.

Closes #90005

Changes

  • A mobile exception timeline now shows a "Screenviews" category with each $screen event, listed by screen name next to a phone icon.
  • combined.tsx selects $screen_name, adds $screen to the query WHERE clause, and maps the event to a SCREEN_VIEWS item.
  • screen.tsx renders the screen name. It drops the URL parsing and "open in browser" action from the pageview renderer, which do not fit a screen.
  • The screenview category reuses the existing shared CombinedEventLoader, so no extra query runs.
  • Mechanical: new SCREEN_VIEWS enum value, a category label and tooltip, an expanded-details WHERE case, and registration in the exception card session tab.

screenviews

How did you test this code?

  • Added combined.test.ts: it catches a revert of the $screen WHERE clause or the $screen to SCREEN_VIEWS mapping, which no existing test covered (CombinedEventLoader had no test).
  • Rendered the real screenRenderer in a Storybook story (MobileScreenviews) through a headless browser to confirm screenviews appear with the screen name and phone icon. The screenshot above is that render.
  • Ran the SessionTimeline Jest suite and the TypeScript check for the touched files.
  • Not run: the full backend and Playwright suites, which this change does not touch.

Automatic notifications

  • Publish to changelog?

Docs update

None. This change adds no user-facing setting or documented workflow.

🤖 Agent context

Autonomy: Fully autonomous

  • Authored by an agent (Claude) from an inbox report about missing mobile screenviews in the exception timeline.
  • Skills invoked: /writing-tests, /simplify, /writing-pr-descriptions.
  • Chose a new SCREEN_VIEWS category over widening PAGE_VIEWS. A screen has no URL and no "open in browser" action, so folding it into the pageview renderer would need a branch inside that renderer. A separate category mirrors how PAGE_VIEWS and CUSTOM_EVENTS already work.
  • /simplify ran four review passes (reuse, simplification, efficiency, altitude); all reported the diff clean.
  • The screenshot and the story use invented screen names, not customer data.

Created with PostHog Desktop from this inbox report.

@trunk-io

trunk-io Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

❌ This pull request was removed from the merge queue because it failed tests. PR #90286 was used for testing. See more details here.

Failed Required Status Conclusion
Visual regression tests pass Failure
  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Bundle size — 🔺 +345 B (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.04 MiB · 🔺 +345 B (+0.0%)

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.37 MiB · 22 files no change ███░░░░░░░ 30.3% of 4.51 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.81 MiB · 3,245 files 🔺 +59 B (+0.0%) █████████░ 90.7% of 9.71 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
306.9 KiB ../node_modules/.pnpm/posthog-js@1.420.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
260.9 KiB ../node_modules/.pnpm/posthog-js@1.420.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.js
252.5 KiB src/taxonomy/core-filter-definitions-by-group.json
154.2 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
104.7 KiB src/lib/api.ts
95.2 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.25 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.25 MiB · 18 files 🔺 +38 B (+0.0%) ████░░░░░░ 39.4% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 45 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
748.8 KiB dist/toolbar/toolbar-app-XYGAYFW6.css
585.4 KiB dist/toolbar/chunk-chunk-WAAZXMI4.js
484.7 KiB dist/toolbar/chunk-chunk-QMGLBVDO.js
133.8 KiB dist/toolbar/chunk-chunk-WIGPXHXA.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
71.3 KiB dist/toolbar/toolbar-app-IO2JX2X2.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-ENVYWGUI.js
20.9 KiB dist/toolbar/chunk-chunk-HEUIHINI.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +5.1 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1449.72 MiB · 🔺 +5.1 KiB (+0.0%)

@posthog

posthog Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Visual changes approved by @hpouillot — baseline updated in d7afed1.

View this run in PostHog

4 changed.

@trunk-io

trunk-io Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@hpouillot
hpouillot marked this pull request as ready for review August 27, 2026 13:59
posthog Bot and others added 3 commits August 27, 2026 16:05
Mobile exceptions lost their screen context. The session timeline built its
events from one CombinedEventLoader query whose filter admitted `$exception`,
`$pageview`, and every non-`$` event, but no other reserved event. `$screen`
starts with `$` and is not `$pageview`, so screenviews never loaded.

Add a SCREEN_VIEWS category. The loader now selects `$screen_name`, adds
`$screen` to the WHERE clause, and maps the event to a screenview item. A new
screenRenderer shows the screen name with a mobile icon, without the URL
parsing or "open in browser" action that only fit pageviews.

Generated-By: PostHog Desktop
Task-Id: 86ebb785-e37b-49d7-9b41-423b9684a072
…ws category

Screenviews shared a separate SCREEN_VIEWS category and toggle. A session is
web or mobile in practice, so one of the pageview and screenview toggles was
always empty.

Fold mobile $screen events into the PAGE_VIEWS category, relabeled "Views". The
pageview renderer now shows the screen name when the event carries one, and the
URL pathname otherwise. Remove the separate screen renderer, enum value, and
toggle.

Generated-By: PostHog Desktop
Task-Id: 86ebb785-e37b-49d7-9b41-423b9684a072
4 updated
Run: 97f2c9e1-8b37-4109-9596-36f6d0e29bb2

Co-authored-by: hpouillot <3455883+hpouillot@users.noreply.github.com>

Copy link
Copy Markdown
Contributor

Closing as a duplicate of #88072. Both fix the same omission: buildWhere() in combined.tsx allows $exception, $pageview, and non-$ events, so $screen never reaches the session timeline. Both touch the same set of symbols and conflict with each other.

#88072 is kept because it follows the existing per-category structure, with its own SCREEN_VIEWS lane and renderer, rather than widening PageItem with two mutually exclusive optional fields. It also leaves the existing "Pageviews" label alone for web users. One latent issue avoided: screen items here inherit page.tsx getMenuItems, whose open-page-view entry is url-gated and would silently disappear.

Worth porting into #88072: the combined.test.ts added here. #88072 has no unit test for the parsing change.

@jakesciotto jakesciotto closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show mobile screenviews in the exception session timeline

4 participants