Manually instrument React Native applications

Manually instrument React Native applications to collect additional telemetry, sanitize personally identifiable information, add global attributes, and more.

You can manually instrument React Native applications using the Splunk RUM React Native agent to collect additional telemetry, add global attributes, and more.
Note:

When adding custom attributes to Splunk RUM data, prefix each attribute name with a string unique to your application or organization to prevent overlap with internal Splunk RUM attributes. For example, use tmo.session.id instead of session.id. Overwriting an internal RUM attribute can affect how telemetry is processed or associated with sessions. This guidance applies to global attributes, span attributes, and attributes added to custom events or workflows.

Manage global attributes

Global attributes are key-value pairs added to all reported data. Global attributes are useful for reporting application- or user-specific values as tags. The following examples show how to define global attributes:

  • To add metadata during agent initialization:

    TYPESCRIPT
    <SplunkRumProvider
      agentConfiguration={{
        endpoint: {
          realm: 'your-splunk-realm',
          rumAccessToken: 'your-splunk-rum-access-token',
        },
        appName: 'your-application-name',
        deploymentEnvironment: 'your-environment-name',
        globalAttributes: {
          'app.region': 'us-east',
          'app.build': 123,
        },
      }}
    >
      <AppRoot />
    </SplunkRumProvider>
  • To add metadata after agent initialization:

    TYPESCRIPT
    import { SplunkRum } from '@splunk/otel-react-native';
    
    const attrs = SplunkRum.instance.globalAttributes;
    
    await attrs.setString('user.id', '123');
    await attrs.setNumber('cart.items', 3);
    await attrs.setAllInNamespace('device', {
      model: 'iPhone',
      os: 'iOS',
    });

Track users

By default, the Splunk RUM React Native agent uses NO_TRACKING. To activate anonymous user tracking:

TYPESCRIPT
import { SplunkRum } from '@splunk/otel-react-native';

await SplunkRum.instance.user.preferences.setTrackingMode('ANONYMOUS_TRACKING');

Report custom events and workflows

You can report custom events and workflows happening in your application using the trackCustomEvent and trackWorkflow APIs. Additionally, you have the option to set custom attributes. See example below:

TYPESCRIPT
import { SplunkRum } from '@splunk/otel-react-native';

await SplunkRum.instance.customTracking.trackCustomEvent('checkout_complete', {
  'order.total': 99.99,
  'order.items': 3,
});

The following example shows how to start a workflow for which metrics are recorded by Splunk RUM:

TYPESCRIPT
const workflow = await SplunkRum.instance.customTracking.startWorkflow('checkout');
// ... perform checkout steps ...
await workflow.end();

Get agent and session state

You can inspect the current state of the agent and the active session:

TYPESCRIPT
const state = await SplunkRum.instance.getState();
const session = await SplunkRum.instance.session.state();

WebView integration (browser RUM correlation)

Use SplunkWebView to integrate browser RUM running inside a WebView with the native RUM session:

TYPESCRIPT
import { WebView } from 'react-native-webview';
import { SplunkWebView } from '@splunk/otel-react-native';

<SplunkWebView
  WebViewComponent={WebView}
  source={{ uri: 'https://example.com' }}
/>;

For manual integration, call integrateWebViewWithBrowserRum once you have the native view tag:

TYPESCRIPT
import { WebView } from 'react-native-webview';
import { SplunkRum } from '@splunk/otel-react-native';

const webViewRef = useRef<WebView>(null);

const onLoadEnd = () => {
  const nativeRef = (webViewRef.current as any)?.webViewRef?.current;
  const viewTag = nativeRef?._nativeTag;
  if (viewTag) {
    SplunkRum.instance.integrateWebViewWithBrowserRum(viewTag);
  }
};

<WebView
  ref={webViewRef}
  onLoadEnd={onLoadEnd}
  source={{ uri: 'https://example.com' }}
/>;

Automatic navigation detection

Automatic navigation detection is deactivated by default. You can activate it by configuring the Navigation detection module module.

Manually track navigation events

