-
Notifications
You must be signed in to change notification settings - Fork 50
[RUM-11630] Support SVG in Session Replay #985
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
base: develop
Are you sure you want to change the base?
[RUM-11630] Support SVG in Session Replay #985
Conversation
9a73098
to
1a4f6ec
Compare
b539a74
to
7228edb
Compare
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/libraries/react-native-svg/constants.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/libraries/react-native-svg/constants.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work 💯 the code looks good to me, and is very well documented, thank you! 🙌
I've left a few comments, some are minor nits and a couple are more important points to consider.
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
packages/react-native-babel-plugin/src/cli/generate-sr-assets.ts
Outdated
Show resolved
Hide resolved
4e46b59
to
80c0caf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great. thanks for the update!
3877d16
to
1786b82
Compare
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
let viewId = context.ids.nodeID(view: view, nodeRecorder: self) | ||
let subView = view.subviews[0] | ||
|
||
if let attrs = view.value(forKey: "attributes") as? [String: String] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let attrs = view.value(forKey: "attributes") as? [String: String] { | |
guard let attrs = view.value(forKey: "attributes") as? [String: String] else { | |
return nil | |
} |
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift
Outdated
Show resolved
Hide resolved
imagePrivacyLevel: context.recorder.imagePrivacy | ||
) | ||
|
||
let element = SessionReplaySpecificElement(subtreeStrategy: .ignore, nodes: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could add a comment explaining why we ignore the children
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
The base branch was changed.
- Wrap identified SVG nodes with a `SessionReplayView.Privacy` view, so we can pass extra information to the native side (e.g., `width`, `height`, `hash`, ....)
- Add `sessionReplay` option to the plugin, allowing SVG tracking to be enabled or disabled.
- Add a new session replay mapper targeting SVG views
- Add new session replay node recorder targeting SVG views
- iOS 2.30.2 - Android 2.26.2
- The code now searches within the file itself for the variables used for width and height and sets those as static values. - If the variables come from outside, this work is then handled in the native layer by using the wireframe's data to fill those values.
…es for clarity and consistency
…nsform properties from style objects
8a7ad2e
to
507b67c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Thanks for addressing my comments. From my side, the only important change left is to list the 3rd party libraries we have added with these changes. Other than that I think we are good to go 💯
packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift
Outdated
Show resolved
Hide resolved
packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift
Outdated
Show resolved
Hide resolved
try { | ||
mergeSvgAssets(assetsDir); | ||
} catch (error) { | ||
console.warn('[SessionReplayAggregator] merge failed:', error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ultra-nit:
console.warn('[SessionReplayAggregator] merge failed:', error); | |
console.warn('[SessionReplayAssetBundler] SVGs merge failed:', error); |
- Ensure assets directory in Session Replay package is cleaned up when `yarn prepare` is ran so no unwanted files get packed
What does this PR do?
This PR adds support for tracking SVG images in React Native Session Replay.
This PR is composed of 3 main components that work together to create a workflow that enables SVGs to be captured in Session Replay:
@datadog/mobile-react-native-babel-plugin
package)@datadog/mobile-react-native-session-replay
package)@datadog/mobile-react-native-babel-plugin
package)Babel Plugin
The Babel plugin feature is the core of this PR, containing most of the complexity. Its main responsibilities are to:
What kind of SVGs does the plugin handle?
To correctly identify and extract SVGs in a user's codebase, the plugin differentiates between three types of SVGs and handles each appropriately:
1. Inline SVGs
SVGs built directly in the codebase using elements from the react-native-svg library (e.g.,
<Svg>
,<Path>
,<Circle>
). These require the most complex logic for full extraction and transformation.Example:
2. External SVGs (Local)
SVGs loaded from the user's filesystem. These are typically already in web-compliant format, but the plugin needs to properly identify them in the user's code since they can be named anything.
Example:
3. External SVGs (Remote)
SVGs loaded from external servers using the SvgUri component from react-native-svg.
Example:
What kind of SVGs do we still need to support?
The plugin currently handles direct usage of
react-native-svg
elements and loading SVG files directly. The main area for future expansion is adding support for popular SVG libraries built on top ofreact-native-svg
, such as:The groundwork to support these libraries is already in place, as the logic should be similar to handling local SVGs (treating library-generated SVGs as specialized local SVG cases).
Areas of Improvement
Some areas for future enhancement that didn't make it into this first release:
All of these improvements are feasible with sufficient time allocation.
Metro Plugin
The Metro plugin (
withSessionReplayAssetBundler
) integrates with React Native's Metro bundler to automatically aggregate SVG assets during development and production builds.Key responsibilities:
assets.bin
) with an accompanying JSON index (assets.json
) for efficient native lookupbundle_build_done
andtransformer_load_done
How it works:
The Metro plugin wraps the Metro config's reporter and watches for new .svg files in the
packages/react-native-session-replay/assets/ directory. When new SVG assets are detected (either from the Babel plugin or the CLI utility), it packs them into:
assets.bin
- A binary file containing all SVG data concatenated togetherassets.json
- An index mapping SVG IDs to their byte offset and length in the binary fileThis approach allows the native SDKs to efficiently load SVG assets by reading specific byte ranges from a single file rather than managing hundreds of individual files.
CLI Utility
The CLI utility (
npx datadog-generate-sr-assets
) provides a way to pre-generate all Session Replay SVG assets before native builds.Key responsibilities:
When to use it:
The CLI utility should be run after installing dependencies and before building iOS/Android apps:
After installing dependencies
yarn install
Generate SVG assets
npx datadog-generate-sr-assets
Then build native apps
cd ios && pod install && cd ..
This ensures that native asset references are available during the build process, particularly important for iOS where the
assets need to be included in the Xcode project.
What it does:
.js
,.jsx
,.ts
, and.tsx
files (excludingnode_modules
, test files, etc.)How does this all work together?
Here's the complete workflow for integrating SVG support in your React Native app:
1. Setup the Babel Plugin
Configure the Babel plugin in your
babel.config.js
to enable SVG tracking:2. Setup the Metro Plugin
Configure the Metro plugin in your
metro.config.js
to enable asset bundling:3. Generate Assets Before Native Builds
Run the CLI utility after installing dependencies and before building native apps:
Install dependencies
yarn install
Generate Session Replay SVG assets
npx datadog-generate-sr-assets
Build iOS (if needed)
cd ios && pod install && cd ..
Now you can run your app
yarn ios
or
yarn android
4. Development Workflow
During development, the Metro plugin automatically handles new SVG assets created by the Babel plugin:
react-native-svg
This ensures that SVGs are seamlessly captured in Session Replay without requiring manual asset management.