Skip to content

feat(android): Add queryable getFramesDelay API to SpanFrameMetricsCollector#5248

Draft
antonis wants to merge 3 commits intomainfrom
feat/queryable-frames-delay-api
Draft

feat(android): Add queryable getFramesDelay API to SpanFrameMetricsCollector#5248
antonis wants to merge 3 commits intomainfrom
feat/queryable-frames-delay-api

Conversation

@antonis
Copy link
Copy Markdown
Contributor

@antonis antonis commented Mar 30, 2026

📜 Description

Add a queryable getFramesDelay(startSystemNanos, endSystemNanos) API to SpanFrameMetricsCollector that returns a SentryFramesDelayResult containing the total frame delay (in seconds) and the number of frames contributing to the delay for a given time range.

This mirrors iOS's existing SentryFramesTracker.getFramesDelaySPI and allows external consumers to query frame delay without registering a duplicate frame listener.

Changes:

  • New SentryFramesDelayResult data class with delaySeconds and framesContributingToDelayCount
  • New getFramesDelay() method on SpanFrameMetricsCollector (extracts delay calculation from captureFrameMetrics() into reusable calculateFrameMetrics())
  • New getSpanFrameMetricsCollector() / setSpanFrameMetricsCollector() on SentryAndroidOptions
  • Wired up in AndroidOptionsInitializer

💡 Motivation and Context

The React Native SDK needs to query frame delay for arbitrary time ranges (see getsentry/sentry-react-native#5908). Currently it registers its own RNSentryFrameDelayCollector as a listener on SentryFrameMetricsCollector, duplicating the work already done by SpanFrameMetricsCollector — double listener callbacks, double storage, and redundant computation on the UI thread.

With this API, the RN SDK can delete ~130 lines and replace them with a single getFramesDelay() call, eliminating the overhead.

💚 How did you test it?

  • 9 new unit tests in SpanFrameMetricsCollectorTest covering: disabled state, invalid ranges, zero delay, slow/frozen frame delay, partial frame overlaps at start/end, pending frame delay, and independent querying without an active span
  • All 25 existing + new tests pass

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

#skip-changelog

antonis and others added 2 commits March 30, 2026 12:43
…llector

Expose a getFramesDelay(startNanos, endNanos) method that allows
external consumers (e.g. React Native SDK) to query frame delay for
arbitrary time ranges without registering a duplicate frame listener.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

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


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

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

Generated by 🚫 dangerJS against 9f94607

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 30, 2026

Sentry Build Distribution

App Name App ID Version Configuration Install Page
SDK Size io.sentry.tests.size 8.37.1 (1) release Install Build

Copy link
Copy Markdown
Contributor Author

@antonis antonis left a comment

Choose a reason for hiding this comment

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

I removed the changelog since I guess this is only useful for our own SDKs

@github-actions
Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 321.94 ms 352.89 ms 30.95 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
9ea89e8 308.06 ms 358.16 ms 50.10 ms
b193867 319.59 ms 403.09 ms 83.50 ms
dcc6bbf 382.58 ms 462.13 ms 79.54 ms
d501a7e 307.33 ms 341.94 ms 34.61 ms
22f4345 325.23 ms 454.66 ms 129.43 ms
33a08cc 267.08 ms 340.45 ms 73.37 ms
dba088c 321.78 ms 364.59 ms 42.82 ms
092f017 353.13 ms 433.84 ms 80.71 ms
d501a7e 314.55 ms 343.34 ms 28.79 ms
ce0a49e 532.00 ms 609.96 ms 77.96 ms

App size

Revision Plain With Sentry Diff
9ea89e8 1.58 MiB 2.28 MiB 716.23 KiB
b193867 1.58 MiB 2.19 MiB 620.00 KiB
dcc6bbf 1.58 MiB 2.12 MiB 553.10 KiB
d501a7e 0 B 0 B 0 B
22f4345 1.58 MiB 2.29 MiB 719.83 KiB
33a08cc 1.58 MiB 2.12 MiB 555.28 KiB
dba088c 1.58 MiB 2.13 MiB 558.99 KiB
092f017 0 B 0 B 0 B
d501a7e 0 B 0 B 0 B
ce0a49e 1.58 MiB 2.10 MiB 532.94 KiB

@antonis antonis marked this pull request as ready for review March 30, 2026 11:31
@markushi
Copy link
Copy Markdown
Member

@antonis this looks very promising! Before diving any further: The Android SDK only collects frame metrics when there's a span active (see e.g. onSpanStarted), will the RN side take care of calling those APIs?

@antonis antonis marked this pull request as draft March 30, 2026 12:14
@antonis
Copy link
Copy Markdown
Contributor Author

antonis commented Mar 30, 2026

The Android SDK only collects frame metrics when there's a span active (see e.g. onSpanStarted), will the RN side take care of calling those APIs?

Thank you for raising this @markushi 🙇 This indeed complicates things since the whole point of this PR was to simplify the RN implementation in getsentry/sentry-react-native#5907

I'll convert this back to draft to revist and iterate back. Thank you for having a first look.

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.

2 participants