-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add session replay support for react native #357
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: main
Are you sure you want to change the base?
feat: add session replay support for react native #357
Conversation
3e1346c to
8b1fb92
Compare
sdk/@launchdarkly/react-native-ld-session-replay/android/src/main/AndroidManifest.xml
Dismissed
Show dismissed
Hide dismissed
...launchdarkly/react-native-ld-session-replay/example/android/app/src/main/AndroidManifest.xml
Dismissed
Show dismissed
Hide dismissed
...native-ld-session-replay/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
Dismissed
Show dismissed
Hide dismissed
...native-ld-session-replay/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
Dismissed
Show dismissed
Hide dismissed
...-replay/android/src/main/java/com/sessionreplayreactnative/SessionReplayReactNativeModule.kt
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayReactNative.mm
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayReactNative.mm
Show resolved
Hide resolved
…n start rejection - Implemented `configure` and `startSessionReplay` methods in `SessionReplayReactNativeModule.kt` to handle session replay functionality. - Both methods currently reject promises with a "NOT_SUPPORTED" message, indicating that session replay is not yet supported on Android, while iOS support is available.
…eplay configuration - Removed unnecessary console log statements from `configureSessionReplay` and `SessionReplayPluginAdapter`. - Enhanced error handling by silencing configuration failure messages, allowing the native module to manage errors.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Outdated
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
- Changed plugin name from '@launchdarkly/observability-react-native' to 'session-replay-react-native'. - Removed try/catch block around async session replay configuration to simplify error handling, allowing the native module to manage errors directly.
- Changed context declaration to be optional and added logging for context creation failure. - Updated the start method to guard against nil context, ensuring session replay does not start without a valid context.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayReactNative.mm
Outdated
Show resolved
Hide resolved
- Added a stop method to the Client class to disable session replay via LDReplay.shared. - Updated the stop method in SessionReplayAdapter to call the new stop method on the client, ensuring proper session replay termination.
- Updated the stop method in SessionReplayAdapter to mutate LDReplay.shared.isEnabled on the main actor, ensuring thread safety when stopping session replay.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Outdated
Show resolved
Hide resolved
- Updated the startSessionReplay method in SessionReplayReactNative to handle success and failure cases using a completion block. - Modified the start method in SessionReplayAdapter to accept a completion handler, providing better error reporting when the client is not initialized or when session replay fails to start. - Improved error logging for session replay initialization issues, ensuring clearer diagnostics for developers.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/SessionReplayReactNative.podspec
Show resolved
Hide resolved
…yAdapter - Eliminated the sessionReplayOptions variable from SessionReplayAdapter as it was not utilized, streamlining the code and improving clarity.
…EADME - Updated the README to include steps for configuring the LaunchDarkly mobile key using environment variables or direct replacement in the code. - Added .env files to .gitignore to prevent committing sensitive information. - Modified App.tsx to utilize the mobile key from an environment variable, enhancing security and flexibility.
- Updated the glob pattern in the lefthook.yml file to remove unnecessary spaces, ensuring proper file matching for pre-commit hooks.
- Eliminated the NSLog statement that logged the mobile key and options during configuration in SessionReplayReactNative, reducing unnecessary console output and improving code cleanliness.
- Removed commented-out code related to the Client initialization and SessionReplay options, enhancing code readability and maintainability.
- Implemented stopSessionReplay method in both iOS and Android modules to allow stopping of session replay. - Updated TypeScript interface to include stopSessionReplay, enhancing the API for session management. - Added error handling for the stopSessionReplay method on Android, indicating that session replay is not yet supported.
- Updated setMobileKey method to accept optional options dictionary, improving flexibility in configuration. - Modified sessionReplayOptionsFrom method to handle nil dictionary, providing default values for session replay options, ensuring robust behavior when no options are provided.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
- Enhanced error handling in the SessionReplayPluginAdapter by logging initialization failures to the console, providing clearer diagnostics for developers when session replay fails to start.
- Added logic to close the previous LDClient instance before initializing a new one in setMobileKey and start methods, ensuring proper resource management. - Implemented a close method in the Client class to handle the shutdown of LDClient, preventing potential memory leaks and ensuring clean termination of network connections and background tasks.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Outdated
Show resolved
Hide resolved
- Introduced synchronization mechanisms to prevent concurrent start calls and manage the LDClient lifecycle more effectively. - Added flags to handle pending close requests when the client is starting, ensuring proper resource management and preventing potential memory leaks. - Enhanced error logging during session replay initialization to provide clearer diagnostics for developers.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Outdated
Show resolved
Hide resolved
- Refactored the handling of pending close requests for LDClient to ensure proper resource management when session replay is starting. - Introduced a dedicated method to close the pending client, enhancing clarity and maintaining the integrity of the session replay lifecycle. - Improved logging to provide better diagnostics when a close is requested during initialization.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
…tialization - Added logic to clean up the LDClient singleton if the client is deallocated while starting, preventing resource leaks. - Improved error handling by providing a completion callback with a message when the client is replaced during initialization. - Enhanced logging to indicate when the LDClient is closed due to client replacement, improving diagnostics for developers.
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
sdk/@launchdarkly/react-native-ld-session-replay/ios/SessionReplayAdapter.swift
Show resolved
Hide resolved
- Added trimming and validation for the mobile key in both SessionReplayAdapter and SessionReplayReactNative to ensure it is non-empty before proceeding with initialization. - Enhanced error handling to reject invalid mobile keys with appropriate messages, improving user feedback during configuration. - Updated the TypeScript interface to enforce mobile key validation, ensuring robust session replay setup.
- Eliminated the unused Hook type import from the SessionReplayPluginAdapter, streamlining the code and improving clarity. - Cleaned up the codebase by removing the getHooks method, which was not utilized, enhancing maintainability.
- Introduced a static method to handle the cleanup of the LDClient singleton when the client is deallocated during initialization, preventing inconsistent states. - Enhanced the error handling logic to ensure proper closure of the LDClient and improved logging for diagnostics when a client is replaced.
- Removed the static method for closing the LDClient singleton when a client is deallocated during initialization to avoid tearing down a new client's session replay. - Updated comments to clarify the handling of client replacement scenarios, ensuring that the LDClient remains consistent and functional during initialization.
| # runner: node | ||
| # | ||
| # - script: "hello.go" | ||
| # runner: go run |
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.
Root lefthook.yml is entirely commented-out dead code
Low Severity
The root lefthook.yml consists entirely of commented-out example configuration (42 lines of comments). It provides no actual functionality. The package has its own working lefthook configuration at sdk/@launchdarkly/react-native-ld-session-replay/lefthook.yml. This file should either be removed or contain actual configuration.
- Added detailed usage examples for integrating the session replay plugin with the LaunchDarkly React Native client. - Included both the declarative and imperative API approaches for configuring and starting session replay, enhancing documentation clarity for developers.
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.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| if shouldClosePending, let ldClient = LDClient.get() { | ||
| self.closePendingClient(ldClient: ldClient) | ||
| } | ||
| completion(false, 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.
Timeout error handling is unreachable dead code
Medium Severity
The timeout error handling at line 204 checks self.config.startOnline == true, but config.startOnline is hardcoded to false at line 146. This condition can never be satisfied, so even when timedOut is true, the code falls through to the else branch and reports success. Session replay initialization timeouts are silently ignored and reported as successful starts.
Additional Locations (1)
| set { | ||
| clientStateQueue.async(flags: .barrier) { [weak self] in self?._clientState = newValue } | ||
| } | ||
| } |
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.
Race condition from async setter with sync getter
Medium Severity
The clientState computed property uses async(flags: .barrier) for the setter but sync for the getter. A write followed immediately by a read may return the stale value because the async write hasn't completed yet. This affects the check at line 38 in setMobileKey where clientState == .started may read outdated state, causing the previous client not to be closed properly.
Additional Locations (1)
| # runner: node | ||
| # | ||
| # - script: "hello.go" | ||
| # runner: go run |
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.
Entirely commented-out configuration file is dead code
Low Severity
The root lefthook.yml contains only commented-out example configuration with no actual hooks defined. The package already has a working lefthook.yml at sdk/@launchdarkly/react-native-ld-session-replay/lefthook.yml with actual pre-commit hooks. This file serves no purpose and should either be configured or removed.


