Advanced Configuration

SDK


Overview

After you complete the initial SDK setup, use the advanced configuration options below to customize data collection, privacy settings, and SDK behavior for your platform.

For browser advanced configuration, see the Browser Advanced Configuration page.

If you have not set up the SDK yet, follow the in-app setup instructions or see the Android RUM setup documentation.

Enrich user sessions

Android RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the RUM Data Collection documentation to learn about the RUM events and default attributes. You can further enrich user session information and gain finer control over the attributes collected by tracking custom events.

Custom views

In addition to tracking views automatically, you can also track specific distinct views (such as activities and fragments) when they become visible and interactive in the onResume() lifecycle. Stop tracking when the view is no longer visible. Most often, this method should be called in the frontmost Activity or Fragment:

fun onResume() {
    GlobalRumMonitor.get().startView(viewKey, viewName, viewAttributes)
}

fun onPause() {
    GlobalRumMonitor.get().stopView(viewKey, viewAttributes)
}
public void onResume() {
    GlobalRumMonitor.get().startView(viewKey, viewName, viewAttributes);
}

public void onPause() {
    GlobalRumMonitor.get().stopView(viewKey, viewAttributes);
}

Custom actions

In addition to tracking actions automatically, you can also track specific custom user actions (such as taps, clicks, and scrolls) with RumMonitor#addAction. For continuous action tracking (for example, tracking a user scrolling a list), use RumMonitor#startAction and RumMonitor#stopAction.

The action type should be one of the following: "custom", "click", "tap", "scroll", "swipe", "back".

fun onUserInteraction() {
    GlobalRumMonitor.get().addAction(actionType, name, actionAttributes)
}
public void onUserInteraction() {
    GlobalRumMonitor.get().addAction(actionType, name, actionAttributes);
}

Enrich resources

When tracking resources automatically, provide a custom RumResourceAttributesProvider instance to add custom attributes to each tracked network request. For example, if you want to track a network request's headers, create an implementation as follows, and pass it in the builder of the DatadogInterceptor.

class CustomRumResourceAttributesProvider : RumResourceAttributesProvider {
    override fun onProvideAttributes(
        request: Request,
        response: Response?,
        throwable: Throwable?
    ): Map<String, Any?> {
        val headers = request.headers
        return headers.names().associate {
            "headers.${it.lowercase(Locale.US)}" to headers.values(it).first()
        }
    }
}
public class CustomRumResourceAttributesProvider implements RumResourceAttributesProvider {
    @NonNull
    @Override
    public Map<String, Object> onProvideAttributes(
            @NonNull Request request,
            @Nullable Response response,
            @Nullable Throwable throwable
    ) {
        Map<String, Object> result = new HashMap<>();
        Headers headers = request.headers();

        for (String key : headers.names()) {
            String attrName = "headers." + key.toLowerCase(Locale.US);
            result.put(attrName, headers.values(key).get(0));
        }

        return result;
    }
}

Custom resources

In addition to tracking resources automatically, you can also track specific custom resources (such as network requests and third-party provider APIs) with methods (such as GET and POST) while loading the resource with RumMonitor#startResource. Stop tracking with RumMonitor#stopResource when it is fully loaded, or RumMonitor#stopResourceWithError if an error occurs while loading the resource.

fun loadResource() {
    GlobalRumMonitor.get().startResource(resourceKey, method, url, resourceAttributes)
    try {
        // do load the resource
        GlobalRumMonitor.get().stopResource(resourceKey, resourceKind, additionalAttributes)
    } catch (e: Exception) {
        GlobalRumMonitor.get().stopResourceWithError(resourceKey, message, origin, e)
    }
}
public void loadResource() {
    GlobalRumMonitor.get().startResource(resourceKey, method, url, resourceAttributes);
    try {
        // do load the resource
        GlobalRumMonitor.get().stopResource(resourceKey, resourceKind, additionalAttributes);
    } catch (Exception e) {
        GlobalRumMonitor.get().stopResourceWithError(resourceKey, message, origin, e);
    }
}

Custom errors

To track specific errors, notify the monitor when an error occurs with the message, source, exception, and additional attributes. See the Error Attributes documentation.

GlobalRumMonitor.get().addError(message, source, throwable, attributes)

Add user properties

You can use the addUserProperties API to append extra user properties to previously set properties.

fun addUserProperties(extraInfo: Map<String, Any?>, sdkCore: SdkCore = getInstance()) {
    sdkCore.addUserProperties(extraInfo)
}

Event and data management

The Android SDK first stores events and only uploads events when the intake specifications conditions are met.

Clear all data

You have the option of deleting all unsent data stored by the SDK with the clearAllData API.

fun clearAllData(sdkCore: SdkCore = getInstance()) {
    sdkCore.clearAllData()
}

Stop data collection

You can use the StopInstance API to stop the SDK instance assigned to the given name (or the default instance if the name is null) from collecting and uploading data further.

fun stopInstance(instanceName: String? = null) {
    synchronized(registry) {
        val instance = registry.unregister(instanceName)
        (instance as? DatadogCore)?.stop()
    }
}

Control event buildup

Many operations, such as data processing and event I/O, are queued in background threads to handle edge cases where the queue has grown so much that there could be delayed processing, high memory usage, or Application Not Responding (ANR) errors.

You can control the buildup of events on the SDK with the setBackpressureStrategy API. This API ignores new tasks if a queue reaches 1024 items.

fun setBackpressureStrategy(backpressureStrategy: BackPressureStrategy): Builder {
    coreConfig = coreConfig.copy(backpressureStrategy = backpressureStrategy)
    return this
}

See an example of this API being used.

Set remote log threshold

You can define the minimum log level (priority) to send events to Datadog in a logger instance. If the log priority is below the one you set at this threshold, it does not get sent. The default value is -1 (allow all).

fun setRemoteLogThreshold(minLogThreshold: Int): Builder {
    minDatadogLogsPriority = minLogThreshold
    return this
}

Track custom global attributes

In addition to the default RUM attributes captured by the RUM Android SDK automatically, you can choose to add additional contextual information, such as custom attributes, to your RUM events to enrich your observability within Datadog. Custom attributes allow you to filter and group information about observed user behavior (such as cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

Track user sessions

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User attributes of a session in the RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use the setUserInfo API, for example:

Datadog.setUserInfo('1234', 'John Doe', 'john@doe.com')

Track attributes

// Adds an attribute to all future RUM events
GlobalRumMonitor.get().addAttribute(key, value)

// Removes an attribute to all future RUM events
GlobalRumMonitor.get().removeAttribute(key)

Track widgets

Widgets are not automatically tracked with the SDK. To send UI interactions from your widgets manually, call the Datadog API. See example.

Initialization parameters

You can use the following methods in Configuration.Builder when creating the Datadog configuration to initialize the library:

setFirstPartyHosts()
Defines hosts that have tracing enabled and have RUM resources categorized as first-party. Note: If you define custom tracing header types in the Datadog configuration and are using a tracer registered with GlobalTracer, make sure the same tracing header types are set for the tracer in use.
useSite(DatadogSite)
Switches target data to EU1, US1, US3, US5, US1_FED, AP1 and AP2 sites.
setFirstPartyHostsWithHeaderType
Sets the list of first party hosts and specifies the type of HTTP headers used for distributed tracing.
setBatchSize([SMALL|MEDIUM|LARGE])
Defines the individual batch size for requests sent to Datadog.
setUploadFrequency([FREQUENT|AVERAGE|RARE])
Defines the frequency for requests made to Datadog endpoints (if requests are available).
setBatchProcessingLevel(LOW|MEDIUM|HIGH)
Defines the number of batches sent in each upload cycle.
setAdditionalConfiguration
Allows you to provide additional configuration values that can be used by the SDK.
setProxy
Enables a custom proxy for uploading tracked data to Datadog's intake.
setEncryption(Encryption)
Set an encryption function applied to data stored locally on the device.
setPersistenceStrategyFactory
Allows you to use a custom persistence strategy.
setCrashReportsEnabled(Boolean)
Allows you to control whether JVM crashes are tracked or not. The default value is true.
setBackpressureStrategy(BackPressureStrategy)
Define the strategy the SDK uses when handling large volumes of data and internal queues are full.

You can use the following methods in RumConfiguration.Builder when creating the RUM configuration to enable RUM features:

trackUserInteractions(Array<ViewAttributesProvider>)
Enables tracking user interactions (such as tap, scroll, or swipe). The parameter also allows you to add custom attributes to the RUM Action events based on the widget with which the user interacted.
disableUserInteractionTracking
Disables the user interaction automatic tracker.
useViewTrackingStrategy(strategy)
Defines the strategy used to track views. See Automatically track views for more information.
trackLongTasks(durationThreshold)
Enables tracking tasks taking longer than durationThreshold on the main thread as long tasks in Datadog. See Automatically track long tasks for more information.
trackNonFatalAnrs(Boolean)
Enables tracking non-fatal ANRs. This is enabled by default on Android API 29 and below, and disabled by default on Android API 30 and above.
setVitalsUpdateFrequency([FREQUENT|AVERAGE|RARE|NEVER])
Sets the preferred frequency for collecting mobile vitals.
setSessionSampleRate(<sampleRate>)
Sets the RUM sessions sample rate. (A value of 0 means no RUM events are sent. A value of 100 means all sessions are kept.)
setSessionListener(RumSessionListener)
Sets a listener to be notified on when a new RUM Session starts.
setTelemetrySampleRate
The sampling rate for the SDK internal telemetry utilized by Datadog. This must be a value between 0 and 100. By default, this is set to 20.
setViewEventMapper
Sets the ViewEventMapper for the RUM ViewEvent. You can use this interface implementation to modify the ViewEvent attributes before serialization.
setResourceEventMapper
Sets the EventMapper for the RUM ResourceEvent. You can use this interface implementation to modify the ResourceEvent attributes before serialization.
setActionEventMapper
Sets the EventMapper for the RUM ActionEvent. You can use this interface implementation to modify the ActionEvent attributes before serialization.
setErrorEventMapper
Sets the EventMapper for the RUM ErrorEvent. You can use this interface implementation to modify the ErrorEvent attributes before serialization.
setInitialResourceIdentifier
Sets a custom identifier for initial network resources used for Time-to-Network-Settled (TNS) view timing calculation.
setLastInteractionIdentifier
Sets a custom identifier for the last interaction in the previous view used for Interaction-to-Next-View (INV) timing calculation.
setLongTaskEventMapper
Sets the EventMapper for the RUM LongTaskEvent. You can use this interface implementation to modify the LongTaskEvent attributes before serialization.
trackBackgroundEvents
Enable/disable tracking RUM events when no activity is happening in the foreground. By default, background events are not tracked. Enabling this feature might increase the number of sessions tracked, and therefore your billing.
trackFrustrations
Enable/disable tracking of frustration signals.
useCustomEndpoint
Use RUM to target a custom server.
trackAnonymousUser
When enabled, the SDK generates a unique, non-personal anonymous user ID that is persisted across app launches. This ID is attached to each RUM Session, allowing you to link sessions originating from the same user/device without collecting personal data. By default, this is set to true.

Automatically track views

To automatically track your views (such as activities and fragments), provide a tracking strategy at initialization. Depending on your application's architecture, you can choose one of the following strategies:

ActivityViewTrackingStrategy
Every activity in your application is considered a distinct view.
FragmentViewTrackingStrategy
Every fragment in your application is considered a distinct view.
MixedViewTrackingStrategy
Every activity or fragment in your application is considered a distinct view.
NavigationViewTrackingStrategy
Recommended for Android Jetpack Navigation library users. Each Navigation destination is considered a distinct view.

For instance, to set each fragment as a distinct view, use the following configuration in your setup:

val rumConfig = RumConfiguration.Builder(applicationId)
  .useViewTrackingStrategy(FragmentViewTrackingStrategy(...))
  .build()
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
 .useViewTrackingStrategy(new FragmentViewTrackingStrategy(...))
 .build();

For ActivityViewTrackingStrategy, FragmentViewTrackingStrategy, or MixedViewTrackingStrategy, you can filter which Fragment or Activity is tracked as a RUM View by providing a ComponentPredicate implementation in the constructor:

val rumConfig = RumConfiguration.Builder(applicationId)
  .useViewTrackingStrategy(
    ActivityViewTrackingStrategy(
      trackExtras = true,
      componentPredicate = object : ComponentPredicate<Activity> {
        override fun accept(component: Activity): Boolean {
            return true
        }

        override fun getViewName(component: Activity): String? = null
      })
    )
  .build()
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
    .useViewTrackingStrategy(new ActivityViewTrackingStrategy(
        true,
        new ComponentPredicate<Activity>() {
            @Override
            public boolean accept(Activity component) {
                return true;
            }

            @Override
            public String getViewName(Activity component) {
                return null;
            }
        }
    ))
    .build();

Note: By default, the library is using ActivityViewTrackingStrategy. If you decide not to provide a view tracking strategy, you must manually send the views by calling the startView and stopView methods yourself.

Automatically track network requests

Basic network instrumentation

To get timing information in resources (such as third-party providers, network requests) such as time to first byte or DNS resolution, customize the OkHttpClient to add the EventListener factory:

  1. Add the Gradle dependency to the dd-sdk-android-okhttp library in the module-level build.gradle file:
dependencies {
    implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x"
}
  1. Add the EventListener factory:
val tracedHosts = listOf("example.com")
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(DatadogInterceptor.Builder(tracedHosts).build())
    .eventListenerFactory(DatadogEventListener.Factory())
    .build()
List<String> tracedHosts = Arrays.asList("example.com");
OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addInterceptor(new DatadogInterceptor.Builder(tracedHosts).build())
    .eventListenerFactory(new DatadogEventListener.Factory())
    .build();

Cronet network instrumentation

If you use Cronet instead of OkHttp, you can instrument your CronetEngine for automatic RUM resource tracking.

  1. Add the Gradle dependencies in the module-level build.gradle file:
dependencies {
    implementation "com.datadoghq:dd-sdk-android-cronet:x.x.x"
}
  1. Instrument the CronetEngine.Builder:
val cronetEngine = CronetEngine.Builder(context)
    .configureDatadogInstrumentation(
        rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
        apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
            tracedHosts = listOf("example.com", "example.eu")
        )
    )
    .build()
