Skip to content

feat(tracing): Add reportFullyDisplayed() static API#6419

Open
antonis wants to merge 12 commits into
mainfrom
antonis/feat/report-fully-displayed
Open

feat(tracing): Add reportFullyDisplayed() static API#6419
antonis wants to merge 12 commits into
mainfrom
antonis/feat/report-fully-displayed

Conversation

@antonis

@antonis antonis commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Adds Sentry.reportFullyDisplayed() as a public imperative API for signaling Time to Full Display (TTFD). This is the imperative equivalent of the <TimeToFullDisplay> component, matching the cross-SDK Sentry.reportFullyDisplayed() API specified at develop.sentry.dev.

💡 Motivation and Context

Closes #6341

💚 How did you test it?

Unit tests — 6 new tests covering:

  • Happy path: TTFD span created with correct op, status, and measurement via integration
  • TTFD-before-TTID: timestamp adjusted to TTID end
  • No active span: no-op with warning, no crash
  • No TTID: no TTFD span created
  • Nested child span: correctly resolves root span ID
  • Idempotency: second call produces no duplicate spans

All 45 time-to-display tests pass. Lint, build, and circular dep check clean.

E2E verification — Tested with the sample app's SpaceflightNewsScreen calling Sentry.reportFullyDisplayed() after articles load. Verified in Sentry that:

  • ui.load.full_display span appears with status ok (~2.1s duration)
  • time_to_full_display measurement is set
  • TTFD > TTID (as expected — TTFD fires after API response, TTID on first render)
  • Multiple navigations produce consistent results with no duplicates

Example trace

📝 Checklist

🔮 Next steps

Add imperative `Sentry.reportFullyDisplayed()` API for signaling Time to
Full Display, matching the cross-SDK spec at develop.sentry.dev. This is
the imperative equivalent of the `<TimeToFullDisplay>` component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • feat(tracing): Add reportFullyDisplayed() static API by antonis in #6419

🤖 This preview updates automatically when you update the PR.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 6895568

@antonis antonis added the ready-to-merge Triggers the full CI test suite label Jul 8, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread packages/core/src/js/tracing/timetodisplay.tsx Outdated
Store the timestamp in a JS-side map and let the timeToDisplayIntegration
pick it up during processEvent, instead of calling updateFullDisplaySpan
directly. The previous approach failed in production because it relied on
updateInitialDisplaySpan to drain the deferred queue, but that function
is never called in the real component/navigation flow — TTID timestamps
are read from native during processEvent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sentry

sentry Bot commented Jul 8, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.18.0 (98) Release

⚙️ sentry-react-native Build Distribution Settings

Comment thread packages/core/test/tracing/timetodisplay.test.tsx
Comment thread packages/core/src/js/tracing/integrations/timeToDisplayIntegration.ts Outdated
Comment thread packages/core/test/tracing/timetodisplay.test.tsx
…e spans

- Use `getRootSpan` in `reportFullyDisplayed()` so the stored key matches the
  integration's `rootSpanId` lookup, even when called inside a nested child span.
- Add early return in `addTimeToFullDisplay` when an existing ok TTFD span is
  found, preventing duplicate `ui.load.full_display` spans.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3df6c17. Configure here.

Comment thread packages/core/src/js/tracing/integrations/timeToDisplayIntegration.ts Outdated
Pop both native and imperative timestamps unconditionally so the
imperative entry is cleaned up even when native takes priority.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3854.11 ms 1225.56 ms -2628.56 ms
Size 4.98 MiB 6.53 MiB 1.55 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
3817909+dirty 1183.90 ms 1187.50 ms 3.60 ms
038a6d7+dirty 3849.69 ms 1228.40 ms -2621.28 ms
3d377b5+dirty 1218.48 ms 1219.51 ms 1.03 ms
e5bb5f6+dirty 3826.14 ms 1212.24 ms -2613.90 ms
1122a96+dirty 3823.10 ms 1218.64 ms -2604.46 ms
27d9693+dirty 3831.11 ms 1216.94 ms -2614.17 ms
774257e+dirty 3846.90 ms 1215.02 ms -2631.88 ms
7d6fd3a+dirty 1223.29 ms 1229.57 ms 6.28 ms
5a23c47+dirty 3855.46 ms 1221.95 ms -2633.50 ms
15d4514+dirty 3840.17 ms 1225.79 ms -2614.38 ms

App size

