Skip to content

Commit 67d8998

Browse files
authored
Merge pull request #312 from flashcatcloud/doc-review/20260825-react-native
docs(rum): correct React Native SDK guidance
2 parents 3d08642 + 90d96cc commit 67d8998

8 files changed

Lines changed: 232 additions & 46 deletions

File tree

en/rum/sdk/react-native/advanced-config.mdx

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: "Configure sampling, tracking consent, event filtering, distributed
44
keywords: ["RUM", "React Native SDK", "advanced configuration", "sampling", "tracking consent", "source map", "native crash", "symbolication", "dSYM", "mapping"]
55
---
66

7-
This page covers the advanced options of the React Native SDK. All options are set as properties on a `DdSdkReactNativeConfiguration` instance before calling `DdSdkReactNative.initialize(config)`.
7+
This page covers the advanced options of the React Native SDK. All eight constructor arguments are read-only; arguments 7 and 8 are the less obvious `trackingConsent` and `useAccessibilityLabel` options. Set the remaining advanced options as instance properties. Complete all configuration before calling `DdSdkReactNative.initialize(config)`.
88

99
## Sampling
1010

@@ -14,6 +14,8 @@ config.resourceTracingSamplingRate = 20; // Distributed tracing sampling rate on
1414
config.telemetrySampleRate = 20; // SDK internal telemetry sampling rate, default 20
1515
```
1616

17+
All three sampling rates accept values from `0` to `100`. `0` samples nothing and `100` samples everything.
18+
1719
## Tracking consent
1820

1921
`TrackingConsent` controls whether data is collected and reported, for compliance requirements such as GDPR:
@@ -30,6 +32,7 @@ const config = new DdSdkReactNativeConfiguration(
3032
'<CLIENT_TOKEN>', 'production', '<APPLICATION_ID>',
3133
true, true, true,
3234
TrackingConsent.PENDING,
35+
false, // argument 8: do not use accessibilityLabel as the action name
3336
);
3437

3538
// Update after the user grants consent
@@ -46,7 +49,11 @@ config.errorEventMapper = (event) => {
4649
event.message = event.message.replace(/token=[^&\s]+/g, 'token=***');
4750
return event;
4851
};
49-
config.resourceEventMapper = (event) => event; // statusCode, kind, size, and context can be modified
52+
config.resourceEventMapper = (event) => {
53+
// Resources only allow context changes; return null to drop the event
54+
event.context = { ...event.context, sanitized: true };
55+
return event;
56+
};
5057
config.actionEventMapper = (event) => event;
5158
config.logEventMapper = (event) => event;
5259
```
@@ -96,7 +103,41 @@ import { WebView } from '@flashcatcloud/mobile-react-native-webview';
96103
/>
97104
```
98105

99-
`allowedHosts` is the list of hosts allowed to be associated; subdomains are matched. The page loaded in the WebView must already integrate the <a href="/en/rum/sdk/web/sdk-integration">Flashduty Browser SDK</a>. The component is fully compatible with the props of `react-native-webview`.
106+
`allowedHosts` is the list of hosts allowed to be associated; subdomains are matched. The page loaded in the WebView must already integrate the <a href="/en/rum/sdk/web/sdk-integration">Flashduty Browser SDK</a>.
107+
108+
The component passes through most `react-native-webview` props, but it controls the following props to inject the RUM bridge:
109+
110+
- `nativeConfig`
111+
- `onMessage`
112+
- `injectedJavaScript`
113+
- `injectedJavaScriptBeforeContentLoaded`
114+
115+
You can still provide your own `onMessage` handler and injected scripts: the component forwards non-RUM messages to your handler and executes the scripts after wrapping them. A custom `nativeConfig` is overwritten. Set `logUserCodeErrors={true}` to record errors from injected user code as logs; it defaults to `false`. Because Logs currently works only on Android, these errors are not reported from iOS.
116+
117+
```tsx
118+
<WebView
119+
source={{ uri: 'https://myapp.example' }}
120+
allowedHosts={['myapp.example']}
121+
logUserCodeErrors={true}
122+
onMessage={(event) => console.log(event.nativeEvent.data)}
123+
/>
124+
```
125+
126+
## Reporting through a proxy
127+
128+
`proxyConfig` supports HTTP, HTTPS, and SOCKS proxies. HTTP and HTTPS proxies support Basic Authentication. SOCKS proxies do not support a username or password; the SDK logs a warning and ignores credentials when you provide them.
129+
130+
```typescript
131+
import { ProxyConfiguration, ProxyType } from '@flashcatcloud/mobile-react-native';
132+
133+
config.proxyConfig = new ProxyConfiguration(
134+
ProxyType.HTTPS,
135+
'proxy.example.com',
136+
8443,
137+
'username',
138+
'password',
139+
);
140+
```
100141

101142
## Source map upload
102143

@@ -224,26 +265,32 @@ A dSYM is matched to crash events by the binary's **UUID**, and every release bu
224265
</Tabs>
225266

226267
<Warning>
227-
**Upload symbol files for both platforms separately.** Symbol files are matched by service, and without an explicit `serviceName` Android falls back to the `applicationId` while iOS falls back to the bundle identifier one app becomes two services in the console, and the Android mapping file is never applied to an iOS crash or vice versa. Set `serviceName` explicitly so both platforms agree, and upload from each platform's release pipeline.
268+
**Upload symbol files for both platforms separately.** Symbol files are matched by service, and without an explicit `serviceName` Android falls back to the `applicationId` while iOS falls back to the bundle identifier. If those platform identifiers differ, one app becomes two services in the console, and the Android mapping file is never applied to an iOS crash or vice versa. Set `serviceName` explicitly so both platforms agree, and upload from each platform's release pipeline.
228269
</Warning>
229270

230271
## Other options
231272

232273
| Option | Default | Description |
233274
|------|--------|------|
234-
| `serviceName` | Platform default | **Strongly recommended.** When unset, Android uses `applicationId` and iOS the bundle identifier, splitting the app into two services |
275+
| `serviceName` | Platform default | **Recommended.** When unset, Android uses `applicationId` and iOS the bundle identifier; the app is split into two services when those identifiers differ |
235276
| `nativeCrashReportEnabled` | false | Whether to collect native crashes |
236-
| `version` / `versionSuffix` | App version | Override the reported version / append a suffix; must match the version used for source map upload |
277+
| `version` / `versionSuffix` | App version | Override the reported version / append a suffix; only letters, numbers, `_`, `-`, `:`, `.`, and `/` are preserved, other characters become `_`, and the SDK adds `-` before the suffix; the result must match the source map upload version |
237278
| `verbosity` | undefined | SDK internal log level (`SdkVerbosity.DEBUG` / `INFO` / `WARN` / `ERROR`); use it when troubleshooting the integration |
279+
| `nativeViewTracking` | false | Enable native view tracking for a custom navigation system based on native views |
280+
| `nativeInteractionTracking` | false | Collect user interactions on native screens |
238281
| `trackBackgroundEvents` | false | Whether to collect events while no view is active; enabling it increases the session count |
239-
| `vitalsUpdateFrequency` | `VitalsUpdateFrequency.AVERAGE` | Collection frequency of native mobile vitals; set to `NEVER` to disable |
240-
| `nativeLongTaskThresholdMs` | 200 | Native main-thread long task threshold in milliseconds; `0` or `false` disables it |
241-
| `longTaskThresholdMs` | 0 (disabled) | JS-thread long task threshold in milliseconds; set 100 to 5000 to enable |
282+
| `vitalsUpdateFrequency` | `VitalsUpdateFrequency.AVERAGE` | Native mobile vital frequency: `FREQUENT`, `AVERAGE`, `RARE`, or `NEVER` |
283+
| `nativeLongTaskThresholdMs` | 200 | Native main-thread long task threshold in milliseconds; `0` / `false` disables it, and enabled values are clamped to 100–5000 |
284+
| `longTaskThresholdMs` | 0 (disabled) | JS-thread long task threshold in milliseconds; `0` / `false` disables it, and enabled values are clamped to 100–5000 |
242285
| `trackFrustrations` | true | Whether to derive frustration signals (such as error taps) from user actions |
243286
| `actionNameAttribute` | undefined | Which component prop to use as the name of automatically collected actions (for example `testID`); `dd-action-name` takes precedence |
244-
| `useAccessibilityLabel` | true | Whether to use `accessibilityLabel` as the action name |
287+
| `useAccessibilityLabel` | true | Whether to use `accessibilityLabel` as the action name; read-only constructor argument 8 |
288+
| `bundleLogsWithRum` | true | Whether to correlate Android logs with the current RUM session; Logs is a no-op on iOS |
245289
| `trackNonFatalAnrs` | Platform default | Whether to collect non-fatal ANRs; disabled by default on Android 30+, enabled on Android 29 and below |
246290
| `appHangThreshold` | undefined | iOS App Hang threshold in seconds; unset means disabled |
291+
| `initialResourceThreshold` | 0.1 seconds | Time window after a view starts in which resources are included in Time to Network-Settled (TNS) |
247292
| `trackWatchdogTerminations` | false | Whether to collect iOS watchdog terminations |
248-
| `uploadFrequency` / `batchSize` / `batchProcessingLevel` | `AVERAGE` / `MEDIUM` / `MEDIUM` | Upload frequency, batch size, and batches per upload cycle; trade off freshness against battery |
249-
| `proxyConfig` | undefined | Report through an HTTP / SOCKS proxy |
293+
| `uploadFrequency` | `UploadFrequency.AVERAGE` | Upload frequency: `FREQUENT` (about 1 second), `AVERAGE` (about 5 seconds), or `RARE` (about 10 seconds) |
294+
| `batchSize` | `BatchSize.MEDIUM` | Amount of data per batch: `SMALL`, `MEDIUM`, or `LARGE` |
295+
| `batchProcessingLevel` | `BatchProcessingLevel.MEDIUM` | Batches processed per upload cycle: `LOW` (1), `MEDIUM` (10), or `HIGH` (100) |
296+
| `proxyConfig` | undefined | Report through an HTTP, HTTPS, or SOCKS proxy; SOCKS does not support Basic Authentication |

en/rum/sdk/react-native/compatible.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ JavaScript class names begin with `Dd*` (`DdSdkReactNative`, `DdSdkReactNativeCo
5858
| Logs | `DdLogs` only sends logs on Android; it is a no-op on iOS and sends nothing |
5959
| Static resources | Only requests issued from JavaScript are collected; images, fonts, and other resources loaded by the native networking stack such as `<Image>` are **not collected**, and the console does not show static-resource panels for React Native applications |
6060
| Resource type | Every collected request is recorded as `xhr`, regardless of the response Content-Type |
61-
| Android app launch time | No app launch vital on Android yet; iOS reports cold / warm launch time |
61+
| Android app launch time | The React Native Android bridge does not yet report launch events; iOS reports cold / warm launch time |
6262
| Platform scope | iOS / Android only; React Native Web is not supported |
6363
| Minimum version | `0.1.1` or later is recommended; in `0.1.0` the Android release build fails when `FLASHCAT_API_KEY` is missing |
6464