CronetEngine.Builder builder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = CronetIntegrationPluginKt
    .configureDatadogInstrumentation(
        builder,
        new RumNetworkInstrumentationConfiguration(),
        new ApmNetworkInstrumentationConfiguration(
            Arrays.asList("example.com", "example.eu")
        )
    )
    .build();

Apollo instrumentation

  1. Set up RUM monitoring with Datadog Android RUM.

  2. Set up OkHttp instrumentation with the Datadog RUM SDK.

  3. Add the following to your application's build.gradle file.

dependencies {
    implementation "com.datadoghq:dd-sdk-android-apollo:x.x.x"
}
  1. Add the Datadog interceptor to your Apollo Client setup:
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.network.okHttpClient
import com.datadog.android.apollo.DatadogApolloInterceptor

val apolloClient = ApolloClient.Builder()
    .serverUrl("GraphQL endpoint")
    .addInterceptor(DatadogApolloInterceptor())
    .okHttpClient(okHttpClient)
    .build()

This automatically adds Datadog headers to your GraphQL requests, allowing them to be tracked by Datadog.

  • The integration only supports Apollo version 4.
  • The query and mutation type operations are tracked; subscription operations are not.
  • GraphQL payload sending is disabled by default. To enable it, set the sendGraphQLPayloads flag in the DatadogApolloInterceptor constructor as follows:
DatadogApolloInterceptor(sendGraphQLPayloads = true)

Automatically track long tasks

Long running operations performed on the main thread can impact the visual performance and reactivity of your application. To track these operations, define the duration threshold above which a task is considered too long.

val rumConfig = RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(durationThreshold)
  .build()

For example, to replace the default 100 ms duration, set a custom threshold in your configuration.

val rumConfig = RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(250L) // track tasks longer than 250ms as long tasks
  .build()
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(durationThreshold)
  .build();

For example, to replace the default 100 ms duration, set a custom threshold in your configuration.

RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(250L) // track tasks longer than 250ms as long tasks
  .build();

Modify or drop RUM events

To modify some attributes in your RUM events, or to drop some of the events entirely before batching, provide an implementation of EventMapper<T> when initializing the RUM Android SDK:

val rumConfig = RumConfiguration.Builder(applicationId)
  // ...
  .setErrorEventMapper(rumErrorEventMapper)
  .setActionEventMapper(rumActionEventMapper)
  .setResourceEventMapper(rumResourceEventMapper)
  .setViewEventMapper(rumViewEventMapper)
  .setLongTaskEventMapper(rumLongTaskEventMapper)
  .build()
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
  // ...
  .setErrorEventMapper(rumErrorEventMapper)
  .setActionEventMapper(rumActionEventMapper)
  .setResourceEventMapper(rumResourceEventMapper)
  .setViewEventMapper(rumViewEventMapper)
  .setLongTaskEventMapper(rumLongTaskEventMapper)
  .build();

When implementing the EventMapper<T> interface, only some attributes are modifiable for each event type:

Event typeAttribute keyDescription
ViewEventview.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ActionEvent
action.target.nameTarget name.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ErrorEvent
error.messageError message.
error.stackStacktrace of the error.
error.resource.urlURL of the resource.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ResourceEvent
resource.urlURL of the resource.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
LongTaskEvent
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.

Note: If you return null from the EventMapper<T> implementation, the event is kept and sent as-is.

Retrieve the RUM session ID

Retrieving the RUM session ID can be helpful for troubleshooting. For example, you can attach the session ID to support requests, emails, or bug reports so that your support team can later find the user session in Datadog.

You can access the RUM session ID at runtime without waiting for the sessionStarted event:

GlobalRumMonitor.get().getCurrentSessionId { sessionId ->
  currentSessionId = sessionId
}

If you have not set up the RUM iOS SDK yet, follow the in-app setup instructions or see the RUM iOS setup documentation.

Enrich user sessions

iOS RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the RUM Data Collection documentation to learn about the RUM events and default attributes. You can further enrich user session information and gain finer control over the attributes collected by tracking custom events.

Custom views

In addition to tracking views automatically, you can also track specific distinct views such as viewControllers when they become visible and interactive. Stop tracking when the view is no longer visible using the following methods in RUMMonitor.shared():

  • .startView(viewController:)
  • .stopView(viewController:)

For example:

import DatadogRUM

// in your `UIViewController`:
let rum = RUMMonitor.shared()

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    rum.startView(viewController: self)
}

override func viewDidDisappear(_ animated: Bool) {
  super.viewDidDisappear(animated)
  rum.stopView(viewController: self)
}
@import DatadogRUM;
// in your `UIViewController`:

DDRUMMonitor *rum = [DDRUMMonitor shared];

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [rum startViewWithViewController:self name:nil attributes:nil];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [rum stopViewWithViewController:self attributes:nil];
}

For more details and available options, see RUMMonitorProtocol in GitHub.

Custom actions

In addition to tracking actions automatically, you can track specific custom user actions (taps, clicks, and scrolls) with the addAction(type:name:) API.

To manually register instantaneous RUM actions such as .tap on RUMMonitor.shared(), use .addAction(type:name:). For continuous RUM actions such as .scroll, use .startAction(type:name:) or .stopAction(type:).

For example:

import DatadogRUM

// in your `UIViewController`:

let rum = RUMMonitor.shared()

@IBAction func didTapDownloadResourceButton(_ sender: UIButton) {
    rum.addAction(
        type: .tap,
        name: sender.currentTitle ?? ""
    )
}
- (IBAction)didTapDownloadResourceButton:(UIButton *)sender {
    NSString *name = sender.currentTitle ? sender.currentTitle : @"";
    [[DDRUMMonitor shared] addActionWithType:DDRUMActionTypeTap name:name attributes:@{}];
}

Note: When using .startAction(type:name:) and .stopAction(type:), the action type must be the same. This is necessary for the RUM iOS SDK to match an action start with its completion.

For more details and available options, see RUMMonitorProtocol in GitHub.

Custom resources

In addition to tracking resources automatically, you can also track specific custom resources such as network requests or third-party provider APIs. This is the recommended approach for third-party libraries that don't expose a URLSession delegate. Use the following methods on RUMMonitor.shared() to manually collect RUM resources:

  • .startResource(resourceKey:request:)
  • .stopResource(resourceKey:response:)
  • .stopResourceWithError(resourceKey:error:)
  • .stopResourceWithError(resourceKey:message:)

For example:

import DatadogRUM

// in your network client:

let rum = RUMMonitor.shared()

rum.startResource(
    resourceKey: "resource-key",
    request: request
)

rum.stopResource(
    resourceKey: "resource-key",
    response: response
)
// in your network client:

[[DDRUMMonitor shared] startResourceWithResourceKey:@"resource-key"
                                            request:request
                                         attributes:@{}];

[[DDRUMMonitor shared] stopResourceWithResourceKey:@"resource-key"
                                          response:response
                                        attributes:@{}];

Note: The String used for resourceKey in both calls must be unique for the resource you are calling. This is necessary for the RUM iOS SDK to match a resource's start with its completion.

For more details and available options, see RUMMonitorProtocol in GitHub.

Custom errors

To track specific errors, notify RUMMonitor.shared() when an error occurs using one of following methods:

  • .addError(message:)
  • .addError(error:)
let rum = RUMMonitor.shared()
rum.addError(message: "error message.")
[[DDRUMMonitor shared] addErrorWithMessage:@"error message." stack:nil source:DDRUMErrorSourceCustom attributes:@{}];

For more details and available options, see RUMMonitorProtocol in GitHub and the Error Attributes documentation.

Track custom global attributes

In addition to the default RUM attributes captured by the RUM iOS SDK automatically, you can choose to add additional contextual information (such as custom attributes) to your RUM events to enrich your observability within Datadog.