Revision Plain With Sentry Diff
3817909+dirty 3.38 MiB 4.73 MiB 1.35 MiB
038a6d7+dirty 5.15 MiB 6.70 MiB 1.55 MiB
3d377b5+dirty 3.38 MiB 4.76 MiB 1.38 MiB
e5bb5f6+dirty 4.98 MiB 6.51 MiB 1.53 MiB
1122a96+dirty 5.15 MiB 6.68 MiB 1.53 MiB
27d9693+dirty 4.98 MiB 6.51 MiB 1.53 MiB
774257e+dirty 5.15 MiB 6.70 MiB 1.54 MiB
7d6fd3a+dirty 3.38 MiB 4.77 MiB 1.39 MiB
5a23c47+dirty 4.98 MiB 6.46 MiB 1.49 MiB
15d4514+dirty 5.15 MiB 6.70 MiB 1.55 MiB

Previous results on branch: antonis/feat/report-fully-displayed

Startup times

Revision Plain With Sentry Diff
433ad0d+dirty 3836.40 ms 1214.55 ms -2621.85 ms
97493c1+dirty 3849.60 ms 1230.16 ms -2619.45 ms

App size

Revision Plain With Sentry Diff
433ad0d+dirty 4.98 MiB 6.53 MiB 1.55 MiB
97493c1+dirty 4.98 MiB 6.53 MiB 1.55 MiB

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 439.79 ms 494.33 ms 54.54 ms
Size 49.74 MiB 55.26 MiB 5.52 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
c151573+dirty 530.34 ms 559.43 ms 29.09 ms
0a9e622+dirty 420.73 ms 464.83 ms 44.10 ms
a858ac3+dirty 426.50 ms 484.82 ms 58.32 ms
21a1e70+dirty 405.72 ms 436.16 ms 30.44 ms
6176a94+dirty 410.90 ms 452.20 ms 41.31 ms
e5bb5f6+dirty 430.09 ms 459.96 ms 29.87 ms
3d377b5+dirty 406.18 ms 453.52 ms 47.34 ms
9b5615c+dirty 431.65 ms 492.28 ms 60.63 ms
1a5721e+dirty 424.07 ms 482.32 ms 58.25 ms
267d3ed+dirty 413.06 ms 440.96 ms 27.90 ms

App size

Revision Plain With Sentry Diff
c151573+dirty 48.30 MiB 53.54 MiB 5.24 MiB
0a9e622+dirty 49.74 MiB 55.09 MiB 5.34 MiB
a858ac3+dirty 49.74 MiB 55.08 MiB 5.34 MiB
21a1e70+dirty 49.74 MiB 54.82 MiB 5.07 MiB
6176a94+dirty 48.30 MiB 53.54 MiB 5.24 MiB
e5bb5f6+dirty 49.74 MiB 55.09 MiB 5.34 MiB
3d377b5+dirty 43.75 MiB 48.14 MiB 4.39 MiB
9b5615c+dirty 49.74 MiB 55.09 MiB 5.34 MiB
1a5721e+dirty 49.74 MiB 55.09 MiB 5.34 MiB
267d3ed+dirty 48.30 MiB 53.58 MiB 5.28 MiB

Previous results on branch: antonis/feat/report-fully-displayed

Startup times

Revision Plain With Sentry Diff
97493c1+dirty 420.49 ms 452.66 ms 32.17 ms
433ad0d+dirty 424.33 ms 478.36 ms 54.02 ms

App size

Revision Plain With Sentry Diff
97493c1+dirty 49.74 MiB 55.26 MiB 5.52 MiB
433ad0d+dirty 49.74 MiB 55.26 MiB 5.52 MiB

- Use `timestampInSeconds()` instead of `Date.now() / 1000` for clock
  consistency with the rest of the tracing module.
- Cap `_imperativeTtfdTimestamps` at 50 entries, evicting the oldest
  when full, to prevent unbounded growth on sampled-out transactions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2461e43. Configure here.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 415.44 ms 456.61 ms 41.17 ms
Size 49.74 MiB 55.26 MiB 5.52 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
f3215d3+dirty 396.53 ms 436.66 ms 40.13 ms
0a9e622+dirty 425.22 ms 457.00 ms 31.78 ms
d2eadf8+dirty 468.02 ms 530.37 ms 62.35 ms
b0d3373+dirty 412.17 ms 452.84 ms 40.67 ms
4e0b819+dirty 599.31 ms 654.31 ms 55.00 ms
a858ac3+dirty 498.50 ms 575.22 ms 76.72 ms
9474ead+dirty 432.18 ms 481.92 ms 49.73 ms
0bd8916+dirty 400.15 ms 442.72 ms 42.57 ms
e5bb5f6+dirty 438.85 ms 466.33 ms 27.48 ms
9b5615c+dirty 428.67 ms 490.15 ms 61.48 ms

App size

