Repository navigation
Conversation
|
✅ All CI checks and tests passed. 🎉 All green!🧪 All tests passed 🔗 Commit SHA: 3cd6690 | Docs | View more details | Give us feedback! |
Bump the iOS SDK to 3.17.0, which adds serialID to FlagAssignment, and send the value through the React Native bridge. The iOS bridge converts FlagAssignment to an NSDictionary with a fixed key list, and converts it back for exposure tracking. The key list omitted the serial ID, so the value was dropped in both directions. The code still compiled, so nothing reported the loss. The serial ID crosses the bridge as a string, for parity with Android, which sends a string because React Native converts integers to Double. An assignment with no serial ID omits the key instead of sending NSNull. The reader accepts a string only. NSNumber and Bool bridge into each other on Apple platforms, so a numeric branch would read a boolean true as serial ID 1. Int(String) rejects that. A malformed serial ID yields no serial ID and never rejects the assignment, because that would drop the exposure event for the whole flag.
705ae26 to
9cf32f3
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The implementation and coverage are complete, with only a non-blocking wording correction identified.
1 open finding
What changed in this PR
Adds iOS split serial IDs to feature-flag exposure events.
Changes:
- Serializes and restores
serialIdacross the iOS bridge. - Adds coverage for valid, absent, zero, malformed, and round-tripped IDs.
- Upgrades Datadog iOS dependencies to 3.17.0.
| File | Description |
|---|---|
packages/core/ios/Sources/DdFlagsImplementation.swift |
Bridges serial IDs as strings. |
packages/core/ios/Tests/DdFlagsTests.swift |
Tests serial-ID conversion behavior. |
packages/core/DatadogSDKReactNative.podspec |
Upgrades core iOS SDK pods. |
packages/react-native-webview/DatadogSDKReactNativeWebView.podspec |
Upgrades WebView pods. |
packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec |
Upgrades Session Replay pod. |
example/ios/Podfile.lock |
Locks upgraded dependencies. |
example-new-architecture/ios/Podfile.lock |
Locks upgraded dependencies. |
benchmarks/ios/Podfile.lock |
Locks upgraded dependencies. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
sameerank
left a comment
There was a problem hiding this comment.
The serial-ID forwarding changes look good! Codex found a couple issues on the SDK 3.17.0 upgrade that might need addressing. Please double check if valid
| s.dependency 'DatadogTrace', '3.17.0' | ||
| s.dependency 'DatadogRUM', '3.17.0' | ||
| s.dependency 'DatadogCrashReporting', '3.17.0' | ||
| s.dependency 'DatadogFlags', '3.17.0' |
There was a problem hiding this comment.
[P1] Handle the new initialization timeout error before upgrading DatadogFlags
SDK 3.17.0 adds FlagsError.initializationTimedOut, but the error switch in DdFlagsImplementation.swift still handles only the previous four cases. This makes the switch non-exhaustive and breaks iOS compilation, regardless of whether feature flags are enabled. I reproduced the compiler error against the 3.17.0 enum. Please add a JavaScript error mapping for .initializationTimedOut and a corresponding test alongside this dependency bump.
| s.dependency 'DatadogRUM', '3.16.0' | ||
| s.dependency 'DatadogCrashReporting', '3.16.0' | ||
| s.dependency 'DatadogFlags', '3.16.0' | ||
| s.dependency 'DatadogCore', '3.17.0' |
There was a problem hiding this comment.
[P1] Account for the minimum OS version increase in SDK 3.17.0
SDK 3.17.0 raises the minimum supported iOS and tvOS versions from 12.0 to 15.0, while the React Native podspecs still declare 12.0. Applications targeting versions 12–14 will therefore fail CocoaPods dependency resolution after upgrading. The example’s 15.1 deployment target masks this incompatibility. Please preserve the existing minimum through a compatible native SDK release, or explicitly handle and document the platform-support change, including updating the podspec deployment targets.
The DatadogCore 3.17.0 podspec explicitly sets both iOS and tvOS deployment targets to 15.0.
This also applies to the Session Replay and WebView podspecs, which retain the older deployment targets.
There was a problem hiding this comment.
Hmm, this is a question for @DataDog/rum-mobile I think. Is it safe to raise the minimum?
Hi @danyal002, I still have to properly review the whole PR, but just be aware that the bump of the iOS SDK to 3.17.0 is blocked at the moment, as it includes breaking changes (it drops support for iOS 12, 13 and 14). The plan is to do a one-off breaking v3 release in the next few weeks that will include that bump as well as the support for SPM (dropping Cocoapods). Just so you are aware that this PR won't be able to be merged until that happens so you can plan accordingly. |
@sbarrio Thanks! That makes sense. I'll put this PR back in draft and check back in a few weeks. |