Custom attributes allow you to filter and group information about observed user behavior (such as the cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

Custom attributes are intended for small, targeted pieces of information (for example, IDs, flags, or short labels). Avoid attaching large objects such as full HTTP response payloads. This can significantly increase event size and impact performance.

Set a custom global attribute

To set a custom global attribute, use RUMMonitor.shared().addAttribute(forKey:value:).

  • To add an attribute, use RUMMonitor.shared().addAttribute(forKey: "<KEY>", value: "<VALUE>").
  • To update the value, use RUMMonitor.shared().addAttribute(forKey: "<KEY>", value: "<UPDATED_VALUE>").
  • To remove the key, use RUMMonitor.shared().removeAttribute(forKey: "<KEY_TO_REMOVE>").

For better performance in bulk operations (modifying multiple attributes at once), use .addAttributes(_:) and .removeAttributes(forKeys:).

Note: You can't create facets on custom attributes if you use spaces or special characters in your key names. For example, use forKey: "store_id" instead of forKey: "Store ID".

Track user sessions

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User API in the RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use the Datadog.setUserInfo(id:name:email:) API.

For example:

import DatadogCore

Datadog.setUserInfo(id: "1234", name: "John Doe", email: "john@doe.com")
[DDDatadog setUserInfoWithId:@"1234" name:@"John Doe" email:@"john@doe.com" extraInfo:@{}];

Track background events

Tracking background events may lead to additional sessions, which can impact billing. For questions, contact Datadog support.

You can track events such as crashes and network requests when your application is in the background (for example, no active view is available).

To track background events, add the following snippet during initialization in your Datadog configuration:

import DatadogRUM

RUM.enable(
  with: RUM.Configuration(
    ...
    trackBackgroundEvents: true
  )
)

Initialization parameters

You can use the following properties in Datadog.Configuration when creating the Datadog configuration to initialize the library:

backgroundTasksEnabled
This flag determines if the UIApplication methods beginBackgroundTask(expirationHandler:) and endBackgroundTask: are used to perform background uploads. Enabling this flag might increase the amount of time that the app operates in the background by 30 seconds. Tasks are normally stopped when there's nothing to upload or when encountering a blocker to uploading, such as having no internet connection or having a low battery. By default, this flag is set to false.
batchProcessingLevel
Batch processing level defines the maximum number of batches processed sequentially without a delay within one reading/uploading cycle. The default value is .medium.
batchSize
Sets the preferred size of batched data uploaded to Datadog. This value impacts the size and number of requests performed by the RUM iOS SDK (small batches mean more requests, but each request becomes smaller in size). Available values include: .small, .medium, and .large.
bundle
The bundle object that contains the current executable.
clientToken
Either the RUM client token (which supports RUM, Logging, and APM) or the regular client token (which supports Logging and APM).
encryption
Data encryption to use for on-disk data persistency by providing an object that complies with the DataEncryption protocol.
env
The environment name that is sent to Datadog. This can be used to filter events by different environments (such as staging or production).
proxyConfiguration
A proxy configuration attribute which can be used to enable a custom proxy for uploading tracked data to Datadog's intake.
serverDateProvider
A custom NTP synchronization interface. By default, the Datadog SDK synchronizes with dedicated NTP pools provided by the NTP Pool Project. Using different pools or setting a no operation ServerDateProvider implementation results in a de-synchronization of the SDK instance and the Datadog servers. This can lead to significant time shifts in RUM sessions or distributed traces.
service
The service name associated with data sent to Datadog. The default value is the application bundle identifier.
site
The Datadog server endpoint that data is sent to. The default value is .us1.
uploadFrequency
The preferred frequency of uploading data to Datadog. Available values include: .frequent, .average, and .rare.

RUM configuration

You can use the following properties in RUM.Configuration when enabling RUM:

actionEventMapper
Sets the data scrubbing callback for actions. This can be used to modify or drop action events before they are sent to Datadog. For more information, see Modify or drop RUM events.
appHangThreshold
Sets the threshold for reporting when an app hangs. The minimum allowed value for this option is 0.1 seconds. To disable reporting, set this value to nil. For more information, see Add app hang reporting.
applicationID
The RUM application identifier.
customEndpoint
A custom server URL for sending RUM data.
errorEventMapper
The data scrubbing callback for errors. This can be used to modify or drop error events before they are sent to Datadog. For more information, see Modify or drop RUM events.
longTaskEventMapper
The data scrubbing callback for long tasks. This can be used to modify or drop long task events before they are sent to Datadog. For more information, see Modify or drop RUM events.
longTaskThreshold
The threshold for RUM long tasks tracking (in seconds). By default, this is set to 0.1 seconds.
networkSettledResourcePredicate
The predicate used to classify "initial" resources for the Time-to-Network-Settled (TNS) view timing calculation.
nextViewActionPredicate
The predicate used to classify the "last" action for the Interaction-to-Next-View (INV) timing calculation.
onSessionStart
(Optional) The method that gets called when RUM starts the session.
resourceEventMapper
The data scrubbing callback for resources. This can be used to modify or drop resource events before they are sent to Datadog. For more information, see Modify or drop RUM events.
sessionSampleRate
The sampling rate for RUM sessions. The sessionSampleRate value must be between 0.0 and 100.0. A value of 0.0 means no sessions are sent, while 100.0 means that all sessions are sent to Datadog. The default value is 100.0.
telemetrySampleRate
The sampling rate for the SDK internal telemetry utilized by Datadog. This rate controls the number of requests reported to the tracing system. This must be a value between 0 and 100. By default, this is set to 20.
trackAnonymousUser
When enabled, the SDK generates a unique, non-personal anonymous user ID that is persisted across app launches. This ID is attached to each RUM Session, allowing you to link sessions originating from the same user/device without collecting personal data. By default, this is set to true.
trackBackgroundEvents
Determines whether RUM events are tracked when no view is active. By default, this is set to false.
trackFrustrations
Determines whether automatic tracking of user frustrations is enabled. By default, this is set to true.
trackMemoryWarnings
Determines whether automatic tracking of memory warnings is enabled. By default, this is set to true.
trackWatchdogTerminations
Determines whether the SDK should track application terminations performed by Watchdog. The default setting is false.
uiKitActionsPredicate
Enables tracking user interactions (taps) as RUM actions. You can use the default implementation of predicate by setting the DefaultUIKitRUMActionsPredicate or implement your own UIKitRUMActionsPredicate customized for your app.
uiKitViewsPredicate
Enables tracking UIViewControllers as RUM views. You can use default implementation of predicate by setting the DefaultUIKitRUMViewsPredicate or implement your own UIKitRUMViewsPredicate customized for your app.
urlSessionTracking
Enables tracking URLSession tasks (network requests) as RUM resources. The firstPartyHostsTracing parameter defines hosts that are categorized as first-party resources (if RUM is enabled) and have tracing information injected (if tracing feature is enabled). The resourceAttributesProvider parameter defines a closure to provide custom attributes for intercepted resources that is called for each resource collected by the RUM iOS SDK. This closure is called with task information and may return custom resource attributes or nil if no attributes should be attached.
viewEventMapper
The data scrubbing callback for views. This can be used to modify view events before they are sent to Datadog. For more information, see Modify or drop RUM events.
vitalsUpdateFrequency
The preferred frequency for collecting mobile vitals. Available values include: .frequent (every 100ms), .average (every 500ms), .rare (every 1s), and .never (which disables vitals monitoring).

Automatically track views

You can automatically track views with UIKit and SwiftUI.

UIKit

To automatically track views (UIViewControllers), use the uiKitViewsPredicate option when enabling RUM. By default, views are named with the view controller's class name. To customize it, provide your own implementation of the predicate which conforms to UIKitRUMViewsPredicate protocol:

public protocol UIKitRUMViewsPredicate {
    func rumView(for viewController: UIViewController) -> RUMView?
}
@objc
public protocol DDUIKitRUMViewsPredicate: AnyObject {
    func rumView(for viewController: UIViewController) -> DDRUMView?
}

Inside the rumView(for:) implementation, your app should decide if a given UIViewController instance should start a RUM view (return a value) or not (return nil). The returned RUMView value must specify the name and may provide additional attributes for the created RUM view.

For instance, you can configure the predicate to use explicit type check for each view controller in your app:

class YourCustomPredicate: UIKitRUMViewsPredicate {

    func rumView(for viewController: UIViewController) -> RUMView? {
        switch viewController {
        case is HomeViewController:     return .init(name: "Home")
        case is DetailsViewController:  return .init(name: "Details")
        default:                        return nil
        }
    }
}
@interface YourCustomPredicate : NSObject<DDUIKitRUMViewsPredicate>

@end

@implementation YourCustomPredicate

- (DDRUMView * _Nullable)rumViewFor:(UIViewController * _Nonnull)viewController {
    if ([viewController isKindOfClass:[HomeViewController class]]) {
        return [[DDRUMView alloc] initWithName:@"Home" attributes:@{}];
    }

    if ([viewController isKindOfClass:[DetailsViewController class]]) {
        return [[DDRUMView alloc] initWithName:@"Details" attributes:@{}];
    }

    return nil;
}

@end

You can even come up with a more dynamic solution depending on your app's architecture.

For example, if your view controllers use accessibilityLabel consistently, you can name views by the value of accessibility label:

class YourCustomPredicate: UIKitRUMViewsPredicate {

    func rumView(for viewController: UIViewController) -> RUMView? {
        guard let accessibilityLabel = viewController.accessibilityLabel else {
            return nil
        }

        return RUMView(name: accessibilityLabel)
    }
}
@interface YourCustomPredicate : NSObject<DDUIKitRUMViewsPredicate>

@end

@implementation YourCustomPredicate

- (DDRUMView * _Nullable)rumViewFor:(UIViewController * _Nonnull)viewController {
    if (viewController.accessibilityLabel) {
        return [[DDRUMView alloc] initWithName:viewController.accessibilityLabel attributes:@{}];
    }

    return nil;
}

@end

Note: The RUM iOS SDK calls rumView(for:) many times while your app is running. Datadog recommends keeping its implementation fast and single-threaded.

SwiftUI

To automatically track views with SwiftUI, use the swiftUIViewsPredicate option when enabling RUM.

The mechanism to extract a SwiftUI view name relies on reflection. As a result, view names may not always be meaningful. If a meaningful name cannot be extracted, a generic name such as AutoTracked_HostingController_Fallback or AutoTracked_NavigationStackController_Fallback is used.

You can use the default predicate (DefaultSwiftUIRUMViewsPredicate) or provide your own implementation of the SwiftUIRUMViewsPredicate protocol to customize or filter view names.

public protocol SwiftUIRUMViewsPredicate {
    func rumView(for extractedViewName: String) -> RUMView?
}

// Example: Custom predicate to ignore fallback names and rename views
class CustomSwiftUIPredicate: SwiftUIRUMViewsPredicate {
    func rumView(for extractedViewName: String) -> RUMView? {
        if extractedViewName == "AutoTracked_HostingController_Fallback" ||
           extractedViewName == "AutoTracked_NavigationStackController_Fallback" {
            return nil // Ignore fallback names
        }
        if extractedViewName == "MySpecialView" {
            return RUMView(name: "Special")
        }
        return RUMView(name: extractedViewName)
    }
}
@protocol DDSwiftUIRUMViewsPredicate <NSObject>
- (DDRUMView * _Nullable)rumViewFor:(NSString * _Nonnull)extractedViewName;
@end

@interface CustomSwiftUIPredicate : NSObject <DDSwiftUIRUMViewsPredicate>
@end

@implementation CustomSwiftUIPredicate
- (DDRUMView * _Nullable)rumViewFor:(NSString * _Nonnull)extractedViewName {
    if ([extractedViewName isEqualToString:@"AutoTracked_HostingController_Fallback"] ||
        [extractedViewName isEqualToString:@"AutoTracked_NavigationStackController_Fallback"]) {
        return nil; // Ignore fallback names
    }
    if ([extractedViewName isEqualToString:@"MySpecialView"]) {
        return [[DDRUMView alloc] initWithName:@"Special" attributes:@{}];
    }
    return [[DDRUMView alloc] initWithName:extractedViewName attributes:@{}];
}
@end

Notes:

  • Datadog recommends enabling UIKit view tracking as well, even if your app is built entirely with SwiftUI.
  • Tab bars are not tracked automatically. Use manual tracking for each tab view to track them.
  • If you use both automatic and manual tracking, you may see duplicate events. To avoid this, rely on a single instrumentation method or use a custom predicate to filter out duplicates.

Automatically track user actions

UIKit

To automatically track user tap actions with UIKit, set the uiKitActionsPredicate option when enabling RUM.

SwiftUI

To automatically track user tap actions in SwiftUI, enable the swiftUIActionsPredicate option when enabling RUM.

Notes:

  • Datadog recommends enabling UIKit action tracking as well even for pure SwiftUI apps as many interactive components rely on UIKit internally.
  • On tvOS, only press interactions on the remote are tracked. Only a UIKit predicate is needed for this. If you have a pure SwiftUI app but want to track remote presses on tvOS, you should also enable UIKit instrumentation.
  • The implementation differs between iOS 18+ and iOS 17 and below:
    • iOS 18 and above: Most interactions are reliably tracked with correct component names (for example, SwiftUI_Button, SwiftUI_NavigationLink).
    • iOS 17 and below: The SDK cannot distinguish between interactive and non-interactive components (for example, Button vs. Label). For that reason, actions are reported as SwiftUI_Unidentified_Element.
  • If you use both automatic and manual tracking, you may see duplicate events. This is a known limitation. To avoid this, use only one instrumentation type - either automatic or manual.
  • You can use the default predicate, DefaultSwiftUIRUMActionsPredicate, or provide your own to filter or rename actions. You can also disable legacy detection (iOS 17 and below) if you only want reliable iOS 18+ tracking:
// Use the default predicate by disabling iOS 17 and below detection
let predicate = DefaultSwiftUIRUMActionsPredicate(isLegacyDetectionEnabled: false)

// Use your own predicate
class CustomSwiftUIActionsPredicate: SwiftUIRUMActionsPredicate {
    func rumAction(for componentName: String) -> RUMAction? {
        // Custom logic to filter or rename actions
        return RUMAction(name: componentName)
    }
}
// Use the default predicate by disabling iOS 17 and below detection
DDDefaultSwiftUIRUMActionsPredicate *swiftUIActionsPredicate = [[DDDefaultSwiftUIRUMActionsPredicate alloc] initWithIsLegacyDetectionEnabled:NO];

// Use your own predicate
@protocol DDSwiftUIRUMActionsPredicate <NSObject>
- (DDRUMAction * _Nullable)rumActionFor:(NSString * _Nonnull)componentName;
@end

@interface CustomSwiftUIActionsPredicate : NSObject <DDSwiftUIRUMActionsPredicate>
@end

@implementation CustomSwiftUIActionsPredicate
- (DDRUMAction * _Nullable)rumActionFor:(NSString * _Nonnull)componentName {
    // Custom logic to filter or rename actions
    return [[DDRUMAction alloc] initWithName:componentName attributes:@{}];
}
@end

Action reporting by iOS version

The table below shows how iOS 17 and iOS 18 report different user interactions.

ComponentiOS 18 reported nameiOS 17 reported name
ButtonSwiftUI_ButtonSwiftUI_Unidentified_Element
NavigationLinkNavigationLinkSwiftUI_Unidentified_Element
MenuSwiftUI_Menu (and its items as _UIContextMenuCell)SwiftUI_Menu (and its items as _UIContextMenuCell)
LinkSwiftUI_ButtonSwiftUI_Unidentified_Element

Automatically track network requests

Network requests are automatically tracked after you enable RUM with the urlSessionTracking configuration.

(Optional) Enable detailed timing breakdown

To get detailed timing breakdown (DNS resolution, SSL handshake, time to first byte, connection time, and download duration), enable URLSessionInstrumentation for your delegate type:

URLSessionInstrumentation.enableDurationBreakdown(
    with: .init(
        delegateClass: <YourSessionDelegate>.self
    )
)

let session = URLSession(
    configuration: .default,
    delegate: <YourSessionDelegate>(),
    delegateQueue: nil
)
DDURLSessionInstrumentationConfiguration *config = [[DDURLSessionInstrumentationConfiguration alloc] initWithDelegateClass:[<YourSessionDelegate> class]];
[DDURLSessionInstrumentation enableWithConfiguration:config];

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                      delegate:[[<YourSessionDelegate> alloc] init]
                                                 delegateQueue:nil];

Notes:

  • Without URLSessionInstrumentation, network requests are still tracked. Enabling it provides detailed timing breakdown for performance analysis.
  • Response data is available in the resourceAttributesProvider callback (set in RUM.Configuration.URLSessionTracking) for tasks with completion handlers in automatic mode, and for all tasks after enabling URLSessionInstrumentation.
  • To filter out specific requests from being tracked, use the resourceEventMapper in RUM.Configuration (see Modify or drop RUM events).

Be mindful of delegate retention. While Datadog instrumentation does not create memory leaks directly, it relies on URLSession delegates. According to Apple documentation: "The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session by calling the invalidateAndCancel() or finishTasksAndInvalidate() method, your app leaks memory until it exits." To avoid memory leaks, make sure to invalidate any URLSession instances you no longer need.

If you have more than one delegate type in your app that you want to instrument, you can call URLSessionInstrumentation.enable(with:) for each delegate type.

Also, you can configure first party hosts using urlSessionTracking. This classifies resources that match the given domain as "first party" in RUM and propagates tracing information to your backend (if you have enabled Tracing). Network traces are sampled with an adjustable sampling rate. A sampling of 20% is applied by default.

For instance, you can configure example.com as the first party host and enable both RUM and Tracing features:


import DatadogRUM

RUM.enable(
  with: RUM.Configuration(
    applicationID: "<rum application id>",
    uiKitViewsPredicate: DefaultUIKitRUMViewsPredicate(),
    uiKitActionsPredicate: DefaultUIKitRUMActionsPredicate(),
    urlSessionTracking: RUM.Configuration.URLSessionTracking(
        firstPartyHostsTracing: .trace(hosts: ["example.com"], sampleRate: 20)
    )
  )
)

URLSessionInstrumentation.enable(
    with: .init(
        delegateClass: <YourSessionDelegate>.self
    )
)

let session = URLSession(
    configuration: .default,
    delegate: <YourSessionDelegate>(),
    delegateQueue: nil
)

This tracks all requests sent with the instrumented session. Requests matching the example.com domain are marked as "first party" and tracing information is sent to your backend to connect the RUM resource with its Trace.

@import DatadogRUM;

DDRUMConfiguration *configuration = [[DDRUMConfiguration alloc] initWithApplicationID:@"<rum application id>"];
DDRUMURLSessionTracking *urlSessionTracking = [DDRUMURLSessionTracking new];
[urlSessionTracking setFirstPartyHostsTracing:[DDRUMFirstPartyHostsTracing alloc] initWithHosts:@[@"example.com"] sampleRate:20];
[configuration setURLSessionTracking:urlSessionTracking];