en/rum/sdk/react-native/data-collection.mdx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Every event carries the following context (collected by the native layer):
2424
- **Device**: device model, OS and version, screen size
2525
- **Session**: `session.id`, sampled by `sessionSamplingRate`
2626
- **Connectivity**: network type (when available)
27-
- **User**: `usr.id` / `usr.name` / `usr.email` set through `DdSdkReactNative.setUser`
27+
- **User**: `usr.id` / `usr.name` / `usr.email` set through `DdSdkReactNative.setUserInfo`
2828
- **Global attributes**: custom fields set through `DdSdkReactNative.setAttributes`
2929

3030
## Network request collection boundary
@@ -48,7 +48,7 @@ The console shows a Performance page for React Native applications. Native vital
4848

4949
| Metric | Android | iOS | Description |
5050
|------|---------|-----|------|
51-
| App launch time | Not yet | Cold / warm launch | Android does not report launch time yet; the corresponding console card shows "No data" |
51+
| App launch time | Not yet | Cold / warm launch | The React Native Android bridge does not yet report the launch event; the corresponding console card shows "No data" |
5252
| Refresh rate | Supported | Supported | Rendering frame rate of the native UI thread |
5353
| **JS-thread frame rate** | Supported | Supported | React Native-specific; reflects whether application JS code is janky; shown on the console's Performance page |
5454
| CPU | Supported | Supported | CPU usage during the view |
@@ -82,7 +82,8 @@ DdRum.startResource('req-1', 'GET', 'https://api.example.com/orders');
8282
DdRum.stopResource('req-1', 200, 'xhr');
8383