Summary
Implement support for session replay into react native through swift-observability-sdk
How did you test this change?
e2e testing, example app is provided
Are there any deployment considerations?
it is a front-end package for building mobile apps
Note
Medium Risk
Adds new native iOS code that manages LaunchDarkly’s singleton
LDClientlifecycle and session replay privacy settings; incorrect configuration or lifecycle handling could cause resource leaks or unexpected replay behavior.Overview
Adds a new React Native TurboModule package,
session-replay-react-native, exposingconfigureSessionReplay,startSessionReplay, andstopSessionReplay, plus a LaunchDarklyLDPluginadapter (createSessionReplayPlugin) that auto-initializes replay using the client’smetadata.sdkKey/mobileKey.Implements the iOS native bridge via
SessionReplayAdapterand an Objective-C++ module, wiring intoLaunchDarklyObservability/LaunchDarklySessionReplay, mapping privacy/masking options, and adding lifecycle handling to avoid singletonLDClientleaks and handle stop-during-start. Android is scaffolded but explicitly returnsNOT_SUPPORTEDfor all APIs.Includes a full example app (iOS + Android projects) demonstrating usage, and adds repo/tooling configs (ESLint/Prettier/TypeScript, commitlint + lefthook hooks, turbo tasks, podspec/SPM dependency, docs/license).
Written by Cursor Bugbot for commit 2b990e4. This will update automatically on new commits. Configure here.