[DDRUM enableWith:configuration];

To add custom attributes to resources, use the URLSessionTracking.resourceAttributesProvider option when enabling the RUM. By setting attributes provider closure, you can return additional attributes to be attached to tracked resource.

For instance, you may want to add HTTP request and response headers to the RUM resource:

RUM.enable(
  with: RUM.Configuration(
    ...
    urlSessionTracking: RUM.Configuration.URLSessionTracking(
        resourceAttributesProvider: { request, response, data, error in
            return [
                "request.headers" : redactedHeaders(from: request),
                "response.headers" : redactedHeaders(from: response)
            ]
        }
    )
  )
)

If you don't want to track requests, you can disable URLSessionInstrumentation for the delegate type:

URLSessionInstrumentation.disable(delegateClass: <YourSessionDelegate>.self)
[DDURLSessionInstrumentation disableWithDelegateClass:[<YourSessionDelegate> class]];

Apollo instrumentation

Instrumenting Apollo in your iOS application gives RUM visibility into GraphQL errors and performance. Because GraphQL requests all go to a single endpoint and often return 200 OK even on errors, default HTTP instrumentation lacks context. It lets RUM capture the operation name, operation type, and variables (and optionally the payload). This provides more detailed context for each network request.

This integration supports both Apollo iOS 1.0+ and Apollo iOS 2.0+. Follow the instructions for the Apollo iOS version you have below.

  1. Set up RUM monitoring with Datadog iOS RUM.

  2. Add the following to your application's Package.swift file:

    dependencies: [
        // For Apollo iOS 1.0+
        .package(url: "https://github.com/DataDog/dd-sdk-ios-apollo-interceptor", .upToNextMajor(from: "1.0.0"))
    
        // For Apollo iOS 2.0+
        .package(url: "https://github.com/DataDog/dd-sdk-ios-apollo-interceptor", .upToNextMajor(from: "2.0.0"))
    ]
    

    Alternatively, you can add it using Xcode:

    1. Go to FileAdd Package Dependencies.
    2. Enter the repository URL: https://github.com/DataDog/dd-sdk-ios-apollo-interceptor.
    3. Select the package version that matches your Apollo major version (choose 1.x.x for Apollo iOS 1.0+ or 2.x.x for Apollo iOS 2.0+).
  3. Set up network instrumentation based on your Apollo iOS version:

Set up network instrumentation for Apollo's built-in URLSessionClient:

import Apollo

URLSessionInstrumentation.enable(with: .init(delegateClass: URLSessionClient.self))

Add the Datadog interceptor to your Apollo Client setup:

import Apollo
import DatadogApollo

class CustomInterceptorProvider: DefaultInterceptorProvider {
    override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
        var interceptors = super.interceptors(for: operation)
        interceptors.insert(DatadogApolloInterceptor(), at: 0)
        return interceptors
    }
}

Configure network instrumentation using the provided DatadogApolloDelegate and DatadogApolloURLSession:

import Apollo
import DatadogApollo
import DatadogCore

// Create the Datadog delegate
let delegate = DatadogApolloDelegate()

// Create the custom URLSession wrapper
let customSession = DatadogApolloURLSession(
    configuration: .default,
    delegate: delegate
)

// Enable Datadog instrumentation for the delegate
URLSessionInstrumentation.enable(
    with: .init(delegateClass: DatadogApolloDelegate.self)
)

// Configure Apollo Client with the custom session
let networkTransport = RequestChainNetworkTransport(
    urlSession: customSession,
    interceptorProvider: NetworkInterceptorProvider(),
    store: store,
    endpointURL: url
)

Create an interceptor provider with the Datadog interceptor:

import Apollo
import DatadogApollo

struct NetworkInterceptorProvider: InterceptorProvider {
    func graphQLInterceptors<Operation>(for operation: Operation) -> [any GraphQLInterceptor] where Operation : GraphQLOperation {
        return [DatadogApolloInterceptor()] + DefaultInterceptorProvider.shared.graphQLInterceptors(for: operation)
    }
}

This lets Datadog RUM extract the operation type, name, variables, and payloads (optional) automatically from the requests to enrich GraphQL Requests RUM Resources.

  • The integration supports Apollo iOS versions 1.0+ and 2.0+.

  • The query and mutation type operations are tracked; subscription operations are not.

  • GraphQL payload sending is disabled by default. To enable it, set the sendGraphQLPayloads flag in the DatadogApolloInterceptor constructor as follows:

    let datadogInterceptor = DatadogApolloInterceptor(sendGraphQLPayloads: true)
    

Automatically track errors

All "error" and "critical" logs sent with Logger are automatically reported as RUM errors and linked to the current RUM view:

import DatadogLogs

let logger = Logger.create()

logger.error("message")
logger.critical("message")
@import DatadogLogs;

DDLogger *logger = [DDLogger create];
[logger error:@"message"];
[logger critical:@"message"];

Similarly, all finished spans marked as error are reported as RUM errors:

import DatadogTrace

let span = Tracer.shared().startSpan(operationName: "operation")
// ... capture the `error`
span.setError(error)
span.finish()
// ... capture the `error`
id<OTSpan> span = [[DDTracer shared] startSpan:@"operation"];
[span setError:error];
[span finish];

Modify or drop RUM events

To modify attributes of a RUM event before it is sent to Datadog or to drop an event entirely, use the Event Mappers API when configuring the RUM iOS SDK:

let configuration = RUM.Configuration(
    applicationID: "<rum application id>",
    viewEventMapper: { RUMViewEvent in
        return RUMViewEvent
    }
    resourceEventMapper: { RUMResourceEvent in
        return RUMResourceEvent
    }
    actionEventMapper: { RUMActionEvent in
        return RUMActionEvent
    }
    errorEventMapper: { RUMErrorEvent in
        return RUMErrorEvent
    }
    longTaskEventMapper: { RUMLongTaskEvent in
        return RUMLongTaskEvent
    }
)
DDRUMConfiguration *configuration = [[DDRUMConfiguration alloc] initWithApplicationID:@"<rum application id>"];

[configuration setViewEventMapper:^DDRUMViewEvent * _Nonnull(DDRUMViewEvent * _Nonnull RUMViewEvent) {
    return RUMViewEvent;
}];

[configuration setErrorEventMapper:^DDRUMErrorEvent * _Nullable(DDRUMErrorEvent * _Nonnull RUMErrorEvent) {
    return RUMErrorEvent;
}];

[configuration setResourceEventMapper:^DDRUMResourceEvent * _Nullable(DDRUMResourceEvent * _Nonnull RUMResourceEvent) {
    return RUMResourceEvent;
}];

[configuration setActionEventMapper:^DDRUMActionEvent * _Nullable(DDRUMActionEvent * _Nonnull RUMActionEvent) {
    return RUMActionEvent;
}];

[configuration setLongTaskEventMapper:^DDRUMLongTaskEvent * _Nullable(DDRUMLongTaskEvent * _Nonnull RUMLongTaskEvent) {
    return RUMLongTaskEvent;
}];

Each mapper is a Swift closure with a signature of (T) -> T?, where T is a concrete RUM event type. This allows changing portions of the event before it is sent.

For example, to redact sensitive information in a RUM Resource's url, implement a custom redacted(_:) -> String function and use it in resourceEventMapper:

let configuration = RUM.Configuration(
    applicationID: "<rum application id>",
    resourceEventMapper: { RUMResourceEvent in
        var RUMResourceEvent = RUMResourceEvent
        RUMResourceEvent.resource.url = redacted(RUMResourceEvent.resource.url)
        return RUMResourceEvent
    }
)
DDRUMConfiguration *configuration = [[DDRUMConfiguration alloc] initWithApplicationID:@"<rum application id>"];

[configuration setResourceEventMapper:^DDRUMResourceEvent * _Nullable(DDRUMResourceEvent * _Nonnull RUMResourceEvent) {
    return RUMResourceEvent;
}];

Returning nil from the error, resource, or action mapper drops the event entirely; the event is not sent to Datadog. The value returned from the view event mapper must not be nil (to drop views, customize your implementation of UIKitRUMViewsPredicate; read more in tracking views automatically).

Depending on the event's type, only some specific properties can be modified:

Event TypeAttribute keyDescription
RUMActionEventRUMActionEvent.action.target?.nameName of the action.
RUMActionEvent.view.urlURL of the view linked to this action.
RUMErrorEventRUMErrorEvent.error.messageError message.
RUMErrorEvent.error.stackStacktrace of the error.
RUMErrorEvent.error.resource?.urlURL of the resource the error refers to.
RUMErrorEvent.view.urlURL of the view linked to this error.
RUMResourceEventRUMResourceEvent.resource.urlURL of the resource.
RUMResourceEvent.view.urlURL of the view linked to this resource.
RUMViewEventRUMViewEvent.view.nameName of the view.
RUMViewEvent.view.urlURL of the view.
RUMViewEvent.view.referrerURL that linked to the initial view of the page.

Retrieve the RUM session ID

Retrieving the RUM session ID can be helpful for troubleshooting. For example, you can attach the session ID to support requests, emails, or bug reports so that your support team can later find the user session in Datadog.

You can access the RUM session ID at runtime without waiting for the sessionStarted event:

RumMonitor.shared().currentSessionID(completion: { sessionId in
  currentSessionId = sessionId
})

To be compliant with the GDPR regulation, the RUM iOS SDK requires the tracking consent value at initialization.

The trackingConsent setting can be one of the following values:

  1. .pending: The RUM iOS SDK starts collecting and batching the data but does not send it to Datadog. The RUM iOS SDK waits for the new tracking consent value to decide what to do with the batched data.
  2. .granted: The RUM iOS SDK starts collecting the data and sends it to Datadog.
  3. .notGranted: The RUM iOS SDK does not collect any data. No logs, traces, or RUM events are sent to Datadog.

To change the tracking consent value after the RUM iOS SDK is initialized, use the Datadog.set(trackingConsent:) API call. The RUM iOS SDK changes its behavior according to the new value.

For example, if the current tracking consent is .pending:

  • If you change the value to .granted, the RUM iOS SDK sends all current and future data to Datadog;
  • If you change the value to .notGranted, the RUM iOS SDK wipes all current data and does not collect future data.

Add user properties

You can use the Datadog.addUserExtraInfo(_:) API to append extra user properties to previously set properties.

import DatadogCore

Datadog.addUserExtraInfo(["company": "Foo"])

Data management

The iOS SDK first stores events locally and only uploads events when the intake specifications conditions are met.

Clear all data

You have the option of deleting all unsent data stored by the SDK with the Datadog.clearAllData() API.

import DatadogCore

Datadog.clearAllData()

Stop data collection

You can use the Datadog.stopInstance() API to stop a named SDK instance (or the default instance if the name is nil) from collecting and uploading data further.

import DatadogCore

Datadog.stopInstance()

Calling this method disables the SDK and all active features, such as RUM. To resume data collection, you must reinitialize the SDK. You can use this API if you want to change configurations dynamically.

If you have not set up the Datadog Flutter SDK for RUM yet, follow the in-app setup instructions or see the RUM Flutter setup documentation. Learn how to set up OpenTelemetry with RUM Flutter. For additional manual instrumentation functions, such as automatic view tracking, see Flutter Libraries for RUM.

Initialization parameters

You can specify the following parameters in your configuration when initializing the SDK.

clientToken
Required
Type: String
A client token for RUM or logging/APM. You can obtain this token in Datadog.
env
Required
Type: String
The environment name sent to Datadog. You can use env to filter events by environment (for example, staging or production).
site
Required
Type: Enum
The Datadog site that data is sent to. Enum values: us1, us3, us5, eu1, us1Fed, ap1, and ap2.
nativeCrashReportEnabled
Optional
Type: Boolean
Default: false
Enables native crash reporting.
service
Optional
Type: String
The service name for the application.
uploadFrequency
Optional
Type: Enum
Default: average
The frequency at which the Datadog SDK tries to upload data batches. Enum values: frequent, average, and rare.
batchSize
Optional
Type: Enum
Default: medium
Defines the Datadog SDK policy for batching data before uploading it to Datadog servers. Larger batches result in larger (but fewer) network requests. Smaller batches result in smaller (but more) network requests. Enum values: small, medium, and large.
batchProcessingLevel
Optional
Type: Enum
Default: medium
Defines the maximum number of batches processed sequentially without a delay, within one reading and uploading cycle. With higher levels, more data is sent in a single upload cycle, and more CPU and memory are used to process the data. With lower levels, less data is sent in a single upload cycle, and less CPU and memory are used to process the data. Enum values: low, medium, and high.
version
Optional
Type: String
The application's version number. Because version is a Datadog tag, it must comply with the rules in Defining Tags.
flavor
Optional
Type: String
The flavor (variant) of the application. For stack trace deobfuscation, this must match the flavor set during symbol upload.
firstPartyHosts
Optional
Type: List<String>
A list of first party hosts, used in conjunction with Datadog network tracking packages. Overrides any values set in firstPartyHostsWithTracinHeaders. To specify different headers per host, use firstPartyHostsWithTracingHeaders instead.
firstPartyHostsWithTracingHeaders
Optional
Type: Map<String, Set<TracingHeaderType>>
A map of first party hosts and the types of tracing headers Datadog automatically injects on resource calls, used in conjunction with Datadog network tracking packages. For example:
final configuration = DatadogConfiguration(
 clientToken: <CLIENT_TOKEN>,
 env: `prod`,
 site: DatadogSite.us1,
 firstPartyHostsWithTracingHeaders: {
  'example.com': {TracingHeaderType.b3},
 },
);
The TracingHeaderType enum has the following values:
rumConfiguration
Optional
Type: Object
See RUM configuration.