8484
// Report an error manually
85-
DdRum.addError('payment failed', ErrorSource.SOURCE, stack);
85+
const error = new Error('payment failed');
86+
DdRum.addError(error.message, ErrorSource.SOURCE, error.stack ?? '');
8687

8788
// Attach global attributes (written to all subsequent events)
8889
DdSdkReactNative.setAttributes({ tenant: 'acme' });
@@ -91,6 +92,24 @@ DdSdkReactNative.setAttributes({ tenant: 'acme' });
9192
DdRum.addTiming('first_order_rendered');
9293
```
9394

95+
### View loading, sessions, and feature flags
96+
97+
Use these APIs to add view loading state, control session boundaries, and associate feature flag values with the current RUM session:
98+
99+
```typescript
100+
// Record loading time from startView until now; true overwrites an existing value
101+
DdRum.addViewLoadingTime(false);
102+
103+
// Returns undefined when the SDK is not initialized or no session is available
104+
const sessionId = await DdRum.getCurrentSessionId();
105+
106+
// Associate the feature flag value actually used in this session
107+
DdRum.addFeatureFlagEvaluation('checkout_redesign', 'variant-a');
108+
109+
// End the current session; the next RUM event starts a new session
110+
await DdRum.stopSession();
111+
```
112+
94113
## Sampling and controls
95114

96115
| Option | Default | Description |

en/rum/sdk/react-native/sdk-integration.mdx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,16 @@ const config = new DdSdkReactNativeConfiguration(
6060
TrackingConsent.GRANTED,
6161
);
6262
config.site = 'CN';
63-
config.serviceName = 'com.example.shopping'; // Required: keeps Android and iOS under one service
63+
config.serviceName = 'com.example.shopping'; // Recommended: keeps Android and iOS under one service
6464
config.nativeCrashReportEnabled = true; // Collect native Android / iOS crashes
6565
config.sessionSamplingRate = 100;
6666

6767
DdSdkReactNative.initialize(config);
6868
```
6969

