Skip to content

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

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

feat(android): Add queryable getFramesDelay API to SpanFrameMetricsCollector#5248
antonis wants to merge 5 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 SentryFrameMetricsCollector 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 SentryFrameMetricsCollector with frame buffer, 5-minute auto-pruning, and partial overlap handling
  • Accessible via the existing options.getFrameMetricsCollector().getFramesDelay(...) — no new getters needed

💡 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 internally — double listener callbacks, double storage, and redundant computation on the UI thread.

With this API, the RN SDK can delete RNSentryFrameDelayCollector (~130 lines) and replace it with a single getFramesDelay() call, keeping only the startCollection/stopCollection lifecycle it already manages.

💚 How did you test it?

  • 6 new unit tests in SentryFrameMetricsCollectorTest covering: unavailable state, invalid ranges, zero delay, slow/frozen frame delay, partial frame overlap, and automatic pruning of old frames
  • All 46 existing + new tests pass (30 SentryFrameMetricsCollector + 16 SpanFrameMetricsCollector)

📝 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 99acb6a

@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

github-actions bot commented Mar 30, 2026

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 372.10 ms 438.49 ms 66.39 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
dc4cc7a 361.10 ms 439.53 ms 78.43 ms
6ea4329 309.06 ms 353.48 ms 44.42 ms
b193867 331.08 ms 397.06 ms 65.98 ms
abfcc92 337.38 ms 427.39 ms 90.00 ms
d15471f 342.08 ms 415.44 ms 73.35 ms
d501a7e 348.06 ms 431.42 ms 83.36 ms
6405ec5 310.88 ms 354.56 ms 43.69 ms
22f4345 307.87 ms 354.51 ms 46.64 ms
37ec571 366.04 ms 424.28 ms 58.23 ms
d364ace 411.72 ms 430.81 ms 19.10 ms

App size

Revision Plain With Sentry Diff
dc4cc7a 1.58 MiB 2.19 MiB 619.28 KiB
6ea4329 1.58 MiB 2.29 MiB 719.82 KiB
b193867 1.58 MiB 2.19 MiB 620.00 KiB
abfcc92 1.58 MiB 2.13 MiB 557.31 KiB
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
d501a7e 0 B 0 B 0 B
6405ec5 1.58 MiB 2.12 MiB 552.23 KiB
22f4345 1.58 MiB 2.29 MiB 719.83 KiB
37ec571 0 B 0 B 0 B
d364ace 1.58 MiB 2.11 MiB 539.75 KiB

Previous results on branch: feat/queryable-frames-delay-api

Startup times

Revision Plain With Sentry Diff
3603793 321.94 ms 352.89 ms 30.95 ms

App size

Revision Plain With Sentry Diff
3603793 0 B 0 B 0 B

@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.

@markushi
Copy link
Copy Markdown
Member

@antonis I just had another look and I think if we have two options here:

  1. Access the APIs on a different level
    Instead of using SpanFrameMetricsCollector we could use the underlying SentryFrameMetricsCollector directly and add a new getFramesDelay(final long startSystemNanos, final long endSystemNanos) method there.

  2. Create virtual spans
    Use SpanFrameMetricsCollector but have a single "virtual" RN span which starts / stops whenever any span is running on the RN side.

I think 1. should be simpler and cleaner to implement, so I'd go for that.

@antonis
Copy link
Copy Markdown
Contributor Author

antonis commented Mar 31, 2026

  1. Access the APIs on a different level
    Instead of using SpanFrameMetricsCollector we could use the underlying SentryFrameMetricsCollector directly and add a new getFramesDelay(final long startSystemNanos, final long endSystemNanos) method there.

Thank you for looking into this @markushi 🙇 That makes sense 👍 I'll iterate on this.

antonis and others added 2 commits March 31, 2026 15:33
Moves the queryable frames delay API from SpanFrameMetricsCollector
to SentryFrameMetricsCollector per review feedback. This avoids
coupling the API to span lifecycle, making it directly usable by
hybrid SDKs via the already-accessible options.getFrameMetricsCollector().

Reverts changes to SpanFrameMetricsCollector, SentryAndroidOptions,
and AndroidOptionsInitializer from the previous approach.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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