Revision Plain With Sentry Diff
f3215d3+dirty 48.30 MiB 53.49 MiB 5.19 MiB
0a9e622+dirty 49.74 MiB 55.09 MiB 5.34 MiB
d2eadf8+dirty 48.30 MiB 53.48 MiB 5.18 MiB
b0d3373+dirty 48.30 MiB 53.58 MiB 5.28 MiB
4e0b819+dirty 49.74 MiB 54.81 MiB 5.07 MiB
a858ac3+dirty 49.74 MiB 55.08 MiB 5.34 MiB
9474ead+dirty 48.30 MiB 53.61 MiB 5.30 MiB
0bd8916+dirty 48.30 MiB 53.57 MiB 5.26 MiB
e5bb5f6+dirty 49.74 MiB 55.09 MiB 5.34 MiB
9b5615c+dirty 49.74 MiB 55.09 MiB 5.34 MiB

Previous results on branch: antonis/feat/report-fully-displayed

Startup times

Revision Plain With Sentry Diff
97493c1+dirty 419.22 ms 464.78 ms 45.56 ms
433ad0d+dirty 419.02 ms 472.57 ms 53.55 ms

App size

Revision Plain With Sentry Diff
97493c1+dirty 49.74 MiB 55.26 MiB 5.52 MiB
433ad0d+dirty 49.74 MiB 55.26 MiB 5.52 MiB

@antonis antonis marked this pull request as ready for review July 8, 2026 12:08
@antonis antonis requested review from a team, alwx and lucas-zimerman as code owners July 8, 2026 12:08
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3852.74 ms 1225.53 ms -2627.20 ms
Size 4.98 MiB 6.53 MiB 1.55 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
b9bebee+dirty 3858.02 ms 1231.92 ms -2626.11 ms
3d377b5+dirty 1201.55 ms 1201.80 ms 0.25 ms
1a2e7e0+dirty 3852.95 ms 1233.78 ms -2619.18 ms
e5bb5f6+dirty 3825.74 ms 1217.30 ms -2608.43 ms
27d9693+dirty 3837.40 ms 1227.74 ms -2609.67 ms
41d6254+dirty 3849.78 ms 1233.91 ms -2615.86 ms
9210ae6+dirty 3834.11 ms 1216.64 ms -2617.47 ms
c004dae+dirty 3857.82 ms 1224.87 ms -2632.95 ms
4e0b819+dirty 3828.96 ms 1205.64 ms -2623.32 ms
0b5120f+dirty 3843.24 ms 1223.00 ms -2620.24 ms

App size

Revision Plain With Sentry Diff
b9bebee+dirty 5.15 MiB 6.68 MiB 1.53 MiB
3d377b5+dirty 3.38 MiB 4.76 MiB 1.38 MiB
1a2e7e0+dirty 4.98 MiB 6.46 MiB 1.49 MiB
e5bb5f6+dirty 4.98 MiB 6.51 MiB 1.53 MiB
27d9693+dirty 4.98 MiB 6.51 MiB 1.53 MiB
41d6254+dirty 5.15 MiB 6.70 MiB 1.54 MiB
9210ae6+dirty 5.15 MiB 6.68 MiB 1.53 MiB
c004dae+dirty 5.15 MiB 6.67 MiB 1.51 MiB
4e0b819+dirty 4.98 MiB 6.46 MiB 1.49 MiB
0b5120f+dirty 5.15 MiB 6.68 MiB 1.53 MiB

Previous results on branch: antonis/feat/report-fully-displayed

Startup times

Revision Plain With Sentry Diff
433ad0d+dirty 3836.32 ms 1222.98 ms -2613.34 ms
97493c1+dirty 3866.45 ms 1244.86 ms -2621.60 ms

App size

Revision Plain With Sentry Diff
433ad0d+dirty 4.98 MiB 6.53 MiB 1.55 MiB
97493c1+dirty 4.98 MiB 6.53 MiB 1.55 MiB

Comment thread packages/core/src/js/tracing/integrations/timeToDisplayIntegration.ts Outdated
… pattern

Only return existing ok/unfinished TTFD span when no new timestamp is
available, so an imperative timestamp can still update an unfinished span.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0d6d0fc. Configure here.

…g-span guard

Split the combined `!ttidSpan || !ttfdEndTimestampSeconds` check so the
existing ok TTFD span guard runs between them, matching the TTID pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
antonis and others added 2 commits July 9, 2026 12:57
…ative API are used

Broadens the existing-span update condition to handle spans with
undefined or ok status, preventing duplicate ui.load.full_display spans
when <TimeToFullDisplay> and reportFullyDisplayed() are both used.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mbined-use test

Broaden the TTID existing-span update condition to match the TTFD fix,
preventing duplicate spans when a component span with ok/undefined
status exists alongside a native timestamp. Add test for combined
<TimeToFullDisplay> component + reportFullyDisplayed() usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate Sentry.reportFullyDisplayed() static API for cross-SDK alignment

1 participant