Skip to content

Add SR support for embedded content wireframes - #3701

Open
jonathanmos wants to merge 16 commits into
developfrom
feature/flutter-support
Open

Add SR support for embedded content wireframes#3701
jonathanmos wants to merge 16 commits into
developfrom
feature/flutter-support

Conversation

@jonathanmos

@jonathanmos jonathanmos commented Aug 11, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Merges feature/flutter-support into develop, adding support for embedded content wireframes. This is required to support Flutter hybrid views in replays. This PR won't actually be merged until there is a final confirmation from the flutter side that this meets all requirements.

Motivation

What inspired you to submit this pull request?

Additional Notes

Anything else we should know when reviewing?

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)

@datadog-prod-us1-3

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

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 72.82%

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 10615a8 | Docs | Datadog PR Page | Give us feedback!

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.61151% with 60 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.20%. Comparing base (3951995) to head (10615a8).
⚠️ Report is 4 commits behind head on develop.

Files with missing lines Patch % Lines
...droid/sessionreplay/_SessionReplayInternalProxy.kt 60.98% 2 Missing and 14 partials ⚠️
...eplay/internal/embedded/EmbeddedContentReceiver.kt 81.82% 5 Missing and 3 partials ⚠️
...ernal/recorder/mapper/EmbeddedContentViewMapper.kt 89.87% 4 Missing and 4 partials ⚠️
...oid/sessionreplay/internal/SessionReplayFeature.kt 86.96% 2 Missing and 4 partials ⚠️
...y/internal/embedded/EmbeddedContentSlotRegistry.kt 83.33% 0 Missing and 5 partials ⚠️
...ssionreplay/internal/processor/MutationResolver.kt 88.89% 2 Missing and 2 partials ⚠️
...sessionreplay/internal/processor/WireframeUtils.kt 66.67% 0 Missing and 3 partials ⚠️
...essionreplay/internal/recorder/SnapshotProducer.kt 50.00% 0 Missing and 2 partials ⚠️
...ssionreplay/internal/recorder/TreeViewTraversal.kt 81.82% 1 Missing and 1 partial ⚠️
...droid/sessionreplay/internal/utils/WireframeExt.kt 33.33% 2 Missing ⚠️
... and 4 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3701      +/-   ##
===========================================
- Coverage    73.51%   73.20%   -0.31%     
===========================================
  Files          999     1004       +5     
  Lines        36570    36928     +358     
  Branches      6183     6428     +245     
===========================================
+ Hits         26884    27033     +149     
- Misses        7980     8046      +66     
- Partials      1706     1849     +143     
Files with missing lines Coverage Δ
.../sessionreplay/internal/DefaultRecorderProvider.kt 94.44% <100.00%> (+0.74%) ⬆️
...sionreplay/internal/SessionReplayRecordCallback.kt 100.00% <100.00%> (ø)
...replay/internal/SessionReplayRumContextProvider.kt 94.12% <100.00%> (+1.81%) ⬆️
...id/sessionreplay/internal/processor/BoundsUtils.kt 70.83% <100.00%> (+2.65%) ⬆️
...onreplay/internal/processor/HeatmapWireframeExt.kt 100.00% <100.00%> (ø)
...ssionreplay/internal/processor/MobileSegmentExt.kt 100.00% <100.00%> (ø)
...replay/internal/processor/RecordedDataProcessor.kt 96.25% <100.00%> (-1.48%) ⬇️
...sionreplay/internal/processor/ResourceProcessor.kt 100.00% <100.00%> (ø)
...nreplay/internal/recorder/SessionReplayRecorder.kt 94.55% <100.00%> (+3.76%) ⬆️
...nreplay/internal/recorder/ViewOnDrawInterceptor.kt 88.89% <100.00%> (+0.65%) ⬆️
... and 16 more

... and 111 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jonathanmos
jonathanmos marked this pull request as ready for review August 11, 2026 09:36
@jonathanmos
jonathanmos requested review from a team as code owners August 11, 2026 09:36
@jonathanmos jonathanmos changed the title Merge feature/flutter-support into develop Add SR support for embedded content wireframes Aug 11, 2026

@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: 10615a8e70

ℹ️ 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 +35 to +38
"slotId": {
"type": "string",
"description": "Unique ID of the slot that generated this record.",
"readOnly": true

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 Preserve the existing record constructors

Adding this optional generated property changes MobileFullSnapshotRecord from the JVM constructor (Long, Data) to (Long, Data, String?); the analogous change in incremental-snapshot-record-schema.json also removes the existing two-argument MobileIncrementalSnapshotRecord constructor. Kotlin default arguments do not retain those old JVM signatures, so an already-compiled library that constructs either public model will fail with NoSuchMethodError when resolved against this SDK version. Keep binary-compatible two-argument overloads or secondary constructors while adding slotId.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We don’t guarantee binary compatibility for the generated Session Replay models, including record and wireframe types. Therefore, preserving the previous JVM constructors is not required for this change.

is MobileSegment.Wireframe.TextWireframe -> this.hasOpaqueBackground()
is MobileSegment.Wireframe.PlaceholderWireframe -> true
is MobileSegment.Wireframe.WebviewWireframe -> true
is MobileSegment.Wireframe.EmbeddedContentWireframe -> this.isVisible != false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Respect transparent embedded host views

When an embedded host has partial or zero alpha, or a translucent background, the mapper carries that opacity in its shape style but this branch still treats the wireframe as fully opaque solely because it is visible. NodeFlattener consequently removes any fully covered native wireframes underneath, so transparent portions of the embedded renderer cannot be reconstructed in the replay. Determine coverage from the host opacity/shape style, or conservatively treat the embedded wireframe as non-opaque when opacity is unknown.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Transparent Flutter hosts appear to be a valid use case, but I don’t want to block this PR. I’ll open a follow-up to address this separately.

) : ResourceProcessor {

override fun process(identifier: String, data: ByteArray, mimeType: String?) {
if (!resourceDataStoreManager.markResourceAsSentIfNew(identifier)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark embedded resources only after persistence succeeds

For the new embedded-resource path, this marks and persists the identifier as sent before SessionReplayResourcesWriter attempts to store the bytes. That writer ignores the Boolean result of EventBatchWriter.write and can also no-op if its feature disappears, so if the first write is rejected during a transient storage failure or shutdown race, every later submission with the same identifier is suppressed and replay wireframes permanently reference a missing resource. Mark the identifier only after a successful storage write, or remove it again when persistence fails.

Useful? React with 👍 / 👎.

@jonathanmos jonathanmos Aug 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This matches the existing native Session Replay resource flow, which also marks resources before writing them. Fixing it would require changing the async writer contract, so I’d handle this in a separate pr

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.

4 participants