By default, the Splunk RUM React Native agent does not automatically track navigation events. If you enable automatic navigation tracking, the agent monitors native navigation components:

  • Android: Activity and Fragment lifecycle events. This might not work for UI frameworks such as Jetpack Compose, which use different lifecycle patterns.
  • iOS: UIKit view-controller lifecycle callbacks. The agent observes show and transition notifications to open and close spans and derives screen names from the controller type. This approach depends on UIKit-driven controller transitions and does not work for UI stacks such as pure SwiftUI.

Because automatic tracking does not support all navigation patterns, manual tracking is recommended for scenarios such as:

  • Custom routers
  • Unnamed routes
  • Tab changes
  • Unsupported navigation flows

To manually track a screen, call SplunkRum.instance.navigation.track().

PYTHON
import { SplunkRum } from '@splunk/otel-react-native'; await SplunkRum.instance.navigation.track('Checkout', { 'checkout.type': 'express', });
This records a navigation event, sets screen.name to Checkout, and attaches the supplied attributes.
Note: The returned Promise resolves after the native SDK accepts the navigation call. It does not wait for telemetry export or backend delivery.

You can also include optional attributes when tracking a screen:

JSON
await SplunkRum.instance.navigation.track('Checkout', { 'checkout.type': 'express', });

Manual tracking reports a navigation event and updates screen.name for subsequent RUM telemetry.

Track native screens automatically

If your app uses native navigation instead of React Navigation, enable automatic detection of Android Activity and Fragment instances or iOS UIViewController instances:
JAVASCRIPT
import { NavigationModuleConfiguration } from '@splunk/otel-react-native';

const modules = [
  new NavigationModuleConfiguration(
    true, // Enable the navigation module
    true, // Enable native automatic tracking
  ),
];

await SplunkRum.install(agentConfiguration, modules);

Add server trace context from Splunk APM

The Splunk RUM React Native agent collects server trace context using back-end data provided by Splunk APM instrumentation through the Server-Timing header. In some cases, you might want to generate the header manually.

To create the Server-Timing header manually, provide a Server-Timing header with the name traceparent, where the desc field holds the version, the trace ID, the parent ID, and the trace flag.

Consider the following HTTP header:

CODE
Server-Timing: traceparent;desc="00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"

The example resolves to a context containing the following data:

CODE
version=00 trace-id=4bf92f3577b34da6a3ce929d0e0e4736parent-id=00f067aa0ba902b7 trace-flags=01

When generating a value for the traceparent header, make sure that it matches the following regular expression:

CODE
00-([0-9a-f]{32})-([0-9a-f]{16})-01

Server timing headers with values that don't match the pattern are automatically discarded. For more information, see the Server-Timing and traceparent documentation on the W3C website.

If multiple valid Server-Timing headers are found, the last valid one is used.

Report errors manually

Report errors that your application catches, such as errors in a catch block, an error boundary, or a handled promise rejection, by calling trackError. Configure automatic crash and error capture separately through module configuration.

Each reported error creates a Real User Monitoring (RUM) span with component=error. The span includes the error type, message, source, and handled state. Reports created from an Error object also include the JavaScript stack trace when one is available. You can attach custom attributes to the span.

Report a caught error

Pass the caught Error object to trackError, as shown in the following example:

TYPESCRIPT
import { SplunkRum } from '@splunk/otel-react-native';

try {
  await riskyOperation();
} catch (e) {
  await SplunkRum.instance.customTracking.trackError(e as Error);
}

The agent derives the error type from the error's name or constructor name, reads the message from error.message, and records the JavaScript stack trace from error.stack without modification.

You can report an error from a message string when you don't have an Error object. A string report doesn't include a stack trace.

TYPESCRIPT
await SplunkRum.instance.customTracking.trackError('Cart is empty');

The returned Promise resolves if reporting fails, and the agent logs the failure. The method doesn't consume or modify the error. Before SDK installation, the call resolves without reporting an error.

Add attributes to an error

Attach custom attributes to add application context to the error span:

TYPESCRIPT
try {
  await checkout(cart);
} catch (e) {
  await SplunkRum.instance.customTracking.trackError(e as Error, {
    attributes: {
      'checkout.step': 'payment',
      'cart.items': 3,
    },
  });
}

Mark an error as unhandled

By default, the agent reports an error as handled and nonfatal. Set handled: false when an error escapes your code. The error span records exception.escaped=true.

TYPESCRIPT
await SplunkRum.instance.customTracking.trackError(e as Error, {
  handled: false,
});