What does this PR do?
The iOS bridge now sends the split serial ID on feature flag exposure events.
packages/core/DatadogSDKReactNative.podspecand 2 other podspecs3.17.0.example/ios/Podfile.lock,example-new-architecture/ios/Podfile.lock,benchmarks/ios/Podfile.lock3.17.0.packages/core/ios/Sources/DdFlagsImplementation.swiftserialIdin both bridge directions. Maps the newinitializationTimedOuterror.packages/core/ios/Tests/DdFlagsTests.swiftpackages/core/ios/Tests/MockDatadogCore.swiftand 3 other test mocksremoteConfiguration.packages/internal-testing-tools/ios/Sources/DatadogCoreProxy.swiftremoteConfigurationto the wrapped core.packages/core/ios/Tests/DdTraceTests.swifttestTracingConcurrently.iOS SDK
3.17.0addsserialIDtoFlagAssignment, reads it on the exposure event, and includes it in the exposure deduplication cache. The React Native bridge supplies the value.The bridge converts a
FlagAssignmentto anNSDictionarywith a fixed key list, and converts the dictionary back for exposure tracking. The key list omitted the serial ID. The value was therefore dropped in both directions, and the code still compiled.The serial ID crosses the bridge as a string. Android does the same, because React Native converts integers to
Double. An assignment with no serial ID omits the key instead of sendingNSNull.The reader accepts a string only.
NSNumberandBoolbridge into each other on Apple platforms, so a numeric branch would read a booleantrueas serial ID1.Int(String)rejects a boolean, and rejects any other value that is not an integer. A malformed serial ID yields no serial ID. It never rejects the assignment, because that would drop the exposure event for the whole flag.Serial IDs are zero-based for each org.
0is therefore a real value, and three tests pin it.iOS SDK
3.17.0also changes two APIs that the bridge and its tests depend on.FlagsErroraddsinitializationTimedOut, and the bridge rejects it with the error codeINITIALIZATION_TIMED_OUT.DatadogCoreProtocoladdsremoteConfiguration. The test mocks returnnil, asNOPDatadogCoredoes.DatadogCoreProxyforwards the value from the core that it wraps.Motivation
The UFC compiler rewrites a holdout into an ordinary allocation before any SDK reads the flag configuration. An exposure event therefore records no holdout. The split serial ID is the only link back to it. An exposure event without the serial ID cannot be resolved to a holdout.
Additional Notes
Testing. The new tests cover the string form, serial ID
0in both directions, an absent serial ID omitting the key, four malformed values, a round trip through both conversions, and theINITIALIZATION_TIMED_OUTerror code. TheDatadogSDKReactNativeandDatadogSDKReactNativeSessionReplaytest schemes pass on an iOS simulator.testTracingConcurrentlyfailed intermittently ondevelop, for example on PR #1409. Its concurrent iterations shared one variable for the span ID. Another iteration could overwrite the value betweenstartSpanandfinishSpan, so one span stayed open. Each iteration now keeps its own span ID. The test passed 100 consecutive runs on a simulator.Risks. The iOS SDK bump from
3.16.0to3.17.0carries every other change in that release.The bridge ignores a numeric serial ID, whereas the Android bridge accepts a string or a number. Every JavaScript producer sends a string: the native snapshot, the OpenFeature offline adapter, and the core precomputed decoder. No current caller therefore depends on the numeric shape. A test pins the numeric case as ignored, so the difference is deliberate and visible.
The OpenFeature offline path already sends the serial ID. PR #1409 adds it to the core client's offline path. Android already sends the serial ID.