Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUM-3531 WebView slot cache #1760

Merged
merged 3 commits into from
Apr 12, 2024

Conversation

maxep
Copy link
Member

@maxep maxep commented Apr 3, 2024

What and why?

The player requires that we keep sending webview wireframes throughout the view instance lifecycle.

A WKWebView instance can exist in multiple RUM views, e.g in case of navigation stack. If the webview becomes invisible, we will send a 'remove' mutation resulting in a drop of the webview slot in the player. When the player drops a slot, it also drops the fullsnapshot of the webpage. If the webview ever come back to a visible state, the player won't be able to recover the previous state since it has lost the fullsnapshot.

More details in this RFC.

How?

The easiest solution for the SDKs and the player is to keep sending webview wireframe updates until the webview is deallocated, this way the player will be able to keep the slot's snapshots in memory and to recover the content of the web page if the webview is back to a visible state.

To achieve this, the ViewTreeSnapshotBuilder will keep all webview slots in cache between snapshots. The SnapshotProcessor will use that cache to keep including hidden webviews to the list of wireframes.

The visible webview wireframes are treated as regular wireframes and placed at the right index of the tree.

Review checklist

  • Feature or bugfix MUST have appropriate tests (unit, integration)
  • Make sure each commit and the PR mention the Issue number or JIRA reference
  • Add CHANGELOG entry for user facing changes

Custom CI job configuration (optional)

  • Run unit tests for Core, RUM, Trace, Logs, CR and WVT
  • Run unit tests for Session Replay
  • Run integration tests
  • Run smoke tests
  • Run tests for tools/

@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Apr 3, 2024

Datadog Report

Branch report: maxep/RUM-3531/hide-webview-wireframe
Commit report: 62185d6
Test service: dd-sdk-ios

✅ 0 Failed, 2839 Passed, 0 Skipped, 12m 30.32s Wall Time
🔻 Test Sessions change in coverage: 2 decreased, 12 increased

🔻 Code Coverage Decreases vs Default Branch (2)

  • test DatadogCoreTests iOS 73.25% (-0.7%) - Details
  • test DatadogCoreTests tvOS 79.91% (-0.36%) - Details

@maxep maxep force-pushed the maxep/RUM-3531/hide-webview-wireframe branch 2 times, most recently from 9eb8ddd to 7fca08d Compare April 4, 2024 12:12
@maxep maxep self-assigned this Apr 4, 2024
@maxep maxep marked this pull request as ready for review April 4, 2024 12:45
@maxep maxep requested review from a team as code owners April 4, 2024 12:45
@maxep maxep force-pushed the maxep/RUM-3531/hide-webview-wireframe branch from 54cf77c to 6eff630 Compare April 10, 2024 08:42
Copy link
Member

@maciejburda maciejburda left a comment

Choose a reason for hiding this comment

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

Nice job! 💪

Left some comments. Super nit, but probably worth replacing webview with camel case webView.

Also there's a chance that we could simplify implementation with NSHashTable or NSMapTable

@@ -165,10 +165,7 @@ class WebViewEventReceiverTests: XCTestCase {

func testGivenRUMContextAvailable_whenReceivingWebEvent_itGetsEnrichedWithOtherMobileContextAndWritten() throws {
let core = PassthroughCoreMock(
context: .mockWith(
source: "react-native",
serverTimeOffset: .mockRandom(min: -10, max: 10).rounded()
Copy link
Member

Choose a reason for hiding this comment

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

any reason for dropping the fuzzy offset?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have noticed it to be flaky..

let node = Node(viewAttributes: attributes, wireframesBuilder: builder)
return SpecificElement(subtreeStrategy: .ignore, nodes: [node])
}
}

/// The slot recorded for a `WKWebView`.
internal struct WKWebViewSlot: WebViewSlot {
Copy link
Member

Choose a reason for hiding this comment

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

I think it can be potentially solved with NSHashTable:
https://developer.apple.com/documentation/foundation/nshashtable

NSHashTable<WKWebview>(options: .weakMemory)

Should ease the implementation as it's relying on NSObject's hash internally if I'm not mistaken.

There's also NSMapTable if we want to control keys.

Copy link
Member Author

@maxep maxep Apr 12, 2024

Choose a reason for hiding this comment

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

That's a good call! It indeed simplifies things, thanks for the suggestion.

}

// This test should pass but it doesn't because `WKWebView` apparently leaks.
Copy link
Member

Choose a reason for hiding this comment

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

Can we confirm the behaviour in the real usage?

Copy link
Member Author

Choose a reason for hiding this comment

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

The commented code was showcasing the leak, webkit is probably holding the reference. Now we rely on NSHashTable which states:

The major option is to provide for "weak" references that are removed automatically, but at some indefinite point in the future.

Which is completely acceptable for our use case.

@maxep maxep force-pushed the maxep/RUM-3531/hide-webview-wireframe branch from 238684f to 62185d6 Compare April 12, 2024 12:20
@maxep maxep requested a review from maciejburda April 12, 2024 12:20
Copy link
Member

@maciejburda maciejburda left a comment

Choose a reason for hiding this comment

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

LGTM! 🚀

@maxep maxep merged commit d4b1d4a into feature/webview-replay Apr 12, 2024
8 checks passed
@maxep maxep deleted the maxep/RUM-3531/hide-webview-wireframe branch April 12, 2024 12:59
@maxep maxep mentioned this pull request Apr 15, 2024
8 tasks
@maciejburda maciejburda mentioned this pull request May 7, 2024
8 tasks
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