RUM configuration

Use the following parameters for the DatadogRumConfiguration class.

applicationId
Required
Type: String
The RUM application ID.
sessionSamplingRate
Optional
Type: Double
Default: 100.0
The sampling rate for RUM sessions. Must be between 0.0 (no RUM events are sent) and 100.0 (all RUM events are sent).
traceSampleRate
Optional
Type: Double
Default: 20.0
The sampling rate for resource tracing. Must be between 0.0 (no resources include APM tracing) and 100.0 (all resources include APM tracing).
traceContextInjection
Optional
Type: Enum
Default: all
The strategy for injecting trace context into requests. Enum values can be all (inject trace context into all requests) or sampled (inject trace context into only sampled requests).
detectLongTasks
Optional
Type: Boolean
Default: true
Enable or disable long task detection. This capability attempts to detect when an application is doing too much work on the main isolate or native thread, which could prevent your app from rendering at a smooth framerate.
longTaskThreshold
Optional
Type: Double
Default: 0.1
The amount of elapsed time that distinguishes a long task, in seconds. If the main isolate takes more than this amount of time to process a microtask, it appears as a long task in Datadog RUM Explorer. Minimum value: 0.02. On Flutter Web, which always uses a value of 0.05 seconds, this argument is ignored.
trackFrustrations
Optional
Type: Boolean
Default: true
Enables automatic collection of user frustrations.
vitalUpdateFrequency
Optional
Type: Enum
Default: average
The preferred frequency for collecting mobile vitals. Enum values: frequent (100ms),average (500ms), and rare (1000ms). To disable mobile vitals collection, set this parameter to null.
reportFlutterPerformance
Optional
Type: Boolean
Default: false
Enables reporting Flutter-specific performance metrics, including build and raster times.
customEndpoint
Optional
Type: String
A custom endpoint for sending RUM data.
telemetrySampleRate
Optional
Type: Double
Default: 20.0
The sampling rate for telemetry data, such as errors and debug logs.

Tracking from background isolates

Starting with v3, Datadog Flutter SDK is capable of monitoring from multiple isolates, but monitoring must be initialized from the background isolate:

When initializing your background isolate, call DatadogSdk.instance.attachToBackgroundIsolate. For example:

Future<void> _spawnIsolate() async {
    final receivePort = ReceivePort();
    receivePort.listen((message) {
      //
    });
    await Isolate.spawn(_backgroundWork, receivePort.sendPort);
  }

void _backgroundWork(SendPort port) async {
  await DatadogSdk.instance.attachToBackgroundIsolate();

  // Your background work
}

attachToBackgroundIsolate must be called after Datadog is initialized in your main isolate, otherwise the call silently fails and tracking is not available.

If you are using Datadog Tracking HTTP Client to automatically track resources, attachToBackgroundIsolate automatically starts tracking resources from the calling isolate. However, using Client from the http package or Dio requires you to re-initialize HTTP tracking for those packages from the background isolate.

Automatically track resources

Use the Datadog Tracking HTTP Client package to enable automatic tracking of resources and HTTP calls from your views.

Add the package to your pubspec.yaml and add the following to your initialization file:

final configuration = DatadogConfiguration(
  // configuration
  firstPartyHosts: ['example.com'],
)..enableHttpTracking()

Note: The Datadog Tracking HTTP Client modifies HttpOverrides.global. If you are using your own custom HttpOverrides, you may need to inherit from DatadogHttpOverrides. In this case, you do not need to call enableHttpTracking. Versions of datadog_tracking_http_client >= 1.3 check the value of HttpOverrides.current and use this for client creation, so you only need to make sure to initialize HttpOverrides.global prior to initializing Datadog.

To enable Datadog distributed tracing, you must set the DatadogConfiguration.firstPartyHosts property in your configuration object to a domain that supports distributed tracing. You can also modify the sampling rate for distributed tracing by setting the traceSampleRate on your DatadogRumConfiguration.

  • firstPartyHosts does not allow wildcards, but matches any subdomains for a given domain. For example, api.example.com matches staging.api.example.com and prod.api.example.com, not news.example.com.

  • DatadogRumConfiguration.traceSampleRate sets a default sampling rate of 20%. If you want all resources requests to generate a full distributed trace, set this value to 100.0.

Track resources from other packages

While Datadog Tracking HTTP Client can track most common network calls in Flutter, Datadog supplies packages for integration into specific networking libraries, including gRPC, GraphQL and Dio. For more information about these libraries, see Integrated Libraries.

Enrich user sessions

Flutter RUM automatically tracks attributes such as user activity, views (using the DatadogNavigationObserver), errors, native crashes, and network requests (using the Datadog Tracking HTTP Client). See the RUM Data Collection documentation to learn about the RUM events and default attributes. You can further enrich user session information and gain finer control over the attributes collected by tracking custom events.

Notify the SDK that your view finished loading

iOS RUM tracks the time it takes for your view to load. To notify the SDK that your view has finished loading, call the addViewLoadingTime method on DatadogRum. Call this method when your view is fully loaded and ready to be displayed to the user:

  DatadogSdk.instance.rum?.addViewLoadingTime(override);

Use the override option to replace the previously calculated loading time for the current view.

After the loading time is sent, it is accessible as @view.loading_time and is visible in the RUM UI.

Note: This API is still experimental and might change in the future.

Add your own performance timing

In addition to RUM's default attributes, you can measure where your application is spending its time by using DdRum.addTiming. The timing measure is relative to the start of the current RUM view.

For example, you can time how long it takes for your hero image to appear:

void _onHeroImageLoaded() {
    DatadogSdk.instance.rum?.addTiming("hero_image");
}

After you set the timing, it is accessible as @view.custom_timings.<timing_name>. For example, @view.custom_timings.hero_image.

To create visualizations in your dashboards, create a measure first.

Track user actions

You can track specific user actions such as taps, clicks, and scrolls using DdRum.addAction.

To manually register instantaneous RUM actions such as RumActionType.tap, use DdRum.addAction(). For continuous RUM actions such as RumActionType.scroll, use DdRum.startAction() or DdRum.stopAction().

For example:

void _downloadResourceTapped(String resourceName) {
    DatadogSdk.instance.rum?.addAction(
        RumActionType.tap,
        resourceName,
    );
}

When using DdRum.startAction and DdRum.stopAction, the type action must be the same for the Datadog Flutter SDK to match an action's start with its completion.

Track custom resources

In addition to tracking resources automatically using the Datadog Tracking HTTP Client, you can track specific custom resources such as network requests or third-party provider APIs using the following methods:

  • DdRum.startResource
  • DdRum.stopResource
  • DdRum.stopResourceWithError
  • DdRum.stopResourceWithErrorInfo

For example:

// in your network client:

DatadogSdk.instance.rum?.startResource(
    "resource-key",
    RumHttpMethod.get,
    url,
);

// Later

DatadogSdk.instance.rum?.stopResource(
    "resource-key",
    200,
    RumResourceType.image
);

The String used for resourceKey in both calls must be unique for the resource you are calling in order for the Flutter Datadog SDK to match a resource's start with its completion.

Track custom errors

To track specific errors, notify DdRum when an error occurs with the message, source, exception, and additional attributes.

DatadogSdk.instance.rum?.addError("This is an error message.");

Track custom global attributes

In addition to the default RUM attributes captured by the Datadog Flutter SDK automatically, you can choose to add additional contextual information (such as custom attributes) to your RUM events to enrich your observability within Datadog.