70-
<Warning>
71-
**`serviceName` must be set explicitly.** Without it, Android defaults to the `applicationId` and iOS to the bundle identifier, so one application is split into two services in the console: the same error appears once per service in the issue list, and filters and source map matching are separated as well.
72-
</Warning>
70+
<Tip>
71+
**Set `serviceName` explicitly for cross-platform consistency.** Without it, Android defaults to the `applicationId` and iOS to the bundle identifier. If those platform identifiers differ, one application is split into two services, separating issue lists, filters, and source map matching.
72+
</Tip>
7373

7474
<Warning>
7575
Do not use server-side secrets in client code. `clientToken` is only used for client-side RUM data reporting, and `applicationId` is used to attribute RUM application data.
@@ -111,16 +111,43 @@ function App() {
111111
}
112112
```
113113

114-
Only one `NavigationContainer` can be tracked at a time; call `DdRumReactNavigationTracking.stopTrackingViews()` before switching containers.
114+
Only one `NavigationContainer` can be tracked at a time. Pass the previous container reference when you stop tracking before switching containers:
115+
116+
```typescript
117+
DdRumReactNavigationTracking.stopTrackingViews(navigationRef.current);
118+
```
119+
120+
The second argument to `startTrackingViews` can rename views. Return `null` to ignore a route. To use this control, replace the call inside `onReady` above with this one:
121+
122+
```typescript
123+
DdRumReactNavigationTracking.startTrackingViews(
124+
navigationRef.current,
125+
(route, trackedName) =>
126+
route.name === 'InternalDebug' ? null : `mobile/${trackedName}`,
127+
);
128+
```
129+
130+
<Note>
131+
Returning `null` only skips the new view; it does not stop the previous RUM view. Later events on the ignored screen may still be attributed to that previous view. Use manual view tracking when you need an explicit view boundary.
132+
</Note>
115133
</Tab>
116134
<Tab title="react-native-navigation (Wix)">
117135
Call once at application startup:
118136

119137
```typescript
120138
import { DdRumReactNativeNavigationTracking } from '@flashcatcloud/mobile-react-native-navigation';
121139

122-
DdRumReactNativeNavigationTracking.startTracking();
140+
DdRumReactNativeNavigationTracking.startTracking(
141+
(_event, trackedName) =>
142+
trackedName === 'InternalDebug' ? null : `mobile/${trackedName}`,
143+
);
123144
```
145+
146+
Call `DdRumReactNativeNavigationTracking.stopTracking()` when automatic tracking is no longer needed.
147+
148+
<Note>
149+
Returning `null` only skips the new view; it does not stop the previous RUM view. Later events on the ignored screen may still be attributed to that previous view. Use manual view tracking when you need an explicit view boundary.
150+
</Note>
124151
</Tab>
125152
<Tab title="Manual">
126153
If you use neither library, start and stop views manually:
@@ -168,7 +195,7 @@ To correlate frontend requests with backend traces, configure `firstPartyHosts`;
168195
After sign-in, set the current user. The SDK writes the user fields into the `usr` object of subsequent RUM events. Always pass `id`: iOS ignores calls without an `id`.
169196

170197
```typescript
171-
DdSdkReactNative.setUser({
198+
DdSdkReactNative.setUserInfo({
172199
id: 'user-1001',
173200
name: 'Alice',
174201
email: 'alice@example.com',

0 commit comments

Comments
 (0)