Skip to content

PANA-8412: Order Flutter records after their placeholder wireframe - #3741

Open
JuanNaranjoDD wants to merge 1 commit into
feature/flutter-supportfrom
juan.naranjo/hybrid-session-replay-flutter
Open

PANA-8412: Order Flutter records after their placeholder wireframe#3741
JuanNaranjoDD wants to merge 1 commit into
feature/flutter-supportfrom
juan.naranjo/hybrid-session-replay-flutter

Conversation

@JuanNaranjoDD

@JuanNaranjoDD JuanNaranjoDD commented Aug 20, 2026

Copy link
Copy Markdown

What does this PR do?

Makes the Android SDK order embedded Flutter records after the placeholder wireframe they composite into.

  • EmbeddedContentSlotRegistry records, per RUM view, the timestamp at which each slot's placeholder was written, and notifies listeners the first time a slot's placeholder appears in a view.
  • EmbeddedRecordTimeline (new) decides whether a batch is covered by a placeholder in its own view, and computes the shift needed to land it after that placeholder. The shift is derived from the earliest record in the batch set and applied uniformly, so a multi-frame gesture keeps its internal spacing instead of collapsing into a single instant.
  • EmbeddedContentReceiver holds batches that no placeholder covers yet and writes them on release. The hold is bounded twice over — 20 batches per slot, 10 slots — and what the bounds displace is written unshifted rather than dropped: a mis-ordered record beats a missing one.
  • RecordedDataProcessor reports placeholders only after the enriched record is successfully written, so nothing is ever shifted past a placeholder that never landed.
  • SessionReplayRecorder gains an on-demand capture path (OnDemandCaptureListener.captureNow()) that bypasses the draw debouncer, used on a RUM view change with marked slots and when a batch arrives with no placeholder to cover it.

Motivation

The Session Replay player composites a Flutter record into a placeholder but requires that placeholder to be already present in the same segment, and records replay in timestamp order per view. The Android recorder is draw-driven, while Flutter renders to its own surface — so a Flutter view over an idle host produces records with no placeholder ahead of them, and the player does not know how to render it.

This is the Android half of the hybrid Session Replay support already merged for iOS in dd-sdk-flutter.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)

@JuanNaranjoDD
JuanNaranjoDD requested review from a team as code owners August 20, 2026 09:43
@datadog-prod-us1-3

datadog-prod-us1-3 Bot commented Aug 20, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🔄 Datadog retried 1 test - 1 passed on retry View in Datadog

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 5b41f07 | Docs | View more details | Give us feedback!

@jonathanmos

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b41f07e0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +328 to +330
ViewOnDrawInterceptor.CaptureRequestResult.CAPTURED -> {
captureRequested.set(false)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep capture pending until its placeholder persists

When the queued snapshot is later rejected by RecordWriter or contains no visible wireframe for the requested slot, CAPTURED still clears this flag even though RecordedDataProcessor deliberately does not register a placeholder. The embedded batch therefore remains held, and subsequent batches for that slot do not request another capture because its pending queue is already nonempty; on the idle native host this path is intended to support, the records can remain stuck indefinitely or eventually be emitted misordered through eviction. The request needs to remain/re-arm until the requested placeholder is successfully persisted.

Useful? React with 👍 / 👎.

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