Custom attributes allow you to filter and group information about observed user behavior (such as the cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

Set a custom global attribute

To set a custom global attribute, use DdRum.addAttribute.

  • To add or update an attribute, use DdRum.addAttribute.
  • To remove the key, use DdRum.removeAttribute.

Track user sessions

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User API in the RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use DatadogSdk.setUserInfo.

For example:

DatadogSdk.instance.setUserInfo("1234", "John Doe", "john@doe.com");

Add custom user attributes

You can add custom attributes to your user session. This additional information is automatically applied to logs, traces, and RUM events.

To remove an existing attribute, set it to null.

For example:

DatadogSdk.instance.addUserExtraInfo({
 'attribute_1': 'foo',
 'attribute_2': null,
});

Clear all data

Use clearAllData to clear all data that has not been sent to Datadog.

DatadogSdk.instance.clearAllData();

Modify or drop RUM events

Note: This feature is not yet available for Flutter web applications.

To modify attributes of a RUM event before it is sent to Datadog or to drop an event entirely, use the Event Mappers API when configuring the Flutter RUM SDK:

final config = DatadogConfiguration(
    // other configuration...
    rumConfiguration: DatadogRumConfiguration(
        applicationId: '<YOUR_APPLICATION_ID>',
        rumViewEventMapper = (event) => event,
        rumActionEventMapper = (event) => event,
        rumResourceEventMapper = (event) => event,
        rumErrorEventMapper = (event) => event,
        rumLongTaskEventMapper = (event) => event,
    ),
);

Each mapper is a function with a signature of (T) -> T?, where T is a concrete RUM event type. This allows changing portions of the event before it is sent, or dropping the event entirely.

For example, to redact sensitive information in a RUM Resource's url, implement a custom redacted function and use it in rumResourceEventMapper:

    rumResourceEventMapper = (event) {
        var resourceEvent = resourceEvent
        resourceEvent.resource.url = redacted(resourceEvent.resource.url)
        return resourceEvent
    }

Returning null from the error, resource, or action mapper drops the event entirely; the event is not sent to Datadog. The value returned from the view event mapper must not be null.

Depending on the event's type, only some specific properties can be modified:

Event TypeAttribute keyDescription
RumViewEventviewEvent.view.urlURL of the view.
viewEvent.view.referrerReferrer of the view.
RumActionEventactionEvent.action.target?.nameName of the action.
actionEvent.view.referrerReferrer of the view linked to this action.
actionEvent.view.urlURL of the view linked to this action.
RumErrorEventerrorEvent.error.messageError message.
errorEvent.error.stackStacktrace of the error.
errorEvent.error.resource?.urlURL of the resource the error refers to.
errorEvent.view.referrerReferrer of the view linked to this action.
errorEvent.view.urlURL of the view linked to this error.
RumResourceEventresourceEvent.resource.urlURL of the resource.
resourceEvent.view.referrerReferrer of the view linked to this action.
resourceEvent.view.urlURL of the view linked to this resource.

Retrieve the RUM session ID

Retrieving the RUM session ID can be helpful for troubleshooting. For example, you can attach the session ID to support requests, emails, or bug reports so that your support team can later find the user session in Datadog.

You can access the RUM session ID at runtime without waiting for the sessionStarted event:

final sessionId = await DatadogSdk.instance.rum?.getCurrentSessionId()

Flutter-specific performance metrics

To enable the collection of Flutter-specific performance metrics, set reportFlutterPerformance: true in DatadogRumConfiguration. Widget build and raster times are displayed in Mobile Vitals.

OpenTelemetry setup

All of Datadog's automatic network tracking packages (Datadog Tracking HTTP Client, gRPC Interceptor, GQL Link, and Dio Interceptor) support distributed traces through both automatic header generation and header ingestion. This section describes how to use OpenTelemetry with RUM Flutter.

Datadog header generation

When configuring your tracking client or gRPC Interceptor, you can specify the types of tracing headers you want Datadog to generate. For example, if you want to send b3 headers to example.com and tracecontext headers for myapi.names, you can do so with the following code:

final hostHeaders = {
    'example.com': { TracingHeaderType.b3 },
    'myapi.names': { TracingHeaderType.tracecontext}
};

You can use this object during initial configuration:

// For default Datadog HTTP tracing:
final configuration = DatadogConfiguration(
    // configuration
    firstPartyHostsWithTracingHeaders: hostHeaders,
);

You can then enable tracing as usual.

This information is merged with any hosts set on DatadogConfiguration.firstPartyHosts. Hosts specified in firstPartyHosts generate Datadog Tracing Headers by default.

Check first party hosts

To determine if a specific URI is a first party host, use isFirstPartyHost.

For example:

var host = 'example.com'
if (DatadogSdk.instance.isFirstPartyHost(host)){
 print('$host is a first party host.');
}

If you have not set up the SDK yet, follow the in-app setup instructions or see the React Native RUM setup documentation.

Jest testing

Testing apps using '@datadog/mobile-react-native' might require completing extra steps, since Native Modules do not exist in testing environments.

Datadog provides mocks for the '@datadog/mobile-react-native' package. To use them with Jest, add the following in your Jest setup file:

jest.mock('@datadog/mobile-react-native', () => {
  return require('@datadog/mobile-react-native/jest')
});

Interaction, error, and resource automated tracking is disabled in your tests if you initialize the SDK with the DatadogProvider component.

All SDK methods are mocked by jest.fn(), so you can assert that a Datadog SDK method was called:

import { DdLogs } from '@datadog/mobile-react-native';

describe('App', () => {
    it('calls DdLogs.debug on mount', () => {
        renderer.create(<App />);
        expect(DdLogs.debug).toHaveBeenCalledWith('app started');
    });
});

If you use a test runner other than Jest, you need to create the mocks for your test runner.

Initialization parameters

You can specify the following parameters in your configuration when initializing the SDK:

Core configuration

clientToken
Required
Type: String
A Datadog client token.
env
Required
Type: String
The application's environment, for example: prod, pre-prod, and staging. Follows the tag syntax requirements.
rumConfiguration
Optional
Type: RumConfiguration
The Datadog RUM configuration. RUM is disabled by default. See RUM configuration.
logsConfiguration
Optional
Default: undefined
Type: LogsConfiguration
The Datadog Logs configuration. Logs is disabled by default: use an empty configuration {} to enable. See Logs configuration.
traceConfiguration
Optional
Type: TraceConfiguration
The Datadog Trace configuration. Trace is disabled by default: use an empty configuration {} to enable. See Trace configuration.
site
Optional
Type: String
Default: US1
The Datadog site parameter of your organization.
service
Optional
Type: String
The service name for your application. Follows the tag syntax requirements.
verbosity
Optional
Type: SdkVerbosity
Default: undefined
Verbosity for internal SDK logging. Set to SdkVerbosity.DEBUG to debug your SDK implementation.
version
Optional
Type: String
The application's version. For example: 1.2.3, 6c44da20, and 2020.02.13. Follows the tag syntax requirements.
versionSuffix
Optional
Type: String
Add a suffix to the reported version of the app. Accepted characters are alphanumerics and _, -, :, ., /. Other special characters are converted to underscores. A dash (-) is automatically added between the version and the suffix. Follows the tag syntax requirements.
proxyConfig
Optional
Type: ProxyConfiguration
Optional proxy configuration.
uploadFrequency
Optional
Type: UploadFrequency
Default: UploadFrequency.AVERAGE
Sets the preferred frequency for uploading batches of data.
batchSize
Optional
Type: BatchSize
Default: BatchSize.MEDIUM
Defines the Datadog SDK policy when batching data together before uploading it to Datadog servers. Smaller batches mean smaller but more network requests, whereas larger batches mean fewer but larger network requests.

RUM configuration

applicationId
Required
Type: String
The RUM application ID.
trackInteractions
Optional
Type: Boolean
Default: false
Enables automatic collection of user actions.
trackResources
Optional
Type: Boolean
Default: false
Enables collection of resource events.
trackErrors
Optional
Type: Boolean
Default: false
Enables collection of React Native crashes.
trackFrustrations
Optional
Type: Boolean
Default: true
Enables automatic collection of user frustrations. Only error taps are supported. Implies trackInteractions: true.
sessionSampleRate
Optional
Type: Number
Default: 100
The percentage of sessions to track: 100 for all, 0 for none. Only tracked sessions send RUM events.
resourceTraceSampleRate
Optional
Type: Number
Default: 100
The percentage of requests to trace: 100 for all, 0 for none. For more information, see Connect RUM and Traces.
nativeCrashReportEnabled
Optional
Type: Boolean
Default: false
Enables crash reporting for native platforms (iOS, Android).
nativeLongTaskThresholdMs
Optional
Type: Number | false
Default: 200
The threshold for native long tasks reporting in milliseconds. Setting it to 0 or false disables native long task reporting. Values below 100 are raised to 100. Values above 5000 are lowered to 5000.
nativeViewTracking
Optional
Type: Boolean
Default: false
Enables native views tracking. Set to true if you use a custom navigation system relying on native views.
nativeInteractionTracking
Optional
Type: Boolean
Default: false
Enables native interaction tracking. Set to true if you want to track interactions on native screens.
firstPartyHosts
Optional
Type: List
Default: []
List of your backends hosts to enable tracing with. For more information, see Connect RUM and Traces.
telemetrySampleRate
Optional
Type: Number
Default: 20
Telemetry data (such as errors and debug logs) about SDK execution is sent to Datadog to detect and solve potential issues. Set this option to 0 to opt out from telemetry collection.
longTaskThresholdMs
Optional
Type: Number | false
Default: 0
The threshold for JavaScript long tasks reporting in milliseconds. Setting it to 0 or false disables JavaScript long task reporting. Values below 100 are raised to 100. Values above 5000 are lowered to 5000.
vitalsUpdateFrequency
Optional
Type: VitalsUpdateFrequency
Default: VitalsUpdateFrequency.AVERAGE
Sets the preferred frequency for collecting mobile vitals.
trackBackgroundEvents
Optional
Type: Boolean
Default: false
Enables tracking of RUM event when no RUM View is active. By default, background events are not tracked. Enabling this feature might increase the number of sessions tracked and impact your billing.
useAccessibilityLabel
Optional
Type: Boolean
Default: true
Determines whether the accessibility labels are used to name RUM actions (default is true).
trackNonFatalAnrs
Optional
Type: Boolean
Default: true on Android 29 and below, false on Android 30+.
Enables tracking of non-fatal ANRs on Android. By default, the reporting of non-fatal ANRs on Android 30+ is disabled because it would create too much noise over fatal ANRs. On Android 29 and below, however, the reporting of non-fatal ANRs is enabled by default, as fatal ANRs cannot be reported on those versions.
trackWatchdogTerminations
Optional
Type: Boolean
Default: false
Determines whether the SDK should track application termination by the watchdog on iOS.
trackMemoryWarnings
Optional
Type: Boolean
Default: true
Enables tracking of memory warnings as RUM events on iOS. When enabled, the SDK automatically records a RUM event each time the app receives a memory warning from the operating system.
appHangThreshold
Optional
Type: Number
Default: undefined
The app hang threshold in seconds for non-fatal app hangs on iOS. App hangs are an iOS-specific type of error that happens when the application is unresponsive for too long. By default, app hangs reporting is disabled, but you can enable it and set your own threshold to monitor app hangs that last more than a specified duration by using this parameter. Set the appHangThreshold parameter to the minimal duration you want app hangs to be reported. For example, enter 0.25 to report hangs lasting at least 250 ms. See Configure the app hang threshold for more guidance on what to set this value to.
initialResourceThreshold
Optional
Type: Number
Default: 0.1 (seconds)
The amount of time after a view starts where a Resource should be considered when calculating Time to Network-Settled (TNS). TNS is calculated using all resources that start within the specified threshold, in seconds.
errorEventMapper
Optional
Type: ErrorEventMapper
Default: null
Custom function to modify the attributes of a RUM Error event before it is sent to Datadog.
actionEventMapper
Optional
Type: ActionEventMapper
Default: null
Custom function to modify the attributes of a RUM Action event before it is sent to Datadog.
resourceEventMapper
Optional
Type: ResourceEventMapper
Default: null
Custom function to modify the attributes of a RUM Resource event before it is sent to Datadog.
customEndpoint
Optional
Type: String
Default: undefined
Sets a target custom server for RUM.

Logs configuration

bundleLogsWithRum
Optional
Type: Boolean
Default: true
Enables RUM correlation with logs (default is true).
bundleLogsWithTraces
Optional
Type: Boolean
Default: true
Enables trace correlation with logs.
logEventMapper
Optional
Type: LogEventMapper
Default: null
Custom function to modify the attributes of a Log event before it is sent to Datadog.
customEndpoint
Optional
Type: String
Default: undefined
Sets a target custom server for Logs.

Trace configuration

customEndpoint
Optional
Type: String
Default: undefined
Sets a target custom server for Traces.

Manual instrumentation

If automatic instrumentation doesn't suit your needs, you can manually create RUM Events and Logs:

Send logs

When you instrument your code to send logs, it can include debug, info, warn, or error details:

DdLogs.debug('Lorem ipsum dolor sit amet…', {});
DdLogs.info('Lorem ipsum dolor sit amet…', {});
DdLogs.warn('Lorem ipsum dolor sit amet…', {});
DdLogs.error('Lorem ipsum dolor sit amet…', {});

Manually track RUM views

To manually track RUM Views, provide a view key, view name, and action name at initialization. Depending on your needs, you can choose one of the following strategies:

DdRum.startView('<view-key>', 'View Name', {}, Date.now());
//…
DdRum.stopView('<view-key>', { custom: 42 }, Date.now());

Manually track RUM actions

You can manually track RUM actions:

DdRum.addAction(RumActionType.TAP, 'action name', {}, Date.now());

To track a continuous action:

DdRum.startAction(RumActionType.TAP, 'action name', {}, Date.now());
//...
DdRum.stopAction({}, Date.now());

Manually track RUM errors

You can manually track RUM errors:

DdRum.addError('<message>', ErrorSource.SOURCE, '<stacktrace>', {}, Date.now());

Manually track RUM resources

You can manually track RUM resources:

DdRum.startResource('<res-key>', 'GET', 'http://www.example.com/api/v1/test', {}, Date.now());
//...
DdRum.stopResource('<res-key>', 200, 'xhr', (size = 1337), {}, Date.now());

Notify the SDK that your view finished loading

You can notify the SDK that your view has finished loading by calling the addViewLoadingTime method on DdRum. Call this method when your view is fully loaded and ready to be displayed to the user:

DdRum.addViewLoadingTime(true);

Use the overwrite parameter to replace the previously calculated loading time for the current view.

After the loading time is sent, it is accessible as @view.loading_time and is visible in the RUM UI.

Note: This API is experimental.

Add custom timings

You can add custom timings:

DdRum.addTiming('<timing-name>');

Manually send spans

You can send spans manually:

const spanId = await DdTrace.startSpan('foo', { custom: 42 }, Date.now());
//...
DdTrace.finishSpan(spanId, { custom: 21 }, Date.now());

Track custom global attributes

You can attach user information to all RUM events to get more detailed information from your RUM sessions.

Track user sessions

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User API in RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.
usr.extraInfoObject(Optional) Include custom attributes such as subscription type, any user specific information that enhance user context in RUM sessions.

To identify user sessions, use the setUserInfo API, for example:

DdSdkReactNative.setUserInfo({
    id: '1337',
    name: 'John Smith',
    email: 'john@example.com',
    extraInfo: {
        type: 'premium'
    }
});

If you want to add or update user information, you can use the following code to modify the existing user's details.

DdSdkReactNative.addUserExtraInfo({
    hasPaid: 'true'
});

If you want to clear the user information (for example, when the user signs out), you can do so by calling the clearUserInfo API:

DdSdkReactNative.clearUserInfo();

Global attributes

You can keep global attributes to track information about a specific session, such as A/B testing configuration, ad campaign origin, or cart status. These attributes are attached to all future Logs, Spans, and RUM events.

Add multiple global attributes

Use addAttributes to add or update several attributes at once.

DdSdkReactNative.addAttributes({
    profile_mode: 'wall',
    chat_enabled: true,
    campaign_origin: 'example_ad_network'
});

Add a single global attribute

Use addAttribute when you want to add or update a single attribute.

DdSdkReactNative.addAttribute('profile_mode', 'wall');
DdSdkReactNative.addAttribute('chat_enabled', true);

If the attribute already exists, its value is overwritten.

Remove a single global attribute

Use removeAttribute to remove a specific attribute from the global context.

DdSdkReactNative.removeAttribute('campaign_origin');

After removal, the attribute is no longer attached to future Logs, Spans, or RUM events.

Remove multiple global attributes

Use removeAttributes to remove several attributes at once.

DdSdkReactNative.removeAttributes([
    'profile_mode',
    'chat_enabled'
]);

This is useful when cleaning up session-specific data, such as when a user logs out or exits a feature flow.

Track view navigation

Because React Native offers a wide range of libraries to create screen navigation, only manual view tracking is supported by default. To see RUM or Error tracking sessions populate in Datadog, you need to implement view tracking.

You can manually start and stop a view using the following startView() and stopView methods.

import {
    DdRum
} from '@datadog/mobile-react-native';

// Start a view with a unique view identifier, a custom view name, and an object to attach additional attributes to the view
DdRum.startView(
    '<view-key>', // <view-key> has to be unique, for example it can be ViewName-unique-id
    'View Name',
    { 'custom.foo': 'something' },
    Date.now()
);
// Stops a previously started view with the same unique view identifier, and an object to attach additional attributes to the view
DdRum.stopView('<view-key>', { 'custom.bar': 42 }, Date.now());

Use one of Datadog's integrations to automatically track views for the following libraries:

If you experience any issues setting up View tracking with @datadog/mobile-react-navigation you can see this Datadog example application as a reference.

Clear all data

Use clearAllData to clear all data that has not been sent to Datadog.

DdSdkReactNative.clearAllData();

Modify or drop RUM events

To modify attributes of a RUM event before it is sent to Datadog, or to drop an event entirely, use the Event Mappers API when configuring the RUM React Native SDK:

import {
    SdkVerbosity,
    DatadogProvider,
    DatadogProviderConfiguration,
    RumConfiguration,
    LogsConfiguration,
    TraceConfiguration
} from '@datadog/mobile-react-native';

const config = new DatadogProviderConfiguration(
    '<CLIENT_TOKEN>',
    '<ENVIRONMENT_NAME>',
    {
        rumConfiguration: {
            applicationId: '<APPLICATION_ID>',
            trackInteractions: true, // Track user interactions (such as a tap on buttons).
            trackResources: true, // Track XHR resources
            trackErrors: true, // Track errors
            // RUM Event Mappers
            errorEventMapper: (event) => event,
            resourceEventMapper: (event) => event,
            actionEventMapper: (event) => event
        },

        // Log Event Mappers
        logsConfiguration: {
            logEventMapper: (event) => event
        },

        traceConfiguration: {}
    }
)

Each mapper is a function with a signature of (T) -> T?, where T is a concrete RUM event type. This allows changing portions of the event before it is sent, or dropping the event entirely.

For example, to redact sensitive information from a RUM error message, implement a custom redacted function and use it in errorEventMapper:

config.rumConfiguration.errorEventMapper = (event) => {
    event.message = redacted(event.message);
    return event;
};

Returning null from the error, resource, or action mapper drops the event entirely; the event is not sent to Datadog.

Depending on the event type, only some specific properties can be modified:

Event TypeAttribute keyDescription
LogEventlogEvent.messageMessage of the log.
logEvent.contextCustom attributes of the log.
ActionEventactionEvent.contextCustom attributes of the action.
ErrorEventerrorEvent.messageError message.
errorEvent.sourceSource of the error.
errorEvent.stacktraceStacktrace of the error.
errorEvent.contextCustom attributes of the error.
errorEvent.timestampMsTimestamp of the error.
ResourceEventresourceEvent.contextCustom attributes of the resource.

Events include additional context:

Event TypeContext attribute keyDescription
LogEventlogEvent.additionalInformation.userInfoContains the global user info set by DdSdkReactNative.setUserInfo.
logEvent.additionalInformation.attributesContains the global attributes set by DdSdkReactNative.addAttributes.
ActionEventactionEvent.actionContextGestureResponderEvent corresponding to the action or undefined.
actionEvent.additionalInformation.userInfoContains the global user info set by DdSdkReactNative.setUserInfo.
actionEvent.additionalInformation.attributesContains the global attributes set by DdSdkReactNative.addAttributes.
ErrorEventerrorEvent.additionalInformation.userInfoContains the global user info set by DdSdkReactNative.setUserInfo.
errorEvent.additionalInformation.attributesContains the global attributes set by DdSdkReactNative.addAttributes.
ResourceEventresourceEvent.resourceContextXMLHttpRequest corresponding to the resource or undefined.
resourceEvent.additionalInformation.userInfoContains the global user info set by DdSdkReactNative.setUserInfo.
resourceEvent.additionalInformation.attributesContains the global attributes set by DdSdkReactNative.addAttributes.

Retrieve the RUM session ID

Retrieving the RUM session ID can be helpful for troubleshooting. For example, you can attach the session ID to support requests, emails, or bug reports so that your support team can later find the user session in Datadog.

You can access the RUM session ID at runtime with:

import { DdRum } from '@datadog/mobile-react-native';

const rumSessionId = await DdRum.getCurrentSessionId();

Resource timings

Resource tracking provides the following timings:

  • First Byte: The time between the scheduled request and the first byte of the response. This includes time for the request preparation on the native level, network latency, and the time it took the server to prepare the response.
  • Download: The time it took to receive a response.

Initializing asynchronously

If your app includes a lot of animations when it starts, running code during these animations might delay them on some devices. To delay the Datadog React Native SDK for RUM to run after all current animations are started, set the initializationMode to InitializationMode.ASYNC in your configuration:

import {
    DatadogProvider,
    DatadogProviderConfiguration,
    InitializationMode,
    RumConfiguration
} from '@datadog/mobile-react-native';

const datadogConfiguration = new DatadogProviderConfiguration(
    '<CLIENT_TOKEN>',
    '<ENVIRONMENT_NAME>',
    initializationMode: InitializationMode.ASYNC,
    rumConfiguration: {
        applicationId: '<APPLICATION_ID>'
    }
);

export default function App() {
    return (
        <DatadogProvider configuration={datadogConfiguration}>
            <Navigation />
        </DatadogProvider>
    );
}

This uses React Native's InteractionManager.runAfterInteractions to delay the animations.

All interactions with the RUM SDK (view tracking, actions, resources tracing, and so on) are still recorded and kept in a queue with a limit of 100 events.

Logs are not recorded and calling a DdLogs method before the actual initialization might break logging.

If you experience any issue setting up the asynchronous initialization of Datadog, see the example application.

Delaying the initialization

There may be situations where you want to wait before initializing the SDK. For example, when you want to use a different configuration based on the user role or to fetch the configuration from one of your servers.

In that case, you can auto-instrument your app from the start (automatically collect user interactions, XHR resources, and errors) and record up to 100 RUM and span events before initializing the SDK.

import {
    DatadogProvider,
    DatadogProviderConfiguration,
    PropagatorType
} from '@datadog/mobile-react-native';

const datadogAutoInstrumentation = {
    rumConfiguration: {
        resourceTraceSampleRate: 100,
        trackErrors: true,
        trackInteractions: true,
        trackResources: true,
        firstPartyHosts: [
            {
                match: 'example.com',
                propagatorTypes: [
                    PropagatorType.DATADOG,
                    PropagatorType.TRACECONTEXT
                ]
            }
        ],
    }
};

const initializeApp = async () => {
    const configuration = await fetchDatadogConfiguration(); // Fetches the configuration from one of your servers
    await DatadogProvider.initialize(configuration);
};

export default function App() {
    useEffect(() => initializeApp(), []);

    return (
        <DatadogProvider configuration={datadogAutoInstrumentation}>
            <Navigation />
        </DatadogProvider>
    );
}

Where your configuration has the following keys:

import { ProxyConfiguration, SdkVerbosity, TrackingConsent } from '@datadog/mobile-react-native';

const configuration = {
    clientToken: '<CLIENT_TOKEN>',
    env: '<ENVIRONMENT_NAME>',
    service: 'com.myapp', // Optional: set the reported service name. Default = package name / bundleIdentifier of your Android / iOS app respectively
    version: '1.0.0', // Optional: see overriding the reported version in the documentation. Default = VersionName / Version of your Android / iOS app respectively
    versionSuffix: 'codepush.v3', // Optional: see overriding the reported version in the documentation. Default = undefined
    trackingConsent: TrackingConsent.GRANTED, // Optional: disable collection if user has not granted consent for tracking. Default = TrackingConsent.GRANTED
    verbosity: SdkVerbosity.WARN, // Optional: let the SDK print internal logs (above or equal to the provided level). Default = undefined (no logs)
    proxyConfiguration: new ProxyConfiguration() // Optional: send requests through a proxy. Default = undefined,
    site: 'US1', // Optional: specify Datadog site. Default = 'US1'
    rumConfiguration: {
        applicationId: '<RUM_APPLICATION_ID>',
        sessionSampleRate: 80, // Optional: sample RUM sessions (here, 80% of session will be sent to Datadog). Default = 100%
        nativeViewTracking: true, // Optional: enables tracking of native views. Default = false
        nativeCrashReportEnabled: true, // Optional: enable native crash reports. Default = false
    }
};

Hybrid app monitoring

See Monitor hybrid React Native applications.

If you have not set up the SDK yet, follow the in-app setup instructions or see the Kotlin Multiplatform RUM setup documentation.

Enrich user sessions

Kotlin Multiplatform RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the RUM Data Collection documentation to learn about the RUM events and default attributes. You can further enrich user session information and gain finer control over the attributes collected by tracking custom events.

Custom views

In addition to tracking views automatically, you can also track specific distinct views (such as activities and fragments) manually. Stop tracking when the view is no longer visible.

// to start view
GlobalRumMonitor.get().startView(viewKey, viewName, viewAttributes)

// to stop view
GlobalRumMonitor.get().stopView(viewKey, viewAttributes)

Add your own performance timing

In addition to RUM's default attributes, you can measure where your application is spending its time by using the addTiming API. The timing measure is relative to the start of the current RUM view. For example, you can time how long it takes for your hero image to appear:

fun onHeroImageLoaded() {
    GlobalRumMonitor.get().addTiming("hero_image")
}

After the timing is sent, the timing is accessible as @view.custom_timings.<timing_name>. For example: @view.custom_timings.hero_image. You must create a measure before graphing it in RUM analytics or in dashboards.

Custom actions

In addition to tracking actions automatically, you can also track specific custom user actions (such as taps, clicks, and scrolls) with RumMonitor#addAction. For continuous action tracking (for example, tracking a user scrolling a list), use RumMonitor#startAction and RumMonitor#stopAction.

The action type should be one of the following: "custom", "click", "tap", "scroll", "swipe", "back".

fun onUserInteraction() {
    GlobalRumMonitor.get().addAction(actionType, name, actionAttributes)
}

Enrich resources

When tracking resources automatically, provide a custom RumResourceAttributesProvider instance to add custom attributes to each tracked network request/response. For example, if you want to track a network request's headers, create an implementation like the following, and pass it in the datadogKtorPlugin initialization call.

class CustomRumResourceAttributesProvider : RumResourceAttributesProvider {
    override fun onRequest(request: HttpRequestSnapshot) =
        request.headers.names().associateWith { request.headers[it] }.mapKeys { "header.$it" }

    override fun onResponse(response: HttpResponse) = emptyMap<String, Any?>()

    override fun onError(request: HttpRequestSnapshot, throwable: Throwable) = emptyMap<String, Any?>()
}

val ktorClient = HttpClient {
    install(
        datadogKtorPlugin(
            tracedHosts = mapOf(
                "example.com" to setOf(TracingHeaderType.DATADOG),
                "example.eu" to setOf(TracingHeaderType.DATADOG)
            ),
            rumResourceAttributesProvider = CustomRumResourceAttributesProvider()
        )
    )
}

Custom resources

In addition to tracking resources automatically, you can also track specific custom resources (such as network requests and third-party provider APIs) with methods (such as GET and POST) while loading the resource with RumMonitor#startResource. Stop tracking with RumMonitor#stopResource when it is fully loaded, or RumMonitor#stopResourceWithError if an error occurs while loading the resource.

fun loadResource() {
    GlobalRumMonitor.get().startResource(resourceKey, method, url, resourceAttributes)
    try {
        // do load the resource
        GlobalRumMonitor.get().stopResource(resourceKey, resourceKind, additionalAttributes)
    } catch (e: Exception) {
        GlobalRumMonitor.get().stopResourceWithError(resourceKey, message, origin, e)
    }
}

Note: stopResource / stopResourceWithError methods accepting NSURLConnection and NSError are also available from iOS source set.

Custom errors

To track specific errors, notify the monitor when an error occurs with the message, source, exception, and additional attributes. See the Attributes collected documentation.

GlobalRumMonitor.get().addError(message, source, throwable, attributes)

Note: addError method accepting NSError is also available from iOS source set.

Add user properties

You can use the addUserExtraInfo API to append extra user properties to previously set properties.

Datadog.addUserExtraInfo(extraInfo)

Event and data management

The Kotlin Multiplatform SDK first stores events. It only uploads these events when the intake specification conditions are met.

Clear all data

You have the option of deleting all unsent data stored by the SDK with the clearAllData API.

Datadog.clearAllData()

Stop data collection

You can use the stopInstance API to stop the SDK instance from collecting and uploading data further.

Datadog.stopInstance()

Set remote log threshold

You can define the minimum log level (priority) to send events to Datadog in a logger instance. If the log priority is below the one you set at this threshold, it does not get sent. The default value is to allow all.

val logger = Logger.Builder()
  .setRemoteLogThreshold(LogLevel.INFO)
  .build()

Track custom global attributes

In addition to the default RUM attributes captured by the RUM Kotlin Multiplatform SDK automatically, you can choose to add additional contextual information, such as custom attributes, to your RUM events to enrich your observability within Datadog. Custom attributes allow you to filter and group information about observed user behavior (such as cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

Track user sessions

Adding user information to your RUM sessions helps you to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User API in RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use the setUserInfo API, for example:

Datadog.setUserInfo('1234', 'John Doe', 'john@doe.com')

Track attributes

// Adds an attribute to all future RUM events
GlobalRumMonitor.get().addAttribute(key, value)

// Removes an attribute to all future RUM events
GlobalRumMonitor.get().removeAttribute(key)

Track background events

You can track events such as crashes and network requests when your application is in the background (for example, no active view is available).

Add the following snippet during RUM configuration:

.trackBackgroundEvents(true)

Tracking background events may lead to additional sessions, which can impact billing. For questions, contact Datadog support.

Initialization parameters

You can use the following methods in Configuration.Builder when creating the Datadog configuration to initialize the library:

useSite(DatadogSite)
Switches target data to EU, US1, US3, US5, US1_FED, AP1, and AP2 sites.
setBatchSize([SMALL|MEDIUM|LARGE])
Defines the individual batch size for requests sent to Datadog.
setUploadFrequency([FREQUENT|AVERAGE|RARE])
Defines the frequency for requests made to Datadog endpoints (if requests are available).
setBatchProcessingLevel(LOW|MEDIUM|HIGH)
Defines the number of batches sent in each upload cycle.
trackCrashes(Boolean)
Allows you to control whether JVM/iOS crashes are tracked or not. The default value is true.

You can use the following methods in RumConfiguration.Builder when creating the RUM configuration to enable RUM features:

Common configuration methods

trackLongTasks(durationThreshold)
Enables tracking tasks taking longer than durationThreshold on the main thread as long tasks in Datadog. See Automatically track long tasks for more information.
setVitalsUpdateFrequency([FREQUENT|AVERAGE|RARE|NEVER])
Sets the preferred frequency for collecting mobile vitals.
setSessionSampleRate(<sampleRate>)
Sets the RUM sessions sample rate. (A value of 0 means no RUM events are sent. A value of 100 means all sessions are kept.)
setSessionListener(RumSessionListener)
Sets a listener to be notified on when a new RUM Session starts.
setTelemetrySampleRate
The sampling rate for the SDK internal telemetry utilized by Datadog. This must be a value between 0 and 100. By default, this is set to 20.
setViewEventMapper
Sets the ViewEventMapper for the RUM ViewEvent. You can use this interface implementation to modify the ViewEvent attributes before serialization.
setResourceEventMapper
Sets the EventMapper for the RUM ResourceEvent. You can use this interface implementation to modify the ResourceEvent attributes before serialization.
setActionEventMapper
Sets the EventMapper for the RUM ActionEvent. You can use this interface implementation to modify the ActionEvent attributes before serialization.
setErrorEventMapper
Sets the EventMapper for the RUM ErrorEvent. You can use this interface implementation to modify the ErrorEvent attributes before serialization.
setLongTaskEventMapper
Sets the EventMapper for the RUM LongTaskEvent. You can use this interface implementation to modify the LongTaskEvent attributes before serialization.
trackBackgroundEvents
Enable/disable tracking RUM events when no activity is happening in the foreground. By default, background events are not tracked. Enabling this feature might increase the number of sessions tracked, and therefore your billing.
trackFrustrations
Enable/disable tracking of frustration signals.

Android configuration methods

These methods can be accessed only from Android source set.

trackNonFatalAnrs(Boolean)
Enables tracking non-fatal ANRs. This is enabled by default on Android API 29 and below, and disabled by default on Android API 30 and above.
trackUserInteractions(Array<ViewAttributesProvider>)
Enables tracking user interactions (such as tap, scroll, or swipe). The parameter also allows you to add custom attributes to the RUM Action events based on the widget with which the user interacted.
useViewTrackingStrategy(strategy)
Defines the strategy used to track views. See Automatically track views for more information.

iOS configuration methods

trackUiKitViews(UIKitRUMViewsPredicate)
Enable automatic tracking of UIViewControllers as RUM views. See Automatically track views for more information.
trackUiKitActions(UIKitRUMActionsPredicate)
Enable automatic tracking of UITouch events as RUM actions. The predicate implementation should return RUM action parameters if the given interaction should be accepted, or null to ignore it. By default, all touches are accepted.
setAppHangThreshold(Long)
Enables app hangs monitoring with the given threshold (in milliseconds). See Add app hang reporting for more information.

Automatically track views

Android

To automatically track your views (such as activities and fragments), provide a tracking strategy at initialization. Depending on your application's architecture, you can choose one of the following strategies:

ActivityViewTrackingStrategy
Every activity in your application is considered a distinct view.
FragmentViewTrackingStrategy
Every fragment in your application is considered a distinct view.
MixedViewTrackingStrategy
Every activity or fragment in your application is considered a distinct view.
NavigationViewTrackingStrategy
Recommended for Android Jetpack Navigation library users. Each Navigation destination is considered a distinct view.

For instance, to set each fragment as a distinct view, use the following configuration in your setup:

// in common source set
val rumConfig = RumConfiguration.Builder(applicationId)
  .apply {
    platformSpecificSetup(this)
  }
  .build()

internal expect fun platformSpecificSetup(
    rumConfigurationBuilder: RumConfiguration.Builder
)

// in Android source set
internal actual fun platformSpecificSetup(
    rumConfigurationBuilder: RumConfiguration.Builder
) {
    rumConfigurationBuilder.useViewTrackingStrategy(
        FragmentViewTrackingStrategy(...)
    )
}

For ActivityViewTrackingStrategy, FragmentViewTrackingStrategy, or MixedViewTrackingStrategy, you can filter which Fragment or Activity is tracked as a RUM View by providing a ComponentPredicate implementation in the constructor:

val strategy = ActivityViewTrackingStrategy(
    trackExtras = true,
    componentPredicate = object : ComponentPredicate<Activity> {
        override fun accept(component: Activity): Boolean {
            return true
        }

        override fun getViewName(component: Activity): String? = null
    }
)

Note: By default, the library is using ActivityViewTrackingStrategy. If you decide not to provide a view tracking strategy, you must manually send the views by calling the startView and stopView methods yourself.

iOS

To automatically track views (UIViewControllers), use the trackUiKitViews method when enabling RUM. By default, views are named with the view controller's class name. To customize it, provide your own implementation of the uiKitViewsPredicate that conforms to UIKitRUMViewsPredicate interface.

Inside the createView(viewController: UIViewController) implementation, your app should decide if a given UIViewController instance should start the RUM view (return value) or not (return null). The returned RUMView value must specify the name and may provide additional attributes for the created RUM view.

For instance, you can configure the predicate to use explicit type check for each view controller in your app:

class YourCustomPredicate: UIKitRUMViewsPredicate {

    override fun createView(viewController: UIViewController): RUMView? {
        return when (viewController) {
          is HomeViewController -> RUMView("Home")
          is DetailsViewController -> RUMView("Details")
          else -> null
        }
    }
}

You can even come up with a more dynamic solution depending on your app's architecture.

Note: By default, UIKit view tracking is not enabled.

Automatically track long tasks

Long running operations performed on the main thread can impact the visual performance and reactivity of your application. To track these operations, define the duration threshold above which a task is considered too long.

val rumConfig = RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(durationThreshold)
  .build()

For example, to replace the default 100 ms duration, set a custom threshold in your configuration.

val rumConfig = RumConfiguration.Builder(applicationId)
  // …
  .trackLongTasks(250L) // track tasks longer than 250ms as long tasks
  .build()

Modify or drop RUM events

To modify some attributes in your RUM events, or to drop some of the events entirely before batching, provide an implementation of EventMapper<T> when initializing the RUM Kotlin Multiplatform SDK:

val rumConfig = RumConfiguration.Builder(applicationId)
  // ...
  .setErrorEventMapper(rumErrorEventMapper)
  .setActionEventMapper(rumActionEventMapper)
  .setResourceEventMapper(rumResourceEventMapper)
  .setViewEventMapper(rumViewEventMapper)
  .setLongTaskEventMapper(rumLongTaskEventMapper)
  .build()

When implementing the EventMapper<T> interface, only some attributes are modifiable for each event type:

Event typeAttribute keyDescription
ViewEventview.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ActionEventaction.target.nameTarget name.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ErrorEventerror.messageError message.
error.stackStacktrace of the error.
error.resource.urlURL of the resource.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
ResourceEventresource.urlURL of the resource.
view.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.
LongTaskEventview.referrerURL that linked to the initial view of the page.
view.urlURL of the view.
view.nameName of the view.

Note: If you return null from the EventMapper<T> implementation, the event is dropped.

Retrieve the RUM session ID

Retrieving the RUM session ID can be helpful for troubleshooting. For example, you can attach the session ID to support requests, emails, or bug reports so that your support team can later find the user session in Datadog.

You can access the RUM session ID at runtime without waiting for the sessionStarted event:

GlobalRumMonitor.get().getCurrentSessionId { sessionId ->
  currentSessionId = sessionId
}

If you have not set up the SDK yet, follow the in-app setup instructions or see the Roku RUM setup documentation.

Track RUM resources

roUrlTransfer

Network requests made directly with a roUrlTransfer node must be tracked.

For synchronous requests, you can use Datadog's datadogroku_DdUrlTransfer wrapper to track the resource automatically. This wrapper supports most features of the roUrlTransfer component, but does not support anything related to async network calls.

For example, here's how to do a GetToString call:

    ddUrlTransfer = datadogroku_DdUrlTransfer(m.global.datadogRumAgent)
    ddUrlTransfer.SetUrl(url)
    ddUrlTransfer.EnablePeerVerification(false)
    ddUrlTransfer.EnableHostVerification(false)
    result = ddUrlTransfer.GetToString()

For asynchronous requests, automatic instrumentation is not supported. You need to track the resource manually. The following code snippet shows how to report the request as a RUM Resource:

sub performRequest()

    m.port = CreateObject("roMessagePort")
    request = CreateObject("roUrlTransfer")
    ' setup the node url, headers, …

    timer = CreateObject("roTimespan")
    timer.Mark()
    request.AsyncGetToString()

    while (true)
        msg = wait(1000, m.port)
        if (msg <> invalid)
            msgType = type(msg)
            if (msgType = "roUrlEvent")
                if (msg.GetInt() = 1) ' transfer complete
                    durationMs& = timer.TotalMilliseconds()
                    transferTime# = datadogroku_millisToSec(durationMs&)
                    httpCode = msg.GetResponseCode()
                    status = "ok"
                    if (httpCode < 0)
                        status = msg.GetFailureReason()
                    end if
                    resource = {
                        url: requestUrl
                        method: "GET"
                        transferTime: transferTime#
                        httpCode: httpCode
                        status: status
                    }
                    m.global.datadogRumAgent.callfunc("addResource", resource)
                end if
            end if
        end if
    end while
end sub

Streaming resources

Whenever you use a Video or an Audio node to stream media, you can forward all roSystemLogEvent you receive to Datadog as follows:

    sysLog = CreateObject("roSystemLog")
    sysLog.setMessagePort(m.port)
    sysLog.enableType("http.error")
    sysLog.enableType("http.complete")

    while(true)
        msg = wait(0, m.port)
        if (type(msg) = "roSystemLogEvent")
            m.global.datadogRumAgent.callfunc("addResource", msg.getInfo())
        end if
    end while

Enrich user sessions

After your Roku channel is instrumented with RUM, you can further enrich user session information and gain finer control over the attributes collected by tracking custom events.

In addition to the default RUM attributes captured by the RUM Roku SDK automatically, you can choose to add additional contextual information, such as custom attributes, to your RUM events to enrich your observability within Datadog. Custom attributes allow you to filter and group information about observed user behavior (such as cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, or network health).

Identifying your users

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user.
  • Know which users are the most impacted by errors.
  • Monitor performance for your most important users.
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use the datadogUserInfo global field, after initializing the SDK, for example:

    m.global.setField("datadogUserInfo", { id: 42, name: "Abcd Efg", email: "abcd.efg@example.com"})

Track custom global attributes

In addition to the default attributes captured by the SDK automatically, you can choose to add additional contextual information, such as custom attributes, to your Logs and RUM events to enrich your observability within Datadog. Custom attributes allow you to filter and group information about observed user behavior (for example by cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

    m.global.setField("datadogContext", { foo: "Some value", bar: 123})

If you have not set up the Datadog Unity SDK for RUM yet, follow the in-app setup instructions or see the RUM Unity setup documentation. Learn how to set up OpenTelemetry with RUM Unity.

Advanced initialization options

Custom Endpoint
Optional
Type: String
Default: undefined
Send data to a custom endpoint instead of the default Datadog endpoint. This is useful for proxying data through a custom server.
SDK Verbosity
Optional
Type: Enum
Default: Warn
The level of debugging information the Datadog SDK should output. Higher levels output more information. This option is helpful for getting debugging information from the SDK when something is not working as expected, or removing the SDK-related debugging entries from console logs.
Telemetry Sample Rate
Optional
Type: Double
Default: 20
The percentage rate at which Datadog sends internal telemetry data. A value of 100 means all telemetry data is sampled and sent to Datadog.

Automatic view tracking

If you select Enable Automatic Scene Tracking, Datadog hooks into Unity's SceneManager to detect scenes loading and unloading, and start RUM Views appropriately. If you are using methods to move between scenes other than SceneManager, or would like to track changes in views that occur without SceneManager, you need to track views manually using DdRum.StartView and DdRum.StopView.

Track user actions

You can track specific user actions such as taps, clicks, and scrolls using DdRum.AddAction.

To manually register instantaneous RUM actions such as RumActionType.Tap, use DdRum.AddAction(). For continuous RUM actions such as RumActionType.Scroll, use DdRum.StartAction() or DdRum.StopAction().

For example:

void DownloadResourceTapped(string resourceName) {
    DatadogSdk.Instance.Rum.AddAction(
        RumActionType.Tap,
        resourceName,
    );
}

When using DdRum.StartAction and DdRum.StopAction, the type action must be the same for the Datadog Unity SDK to match an action's start with its completion.

Track resources

Datadog provides DatadogTrackedWebRequest as a drop in replacement for UnityWebRequest to enable tracking of resources and HTTP calls from your RUM views.

You can use it the same way as you would any other UnityWebRequest:

var request = DatadogTrackedWebRequest.Get("https://httpbin.org/headers");
yield return request.SendWebRequest();

Debug.Log("Got result: " + request.downloadHandler.text);

Track custom resources

In addition to tracking resources automatically using DatadogTrackedWebRequest, you can track specific custom resources such as network requests or third-party provider APIs using the following methods:

  • DdRum.StartResource
  • DdRum.StopResource
  • DdRum.StopResourceWithError
  • DdRum.StopResourceWithErrorInfo

For example:

// in your network client:

DatadogSdk.Instance.Rum.StartResource(
    "resource-key",
    RumHttpMethod.Get,
    url,
);

// Later

DatadogSdk.Instance.Rum.StopResource(
    "resource-key",
    200,
    RumResourceType.Image
);

The string used for resourceKey in both calls must be unique for the resource you are calling in order for the Unity Datadog SDK to match a resource's start with its completion.

Track custom errors

To track specific errors, notify DdRum when an error occurs with the exception, the source, and any additional attributes.

try
{
  // Error prone code
}
catch(Exception e)
{
  DatadogSdk.Instance.Rum.AddError(e, RumErrorSource.Source);
}

Track custom global attributes

In addition to the default RUM attributes captured by the Datadog Unity SDK automatically, you can choose to add additional contextual information (such as custom attributes) to your RUM events to enrich your observability within Datadog.

Custom attributes allow you to filter and group information about observed user behavior (such as the cart value, merchant tier, or ad campaign) with code-level information (such as backend services, session timeline, error logs, and network health).

Set a custom global attribute

To set a custom global attribute, use DdRum.AddAttribute.

  • To add or update an attribute, use DdRum.AddAttribute.
  • To remove the key, use DdRum.RemoveAttribute.

Track user sessions

Adding user information to your RUM sessions makes it possible to:

  • Follow the journey of a given user
  • Know which users are the most impacted by errors
  • Monitor performance for your most important users
User API in the RUM UI
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI if the user name is not present.

To identify user sessions, use DatadogSdk.SetUserInfo.

For example:

DatadogSdk.Instance.SetUserInfo("1234", "John Doe", "john@doe.com");

Add custom user attributes

You can add custom attributes to your user session. This additional information is automatically applied to logs, traces, and RUM events.

To remove an existing attribute, set it to null.

For example:

DatadogSdk.Instance.AddUserExtraInfo(new ()
{
 { "attribute_1", "foo" },
 { "attribute_2", null },
});

Clear all data

Use ClearAllData to clear all data that has not been sent to Datadog.

DatadogSdk.instance.ClearAllData();