---
title: Advanced Configuration
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: Docs > Client SDKs > Advanced Configuration
---

# Advanced Configuration

## Overview{% #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.

{% section displayed-if="SDK is Browser" %}
This section only applies to users who meet the following criteria: SDK is Browser

{% alert level="info" %}
For browser advanced configuration, see the [Browser Advanced Configuration](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/browser/advanced_configuration.md) page.
{% /alert %}
{% /section %}

{% section displayed-if="SDK is Android" %}
This section only applies to users who meet the following criteria: SDK is Android

If you have not set up the SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [Android RUM setup documentation](https://docs.datadoghq.com/real_user_monitoring/android.md).

## Enrich user sessions{% #enrich-user-sessions %}

Android RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the [RUM Data Collection documentation](https://docs.datadoghq.com/real_user_monitoring/android/data_collected.md) 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{% #custom-views %}

In addition to [tracking views automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#automatically-track-views), 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`:

{% tab title="Kotlin" %}

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

fun onPause() {
    GlobalRumMonitor.get().stopView(viewKey, viewAttributes)
}
```

{% /tab %}

{% tab title="Java" %}

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

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

{% /tab %}

### Custom actions{% #custom-actions %}

In addition to [tracking actions automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#initialization-parameters), 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".

{% tab title="Kotlin" %}

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

{% /tab %}

{% tab title="Java" %}

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

{% /tab %}

### Enrich resources{% #enrich-resources %}

When [tracking resources automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#automatically-track-network-requests), 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`.

{% tab title="Kotlin" %}

```
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()
        }
    }
}
```

{% /tab %}

{% tab title="Java" %}

```
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;
    }
}
```

{% /tab %}

### Custom resources{% #custom-resources %}

In addition to [tracking resources automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#automatically-track-network-requests), 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.

{% tab title="Kotlin" %}

```
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)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```
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);
    }
}
```

{% /tab %}

### Custom errors{% #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](https://docs.datadoghq.com/real_user_monitoring/android/data_collected.md#event-specific-attributes).

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

### Add user properties{% #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{% #event-and-data-management %}

The Android SDK first stores events and only uploads events when the [intake specifications](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/setup.md#sending-data-when-device-is-offline) conditions are met.

### Clear all data{% #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{% #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{% #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](https://github.com/DataDog/dd-sdk-android/blob/eaa15cd344d1723fafaf179fcebf800d6030c6bb/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt#L279) being used.

### Set remote log threshold{% #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{% #track-custom-global-attributes %}

In addition to the [default RUM attributes](https://docs.datadoghq.com/real_user_monitoring/android/data_collected.md) 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{% #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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api-1.25bdf1f69bdca2ed94798fa98634f090.png?auto=format"
   alt="User attributes of a session in the RUM UI" /%}

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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{% #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{% #track-widgets %}

Widgets are not automatically tracked with the SDK. To send UI interactions from your widgets manually, call the Datadog API. [See example](https://github.com/DataDog/dd-sdk-android/tree/master/sample/kotlin/src/main/kotlin/com/datadog/android/sample/widget).

## Initialization parameters{% #initialization-parameters %}

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

{% dl %}

{% dt %}
`setFirstPartyHosts()`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`useSite(DatadogSite)`
{% /dt %}

{% dd %}
Switches target data to EU1, US1, US3, US5, US1_FED, AP1 and AP2 sites.
{% /dd %}

{% dt %}
`setFirstPartyHostsWithHeaderType`
{% /dt %}

{% dd %}
Sets the list of first party hosts and specifies the type of HTTP headers used for distributed tracing.
{% /dd %}

{% dt %}
`setBatchSize([SMALL|MEDIUM|LARGE])`
{% /dt %}

{% dd %}
Defines the individual batch size for requests sent to Datadog.
{% /dd %}

{% dt %}
`setUploadFrequency([FREQUENT|AVERAGE|RARE])`
{% /dt %}

{% dd %}
Defines the frequency for requests made to Datadog endpoints (if requests are available).
{% /dd %}

{% dt %}
`setBatchProcessingLevel(LOW|MEDIUM|HIGH)`
{% /dt %}

{% dd %}
Defines the number of batches sent in each upload cycle.
{% /dd %}

{% dt %}
`setAdditionalConfiguration`
{% /dt %}

{% dd %}
Allows you to provide additional configuration values that can be used by the SDK.
{% /dd %}

{% dt %}
`setProxy`
{% /dt %}

{% dd %}
Enables a custom proxy for uploading tracked data to Datadog's intake.
{% /dd %}

{% dt %}
`setEncryption(Encryption)`
{% /dt %}

{% dd %}
Set an encryption function applied to data stored locally on the device.
{% /dd %}

{% dt %}
`setPersistenceStrategyFactory`
{% /dt %}

{% dd %}
Allows you to use a custom persistence strategy.
{% /dd %}

{% dt %}
`setCrashReportsEnabled(Boolean)`
{% /dt %}

{% dd %}
Allows you to control whether JVM crashes are tracked or not. The default value is `true`.
{% /dd %}

{% dt %}
`setBackpressureStrategy(BackPressureStrategy)`
{% /dt %}

{% dd %}
Define the strategy the SDK uses when handling large volumes of data and internal queues are full.
{% /dd %}

{% /dl %}

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

{% dl %}

{% dt %}
`trackUserInteractions(Array<ViewAttributesProvider>)`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`disableUserInteractionTracking`
{% /dt %}

{% dd %}
Disables the user interaction automatic tracker.
{% /dd %}

{% dt %}
`useViewTrackingStrategy(strategy)`
{% /dt %}

{% dd %}
Defines the strategy used to track views. See Automatically track views for more information.
{% /dd %}

{% dt %}
`trackLongTasks(durationThreshold)`
{% /dt %}

{% dd %}
Enables tracking tasks taking longer than `durationThreshold` on the main thread as long tasks in Datadog. See Automatically track long tasks for more information.
{% /dd %}

{% dt %}
`trackNonFatalAnrs(Boolean)`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`setVitalsUpdateFrequency([FREQUENT|AVERAGE|RARE|NEVER])`
{% /dt %}

{% dd %}
Sets the preferred frequency for collecting mobile vitals.
{% /dd %}

{% dt %}
`setSessionSampleRate(<sampleRate>)`
{% /dt %}

{% dd %}
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.)
{% /dd %}

{% dt %}
`setSessionListener(RumSessionListener)`
{% /dt %}

{% dd %}
Sets a listener to be notified on when a new RUM Session starts.
{% /dd %}

{% dt %}
`setTelemetrySampleRate`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`setViewEventMapper`
{% /dt %}

{% dd %}
Sets the ViewEventMapper for the RUM ViewEvent. You can use this interface implementation to modify the ViewEvent attributes before serialization.
{% /dd %}

{% dt %}
`setResourceEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ResourceEvent. You can use this interface implementation to modify the ResourceEvent attributes before serialization.
{% /dd %}

{% dt %}
`setActionEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ActionEvent. You can use this interface implementation to modify the ActionEvent attributes before serialization.
{% /dd %}

{% dt %}
`setErrorEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ErrorEvent. You can use this interface implementation to modify the ErrorEvent attributes before serialization.
{% /dd %}

{% dt %}
`setInitialResourceIdentifier`
{% /dt %}

{% dd %}
Sets a custom identifier for initial network resources used for [Time-to-Network-Settled](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/monitoring_app_performance.md#time-to-network-settled) (TNS) view timing calculation.
{% /dd %}

{% dt %}
`setLastInteractionIdentifier`
{% /dt %}

{% dd %}
Sets a custom identifier for the last interaction in the previous view used for [Interaction-to-Next-View](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/monitoring_app_performance.md#interaction-to-next-view) (INV) timing calculation.
{% /dd %}

{% dt %}
`setLongTaskEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM LongTaskEvent. You can use this interface implementation to modify the LongTaskEvent attributes before serialization.
{% /dd %}

{% dt %}
`trackBackgroundEvents`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`trackFrustrations`
{% /dt %}

{% dd %}
Enable/disable tracking of frustration signals.
{% /dd %}

{% dt %}
`useCustomEndpoint`
{% /dt %}

{% dd %}
Use RUM to target a custom server.
{% /dd %}

{% dt %}
`trackAnonymousUser`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% /dl %}

### Automatically track views{% #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:

{% dl %}

{% dt %}
`ActivityViewTrackingStrategy`
{% /dt %}

{% dd %}
Every activity in your application is considered a distinct view.
{% /dd %}

{% dt %}
`FragmentViewTrackingStrategy`
{% /dt %}

{% dd %}
Every fragment in your application is considered a distinct view.
{% /dd %}

{% dt %}
`MixedViewTrackingStrategy`
{% /dt %}

{% dd %}
Every activity or fragment in your application is considered a distinct view.
{% /dd %}

{% dt %}
`NavigationViewTrackingStrategy`
{% /dt %}

{% dd %}
Recommended for Android Jetpack Navigation library users. Each Navigation destination is considered a distinct view.
{% /dd %}

{% /dl %}

For instance, to set each fragment as a distinct view, use the following configuration in your [setup](https://app.datadoghq.com/rum/application/create):

{% tab title="Kotlin" %}

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

{% /tab %}

{% tab title="Java" %}

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

{% /tab %}

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:

{% tab title="Kotlin" %}

```
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()
```

{% /tab %}

{% tab title="Java" %}

```
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();
```

{% /tab %}

**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{% #automatically-track-network-requests %}

#### Basic network instrumentation{% #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](https://square.github.io/okhttp/features/events/) 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"
}
```
Add the [EventListener](https://square.github.io/okhttp/features/events/) factory:
{% tab title="Kotlin" %}

```
val tracedHosts = listOf("example.com")
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(DatadogInterceptor.Builder(tracedHosts).build())
    .eventListenerFactory(DatadogEventListener.Factory())
    .build()
```

{% /tab %}

{% tab title="Java" %}

```
List<String> tracedHosts = Arrays.asList("example.com");
OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addInterceptor(new DatadogInterceptor.Builder(tracedHosts).build())
    .eventListenerFactory(new DatadogEventListener.Factory())
    .build();
```

{% /tab %}

#### Cronet network instrumentation{% #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"
}
```
Instrument the `CronetEngine.Builder`:
{% tab title="Kotlin" %}

```
val cronetEngine = CronetEngine.Builder(context)
    .configureDatadogInstrumentation(
        rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
        apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
            tracedHosts = listOf("example.com", "example.eu")
        )
    )
    .build()
```

{% /tab %}

{% tab title="Java" %}

```
CronetEngine.Builder builder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = CronetIntegrationPluginKt
    .configureDatadogInstrumentation(
        builder,
        new RumNetworkInstrumentationConfiguration(),
        new ApmNetworkInstrumentationConfiguration(
            Arrays.asList("example.com", "example.eu")
        )
    )
    .build();
```

{% /tab %}

#### Apollo instrumentation{% #apollo-instrumentation %}

1. [Set up](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/setup.md?tab=kotlin#setup) RUM monitoring with Datadog Android RUM.

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

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

```
dependencies {
    implementation "com.datadoghq:dd-sdk-android-apollo:x.x.x"
}
```
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.

{% alert level="danger" %}

- 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)
```

{% /alert %}

### Automatically track long tasks{% #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.

{% tab title="Kotlin" %}

```
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()
```

{% /tab %}

{% tab title="Java" %}

```
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();
```

{% /tab %}

## Modify or drop RUM events{% #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:

{% tab title="Kotlin" %}

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

{% /tab %}

{% tab title="Java" %}

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

{% /tab %}

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

| Event type           | Attribute key                                    | Description                                      |
| -------------------- | ------------------------------------------------ | ------------------------------------------------ |
| ViewEvent            | `view.referrer`                                  | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ActionEvent          |
| `action.target.name` | Target name.                                     |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ErrorEvent           |
| `error.message`      | Error message.                                   |
| `error.stack`        | Stacktrace of the error.                         |
| `error.resource.url` | URL of the resource.                             |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ResourceEvent        |
| `resource.url`       | URL of the resource.                             |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| LongTaskEvent        |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name 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{% #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
}
```
{% /section %}

{% section displayed-if="SDK is iOS" %}
This section only applies to users who meet the following criteria: SDK is iOS

If you have not set up the RUM iOS SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [RUM iOS setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios.md).

## Enrich user sessions{% #enrich-user-sessions-2 %}

iOS RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the [RUM Data Collection documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios/data_collected.md) 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{% #custom-views-2 %}

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:

{% tab title="Swift" %}

```
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)
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
@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];
}
```

{% /tab %}

For more details and available options, see [`RUMMonitorProtocol` in GitHub](https://github.com/DataDog/dd-sdk-ios/blob/master/DatadogRUM/Sources/RUMMonitorProtocol.swift).

### Custom actions{% #custom-actions-2 %}

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:

{% tab title="Swift" %}

```
import DatadogRUM

// in your `UIViewController`:

let rum = RUMMonitor.shared()

@IBAction func didTapDownloadResourceButton(_ sender: UIButton) {
    rum.addAction(
        type: .tap,
        name: sender.currentTitle ?? ""
    )
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
- (IBAction)didTapDownloadResourceButton:(UIButton *)sender {
    NSString *name = sender.currentTitle ? sender.currentTitle : @"";
    [[DDRUMMonitor shared] addActionWithType:DDRUMActionTypeTap name:name attributes:@{}];
}
```

{% /tab %}

**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](https://github.com/DataDog/dd-sdk-ios/blob/master/DatadogRUM/Sources/RUMMonitorProtocol.swift).

### Custom resources{% #custom-resources-2 %}

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:

{% tab title="Swift" %}

```
import DatadogRUM

// in your network client:

let rum = RUMMonitor.shared()

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

rum.stopResource(
    resourceKey: "resource-key",
    response: response
)
```

{% /tab %}

{% tab title="Objective-C" %}

```
// in your network client:

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

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

{% /tab %}

**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](https://github.com/DataDog/dd-sdk-ios/blob/master/DatadogRUM/Sources/RUMMonitorProtocol.swift).

### Custom errors{% #custom-errors-2 %}

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

- `.addError(message:)`
- `.addError(error:)`

{% tab title="Swift" %}

```
let rum = RUMMonitor.shared()
rum.addError(message: "error message.")
```

{% /tab %}

{% tab title="Objective-C" %}

```
[[DDRUMMonitor shared] addErrorWithMessage:@"error message." stack:nil source:DDRUMErrorSourceCustom attributes:@{}];
```

{% /tab %}

For more details and available options, see [`RUMMonitorProtocol` in GitHub](https://github.com/DataDog/dd-sdk-ios/blob/master/DatadogRUM/Sources/RUMMonitorProtocol.swift) and the [Error Attributes documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios/data_collected.md?tab=error#error-attributes).

## Track custom global attributes{% #track-custom-global-attributes-2 %}

In addition to the [default RUM attributes](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios/data_collected.md?tab=session#default-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).

{% alert level="info" %}
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.
{% /alert %}

### Set a custom global attribute{% #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{% #track-user-sessions-2 %}

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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format"
   alt="User API in the RUM UI" /%}

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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:

{% tab title="Swift" %}

```
import DatadogCore

Datadog.setUserInfo(id: "1234", name: "John Doe", email: "john@doe.com")
```

{% /tab %}

{% tab title="Objective-C" %}

```
[DDDatadog setUserInfoWithId:@"1234" name:@"John Doe" email:@"john@doe.com" extraInfo:@{}];
```

{% /tab %}

## Track background events{% #track-background-events %}

{% alert level="info" %}
Tracking background events may lead to additional sessions, which can impact billing. For questions, [contact Datadog support](https://docs.datadoghq.com/help/).
{% /alert %}

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{% #initialization-parameters-2 %}

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

{% dl %}

{% dt %}
`backgroundTasksEnabled`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`batchProcessingLevel`
{% /dt %}

{% dd %}
Batch processing level defines the maximum number of batches processed sequentially without a delay within one reading/uploading cycle. The default value is `.medium`.
{% /dd %}

{% dt %}
`batchSize`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`bundle`
{% /dt %}

{% dd %}
The bundle object that contains the current executable.
{% /dd %}

{% dt %}
`clientToken`
{% /dt %}

{% dd %}
Either the RUM client token (which supports RUM, Logging, and APM) or the regular client token (which supports Logging and APM).
{% /dd %}

{% dt %}
`encryption`
{% /dt %}

{% dd %}
Data encryption to use for on-disk data persistency by providing an object that complies with the `DataEncryption` protocol.
{% /dd %}

{% dt %}
`env`
{% /dt %}

{% dd %}
The environment name that is sent to Datadog. This can be used to filter events by different environments (such as `staging` or `production`).
{% /dd %}

{% dt %}
`proxyConfiguration`
{% /dt %}

{% dd %}
A proxy configuration attribute which can be used to enable a custom proxy for uploading tracked data to Datadog's intake.
{% /dd %}

{% dt %}
`serverDateProvider`
{% /dt %}

{% dd %}
A custom NTP synchronization interface. By default, the Datadog SDK synchronizes with dedicated NTP pools provided by the [NTP Pool Project](https://www.ntppool.org/en/). 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.
{% /dd %}

{% dt %}
`service`
{% /dt %}

{% dd %}
The service name associated with data sent to Datadog. The default value is the application bundle identifier.
{% /dd %}

{% dt %}
`site`
{% /dt %}

{% dd %}
The Datadog server endpoint that data is sent to. The default value is `.us1`.
{% /dd %}

{% dt %}
`uploadFrequency`
{% /dt %}

{% dd %}
The preferred frequency of uploading data to Datadog. Available values include: `.frequent`, `.average`, and `.rare`.
{% /dd %}

{% /dl %}

### RUM configuration{% #rum-configuration %}

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

{% dl %}

{% dt %}
`actionEventMapper`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`appHangThreshold`
{% /dt %}

{% dd %}
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](https://docs.datadoghq.com/real_user_monitoring/error_tracking/mobile/ios.md#add-app-hang-reporting).
{% /dd %}

{% dt %}
`applicationID`
{% /dt %}

{% dd %}
The RUM application identifier.
{% /dd %}

{% dt %}
`customEndpoint`
{% /dt %}

{% dd %}
A custom server URL for sending RUM data.
{% /dd %}

{% dt %}
`errorEventMapper`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`longTaskEventMapper`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`longTaskThreshold`
{% /dt %}

{% dd %}
The threshold for RUM long tasks tracking (in seconds). By default, this is set to `0.1` seconds.
{% /dd %}

{% dt %}
`networkSettledResourcePredicate`
{% /dt %}

{% dd %}
The predicate used to classify "initial" resources for the Time-to-Network-Settled (TNS) view timing calculation.
{% /dd %}

{% dt %}
`nextViewActionPredicate`
{% /dt %}

{% dd %}
The predicate used to classify the "last" action for the Interaction-to-Next-View (INV) timing calculation.
{% /dd %}

{% dt %}
`onSessionStart`
{% /dt %}

{% dd %}
(Optional) The method that gets called when RUM starts the session.
{% /dd %}

{% dt %}
`resourceEventMapper`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`sessionSampleRate`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`telemetrySampleRate`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`trackAnonymousUser`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`trackBackgroundEvents`
{% /dt %}

{% dd %}
Determines whether RUM events are tracked when no view is active. By default, this is set to `false`.
{% /dd %}

{% dt %}
`trackFrustrations`
{% /dt %}

{% dd %}
Determines whether automatic tracking of user frustrations is enabled. By default, this is set to `true`.
{% /dd %}

{% dt %}
`trackMemoryWarnings`
{% /dt %}

{% dd %}
Determines whether automatic tracking of memory warnings is enabled. By default, this is set to `true`.
{% /dd %}

{% dt %}
`trackWatchdogTerminations`
{% /dt %}

{% dd %}
Determines whether the SDK should track application terminations performed by Watchdog. The default setting is `false`.
{% /dd %}

{% dt %}
`uiKitActionsPredicate`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`uiKitViewsPredicate`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`urlSessionTracking`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`viewEventMapper`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`vitalsUpdateFrequency`
{% /dt %}

{% dd %}
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).
{% /dd %}

{% /dl %}

### Automatically track views{% #automatically-track-views-2 %}

You can automatically track views with UIKit and SwiftUI.

#### UIKit{% #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:

{% tab title="Swift" %}

```
public protocol UIKitRUMViewsPredicate {
    func rumView(for viewController: UIViewController) -> RUMView?
}
```

{% /tab %}

{% tab title="Objective-C" %}

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

{% /tab %}

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:

{% tab title="Swift" %}

```
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
        }
    }
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
@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
```

{% /tab %}

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:

{% tab title="Swift" %}

```
class YourCustomPredicate: UIKitRUMViewsPredicate {

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

        return RUMView(name: accessibilityLabel)
    }
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
@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
```

{% /tab %}

**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{% #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.

{% tab title="Swift" %}

```
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)
    }
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
@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
```

{% /tab %}

**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{% #automatically-track-user-actions %}

#### UIKit{% #uikit-2 %}

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

#### SwiftUI{% #swiftui-2 %}

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:

{% tab title="Swift" %}

```
// 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)
    }
}
```

{% /tab %}

{% tab title="Objective-C" %}

```
// 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
```

{% /tab %}

#### Action reporting by iOS version{% #action-reporting-by-ios-version %}

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

| **Component**  | **iOS 18 reported name**                           | **iOS 17 reported name**                           |
| -------------- | -------------------------------------------------- | -------------------------------------------------- |
| Button         | SwiftUI_Button                                     | SwiftUI_Unidentified_Element                       |
| NavigationLink | NavigationLink                                     | SwiftUI_Unidentified_Element                       |
| Menu           | SwiftUI_Menu (and its items as _UIContextMenuCell) | SwiftUI_Menu (and its items as _UIContextMenuCell) |
| Link           | SwiftUI_Button                                     | SwiftUI_Unidentified_Element                       |

### Automatically track network requests{% #automatically-track-network-requests-2 %}

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

#### (Optional) Enable detailed timing breakdown{% #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:

{% tab title="Swift" %}

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

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

{% /tab %}

{% tab title="Objective-C" %}

```
DDURLSessionInstrumentationConfiguration *config = [[DDURLSessionInstrumentationConfiguration alloc] initWithDelegateClass:[<YourSessionDelegate> class]];
[DDURLSessionInstrumentation enableWithConfiguration:config];

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

{% /tab %}

**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).

{% alert level="info" %}
Be mindful of delegate retention. While Datadog instrumentation does not create memory leaks directly, it relies on `URLSession` delegates. According to [Apple documentation](https://developer.apple.com/documentation/foundation/urlsession/init\(configuration:delegate:delegatequeue:\)#parameters): "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.
{% /alert %}

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:

{% tab title="Swift" %}

```

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](https://docs.datadoghq.com/real_user_monitoring/correlate_with_other_telemetry/apm.md?tab=browserrum).
{% /tab %}

{% tab title="Objective-C" %}

```
@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];
```

{% /tab %}

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:

{% tab title="Swift" %}

```
URLSessionInstrumentation.disable(delegateClass: <YourSessionDelegate>.self)
```

{% /tab %}

{% tab title="Objective-C" %}

```
[DDURLSessionInstrumentation disableWithDelegateClass:[<YourSessionDelegate> class]];
```

{% /tab %}

#### Apollo instrumentation{% #apollo-instrumentation-2 %}

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](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios.md) RUM monitoring with Datadog iOS RUM.

1. 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 **File** → **Add Package Dependencies**.
   1. Enter the repository URL: `https://github.com/DataDog/dd-sdk-ios-apollo-interceptor`.
   1. 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+).

1. Set up network instrumentation based on your Apollo iOS version:

{% tab title="Apollo iOS 1.0+" %}
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
    }
}
```

{% /tab %}

{% tab title="Apollo iOS 2.0+" %}
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)
    }
}
```

{% /tab %}

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

{% alert level="info" %}

- 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)
  ```

{% /alert %}

### Automatically track errors{% #automatically-track-errors %}

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

{% tab title="Swift" %}

```
import DatadogLogs

let logger = Logger.create()

logger.error("message")
logger.critical("message")
```

{% /tab %}

{% tab title="Objective-C" %}

```
@import DatadogLogs;

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

{% /tab %}

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

{% tab title="Swift" %}

```
import DatadogTrace

let span = Tracer.shared().startSpan(operationName: "operation")
// ... capture the `error`
span.setError(error)
span.finish()
```

{% /tab %}

{% tab title="Objective-C" %}

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

{% /tab %}

## Modify or drop RUM events{% #modify-or-drop-rum-events-2 %}

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:

{% tab title="Swift" %}

```
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
    }
)
```

{% /tab %}

{% tab title="Objective-C" %}

```
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;
}];
```

{% /tab %}

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`:

{% tab title="Swift" %}

```
let configuration = RUM.Configuration(
    applicationID: "<rum application id>",
    resourceEventMapper: { RUMResourceEvent in
        var RUMResourceEvent = RUMResourceEvent
        RUMResourceEvent.resource.url = redacted(RUMResourceEvent.resource.url)
        return RUMResourceEvent
    }
)
```

{% /tab %}

{% tab title="Objective-C" %}

```
DDRUMConfiguration *configuration = [[DDRUMConfiguration alloc] initWithApplicationID:@"<rum application id>"];

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

{% /tab %}

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 Type                          | Attribute key                                    | Description          |
| ----------------------------------- | ------------------------------------------------ | -------------------- |
| RUMActionEvent                      | `RUMActionEvent.action.target?.name`             | Name of the action.  |
| `RUMActionEvent.view.url`           | URL of the view linked to this action.           |
| RUMErrorEvent                       | `RUMErrorEvent.error.message`                    | Error message.       |
| `RUMErrorEvent.error.stack`         | Stacktrace of the error.                         |
| `RUMErrorEvent.error.resource?.url` | URL of the resource the error refers to.         |
| `RUMErrorEvent.view.url`            | URL of the view linked to this error.            |
| RUMResourceEvent                    | `RUMResourceEvent.resource.url`                  | URL of the resource. |
| `RUMResourceEvent.view.url`         | URL of the view linked to this resource.         |
| RUMViewEvent                        | `RUMViewEvent.view.name`                         | Name of the view.    |
| `RUMViewEvent.view.url`             | URL of the view.                                 |
| `RUMViewEvent.view.referrer`        | URL that linked to the initial view of the page. |

## Retrieve the RUM session ID{% #retrieve-the-rum-session-id-2 %}

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
})
```

## Set tracking consent (GDPR compliance){% #set-tracking-consent--gdpr-compliance %}

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.
1. `.granted`: The RUM iOS SDK starts collecting the data and sends it to Datadog.
1. `.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{% #add-user-properties-2 %}

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

```
import DatadogCore

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

## Data management{% #data-management %}

The iOS SDK first stores events locally and only uploads events when the [intake specifications](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/ios/setup.md) conditions are met.

### Clear all data{% #clear-all-data-2 %}

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{% #stop-data-collection-2 %}

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.
{% /section %}

{% section displayed-if="SDK is Flutter" %}
This section only applies to users who meet the following criteria: SDK is Flutter

If you have not set up the Datadog Flutter SDK for RUM yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [RUM Flutter setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/flutter/setup.md). Learn how to set up OpenTelemetry with RUM Flutter. For additional manual instrumentation functions, such as automatic view tracking, see [Flutter Libraries for RUM](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/flutter/integrated_libraries.md).

## Initialization parameters{% #initialization-parameters-3 %}

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

{% dl %}

{% dt %}
`clientToken`
{% /dt %}

{% dd %}
Required**Type**: StringA client token for RUM or logging/APM. You can obtain this token in Datadog.
{% /dd %}

{% dt %}
`env`
{% /dt %}

{% dd %}
Required**Type**: StringThe environment name sent to Datadog. You can use `env` to filter events by environment (for example, `staging` or `production`).
{% /dd %}

{% dt %}
`site`
{% /dt %}

{% dd %}
Required**Type**: EnumThe Datadog site that data is sent to. Enum values: `us1`, `us3`, `us5`, `eu1`, `us1Fed`, `ap1`, and `ap2`.
{% /dd %}

{% dt %}
`nativeCrashReportEnabled`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables native crash reporting.
{% /dd %}

{% dt %}
`service`
{% /dt %}

{% dd %}
Optional**Type**: StringThe service name for the application.
{% /dd %}

{% dt %}
`uploadFrequency`
{% /dt %}

{% dd %}
Optional**Type**: Enum**Default**: `average`The frequency at which the Datadog SDK tries to upload data batches. Enum values: `frequent`, `average`, and `rare`.
{% /dd %}

{% dt %}
`batchSize`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`batchProcessingLevel`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`version`
{% /dt %}

{% dd %}
Optional**Type**: StringThe application's version number. Because `version` is a Datadog tag, it must comply with the rules in [Defining Tags](https://docs.datadoghq.com/getting_started/tagging.md#defining-tags).
{% /dd %}

{% dt %}
`flavor`
{% /dt %}

{% dd %}
Optional**Type**: StringThe flavor (variant) of the application. For stack trace deobfuscation, this must match the flavor set during symbol upload.
{% /dd %}

{% dt %}
`firstPartyHosts`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`firstPartyHostsWithTracingHeaders`
{% /dt %}

{% dd %}
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:
- `datadog`: Datadog's [`x-datadog-*` header](https://docs.datadoghq.com/real_user_monitoring/connect_rum_and_traces.md?tab=browserrum#how-are-rum-resources-linked-to-traces)
- `b3`: OpenTelemetry B3 [single header](https://github.com/openzipkin/b3-propagation#single-headers)
- `b3multi`: OpenTelemetry B3 [multiple headers](https://github.com/openzipkin/b3-propagation#multiple-headers)
- `tracecontext`: W3C [trace context header](https://www.w3.org/TR/trace-context/#tracestate-header)

{% /dd %}

{% dt %}
`rumConfiguration`
{% /dt %}

{% dd %}
Optional**Type**: ObjectSee RUM configuration.
{% /dd %}

{% /dl %}

### RUM configuration{% #rum-configuration-2 %}

Use the following parameters for the `DatadogRumConfiguration` class.

{% dl %}

{% dt %}
`applicationId`
{% /dt %}

{% dd %}
Required**Type**: StringThe RUM application ID.
{% /dd %}

{% dt %}
`sessionSamplingRate`
{% /dt %}

{% dd %}
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).
{% /dd %}

{% dt %}
`traceSampleRate`
{% /dt %}

{% dd %}
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).
{% /dd %}

{% dt %}
`traceContextInjection`
{% /dt %}

{% dd %}
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).
{% /dd %}

{% dt %}
`detectLongTasks`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`longTaskThreshold`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`trackFrustrations`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `true`Enables [automatic collection of user frustrations](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/browser/frustration_signals.md).
{% /dd %}

{% dt %}
`vitalUpdateFrequency`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`reportFlutterPerformance`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables reporting Flutter-specific performance metrics, including build and raster times.
{% /dd %}

{% dt %}
`customEndpoint`
{% /dt %}

{% dd %}
Optional**Type**: StringA custom endpoint for sending RUM data.
{% /dd %}

{% dt %}
`telemetrySampleRate`
{% /dt %}

{% dd %}
Optional**Type**: Double**Default**: `20.0`The sampling rate for telemetry data, such as errors and debug logs.
{% /dd %}

{% /dl %}

## Tracking from background isolates{% #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](https://pub.dev/packages/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{% #automatically-track-resources %}

Use the [Datadog Tracking HTTP Client](https://pub.dev/packages/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`](https://api.flutter.dev/flutter/dart-io/HttpOverrides/current.html). If you are using your own custom `HttpOverrides`, you may need to inherit from [`DatadogHttpOverrides`](https://pub.dev/documentation/datadog_tracking_http_client/latest/datadog_tracking_http_client/DatadogTrackingHttpOverrides-class.html). 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](https://docs.datadoghq.com/serverless/aws_lambda/distributed_tracing.md), 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{% #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](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/flutter/integrated_libraries.md).

## Enrich user sessions{% #enrich-user-sessions-3 %}

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](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/flutter/data_collected.md) 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{% #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{% #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](https://docs.datadoghq.com/real_user_monitoring/explorer.md?tab=measures#setup-facets-and-measures) first.

### Track user actions{% #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{% #track-custom-resources %}

In addition to tracking resources automatically using the [Datadog Tracking HTTP Client](https://github.com/DataDog/dd-sdk-flutter/tree/main/packages/datadog_tracking_http_client), you can track specific custom resources such as network requests or third-party provider APIs using the [following methods](https://pub.dev/documentation/datadog_flutter_plugin/latest/datadog_flutter_plugin/):

- `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{% #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{% #track-custom-global-attributes-3 %}

In addition to the [default RUM attributes](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/flutter/data_collected.md) 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{% #set-a-custom-global-attribute-2 %}

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{% #track-user-sessions-3 %}

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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format"
   alt="User API in the RUM UI" /%}

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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{% #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{% #clear-all-data-3 %}

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

```
DatadogSdk.instance.clearAllData();
```

## Modify or drop RUM events{% #modify-or-drop-rum-events-3 %}

**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 Type                       | Attribute key                               | Description          |
| -------------------------------- | ------------------------------------------- | -------------------- |
| RumViewEvent                     | `viewEvent.view.url`                        | URL of the view.     |
| `viewEvent.view.referrer`        | Referrer of the view.                       |
| RumActionEvent                   | `actionEvent.action.target?.name`           | Name of the action.  |
| `actionEvent.view.referrer`      | Referrer of the view linked to this action. |
| `actionEvent.view.url`           | URL of the view linked to this action.      |
| RumErrorEvent                    | `errorEvent.error.message`                  | Error message.       |
| `errorEvent.error.stack`         | Stacktrace of the error.                    |
| `errorEvent.error.resource?.url` | URL of the resource the error refers to.    |
| `errorEvent.view.referrer`       | Referrer of the view linked to this action. |
| `errorEvent.view.url`            | URL of the view linked to this error.       |
| RumResourceEvent                 | `resourceEvent.resource.url`                | URL of the resource. |
| `resourceEvent.view.referrer`    | Referrer of the view linked to this action. |
| `resourceEvent.view.url`         | URL of the view linked to this resource.    |

## Retrieve the RUM session ID{% #retrieve-the-rum-session-id-3 %}

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{% #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](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/mobile_vitals.md?tab=flutter).

## OpenTelemetry setup{% #opentelemetry-setup %}

All of Datadog's automatic network tracking packages ([Datadog Tracking HTTP Client](https://pub.dev/packages/datadog_tracking_http_client), [gRPC Interceptor](https://pub.dev/packages/datadog_grpc_interceptor), [GQL Link](https://pub.dev/packages/datadog_gql_link), and [Dio Interceptor](https://pub.dev/packages/datadog_dio)) support distributed traces through both automatic header generation and header ingestion. This section describes how to use OpenTelemetry with RUM Flutter.

### Datadog header generation{% #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{% #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.');
}
```
{% /section %}

{% section displayed-if="SDK is React Native" %}
This section only applies to users who meet the following criteria: SDK is React Native

If you have not set up the SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [React Native RUM setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/react_native.md).

## Jest testing{% #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](https://jestjs.io/), 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{% #initialization-parameters-4 %}

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

### Core configuration{% #core-configuration %}

{% dl %}

{% dt %}
`clientToken`
{% /dt %}

{% dd %}
Required**Type**: StringA [Datadog client token](https://docs.datadoghq.com/account_management/api-app-keys.md#client-tokens).
{% /dd %}

{% dt %}
`env`
{% /dt %}

{% dd %}
Required**Type**: StringThe application's environment, for example: prod, pre-prod, and staging. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging.md#define-tags).
{% /dd %}

{% dt %}
`rumConfiguration`
{% /dt %}

{% dd %}
Optional**Type**: `RumConfiguration`The Datadog RUM configuration. RUM is **disabled by default**. See RUM configuration.
{% /dd %}

{% dt %}
`logsConfiguration`
{% /dt %}

{% dd %}
Optional**Default**: `undefined`**Type**: `LogsConfiguration`The Datadog Logs configuration. Logs is **disabled by default**: use an empty configuration `{}` to enable. See Logs configuration.
{% /dd %}

{% dt %}
`traceConfiguration`
{% /dt %}

{% dd %}
Optional**Type**: `TraceConfiguration`The Datadog Trace configuration. Trace is **disabled by default**: use an empty configuration `{}` to enable. See Trace configuration.
{% /dd %}

{% dt %}
`site`
{% /dt %}

{% dd %}
Optional**Type**: String**Default**: `US1`[The Datadog site parameter of your organization](https://docs.datadoghq.com/getting_started/site.md).
{% /dd %}

{% dt %}
`service`
{% /dt %}

{% dd %}
Optional**Type**: StringThe service name for your application. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging.md#define-tags).
{% /dd %}

{% dt %}
`verbosity`
{% /dt %}

{% dd %}
Optional**Type**: SdkVerbosity**Default**: `undefined`Verbosity for internal SDK logging. Set to `SdkVerbosity.DEBUG` to debug your SDK implementation.
{% /dd %}

{% dt %}
`version`
{% /dt %}

{% dd %}
Optional**Type**: StringThe application's version. For example: 1.2.3, 6c44da20, and 2020.02.13. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging.md#define-tags).
{% /dd %}

{% dt %}
`versionSuffix`
{% /dt %}

{% dd %}
Optional**Type**: StringAdd 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](https://docs.datadoghq.com/getting_started/tagging.md#define-tags).
{% /dd %}

{% dt %}
`proxyConfig`
{% /dt %}

{% dd %}
Optional**Type**: ProxyConfigurationOptional [proxy configuration](https://docs.datadoghq.com/real_user_monitoring/guide/proxy-mobile-rum-data.md).
{% /dd %}

{% dt %}
`uploadFrequency`
{% /dt %}

{% dd %}
Optional**Type**: UploadFrequency**Default**: `UploadFrequency.AVERAGE`Sets the preferred frequency for uploading batches of data.
{% /dd %}

{% dt %}
`batchSize`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% /dl %}

### RUM configuration{% #rum-configuration-3 %}

{% dl %}

{% dt %}
`applicationId`
{% /dt %}

{% dd %}
**Required****Type**: StringThe RUM application ID.
{% /dd %}

{% dt %}
`trackInteractions`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables automatic collection of user actions.
{% /dd %}

{% dt %}
`trackResources`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables collection of resource events.
{% /dd %}

{% dt %}
`trackErrors`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables collection of React Native crashes.
{% /dd %}

{% dt %}
`trackFrustrations`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `true`Enables [automatic collection of user frustrations](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/browser/frustration_signals.md). Only error taps are supported. Implies `trackInteractions: true`.
{% /dd %}

{% dt %}
`sessionSampleRate`
{% /dt %}

{% dd %}
Optional**Type**: Number**Default**: `100`The percentage of sessions to track: `100` for all, `0` for none. Only tracked sessions send RUM events.
{% /dd %}

{% dt %}
`resourceTraceSampleRate`
{% /dt %}

{% dd %}
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](https://docs.datadoghq.com/real_user_monitoring/correlate_with_other_telemetry/apm.md?tab=reactnativerum).
{% /dd %}

{% dt %}
`nativeCrashReportEnabled`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables crash reporting for native platforms (iOS, Android).
{% /dd %}

{% dt %}
`nativeLongTaskThresholdMs`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`nativeViewTracking`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables native views tracking. Set to `true` if you use a custom navigation system relying on native views.
{% /dd %}

{% dt %}
`nativeInteractionTracking`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Enables native interaction tracking. Set to `true` if you want to track interactions on native screens.
{% /dd %}

{% dt %}
`firstPartyHosts`
{% /dt %}

{% dd %}
Optional**Type**: List**Default**: `[]`List of your backends hosts to enable tracing with. For more information, see [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/correlate_with_other_telemetry/apm.md?tab=reactnativerum).
{% /dd %}

{% dt %}
`telemetrySampleRate`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`longTaskThresholdMs`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`vitalsUpdateFrequency`
{% /dt %}

{% dd %}
Optional**Type**: VitalsUpdateFrequency**Default**: `VitalsUpdateFrequency.AVERAGE`Sets the preferred frequency for collecting mobile vitals.
{% /dd %}

{% dt %}
`trackBackgroundEvents`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`useAccessibilityLabel`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `true`Determines whether the accessibility labels are used to name RUM actions (default is true).
{% /dd %}

{% dt %}
`trackNonFatalAnrs`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`trackWatchdogTerminations`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `false`Determines whether the SDK should track application termination by the watchdog on iOS.
{% /dd %}

{% dt %}
`trackMemoryWarnings`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`appHangThreshold`
{% /dt %}

{% dd %}
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](https://docs.datadoghq.com/real_user_monitoring/error_tracking/mobile/ios.md?tab=cocoapods#configure-the-app-hang-threshold) for more guidance on what to set this value to.
{% /dd %}

{% dt %}
`initialResourceThreshold`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`errorEventMapper`
{% /dt %}

{% dd %}
Optional**Type**: `ErrorEventMapper`**Default**: `null`Custom function to modify the attributes of a RUM Error event before it is sent to Datadog.
{% /dd %}

{% dt %}
`actionEventMapper`
{% /dt %}

{% dd %}
Optional**Type**: `ActionEventMapper`**Default**: `null`Custom function to modify the attributes of a RUM Action event before it is sent to Datadog.
{% /dd %}

{% dt %}
`resourceEventMapper`
{% /dt %}

{% dd %}
Optional**Type**: `ResourceEventMapper`**Default**: `null`Custom function to modify the attributes of a RUM Resource event before it is sent to Datadog.
{% /dd %}

{% dt %}
`customEndpoint`
{% /dt %}

{% dd %}
Optional**Type**: String**Default**: `undefined`Sets a target custom server for RUM.
{% /dd %}

{% /dl %}

### Logs configuration{% #logs-configuration %}

{% dl %}

{% dt %}
`bundleLogsWithRum`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `true`Enables RUM correlation with logs (default is true).
{% /dd %}

{% dt %}
`bundleLogsWithTraces`
{% /dt %}

{% dd %}
Optional**Type**: Boolean**Default**: `true`Enables trace correlation with logs.
{% /dd %}

{% dt %}
`logEventMapper`
{% /dt %}

{% dd %}
Optional**Type**: `LogEventMapper`**Default**: `null`Custom function to modify the attributes of a Log event before it is sent to Datadog.
{% /dd %}

{% dt %}
`customEndpoint`
{% /dt %}

{% dd %}
Optional**Type**: String**Default**: `undefined`Sets a target custom server for Logs.
{% /dd %}

{% /dl %}

### Trace configuration{% #trace-configuration %}

{% dl %}

{% dt %}
`customEndpoint`
{% /dt %}

{% dd %}
Optional**Type**: String**Default**: `undefined`Sets a target custom server for Traces.
{% /dd %}

{% /dl %}

## Manual instrumentation{% #manual-instrumentation %}

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

### Send 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{% #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{% #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{% #manually-track-rum-errors %}

You can manually track RUM errors:

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

### Manually track RUM resources{% #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{% #notify-the-sdk-that-your-view-finished-loading-2 %}

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{% #add-custom-timings %}

You can add custom timings:

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

### Manually send spans{% #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{% #track-custom-global-attributes-4 %}

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

### Track user sessions{% #track-user-sessions-4 %}

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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format"
   alt="User API in RUM UI" /%}

| Attribute       | Type   | Description                                                                                                                              |
| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `usr.id`        | String | (Required) Unique user identifier.                                                                                                       |
| `usr.name`      | String | (Optional) User friendly name, displayed by default in the RUM UI.                                                                       |
| `usr.email`     | String | (Optional) User email, displayed in the RUM UI if the user name is not present.                                                          |
| `usr.extraInfo` | Object | (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{% #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{% #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 use the [`react-native-navigation`](https://github.com/wix/react-native-navigation) library, then add the `@datadog/mobile-react-native-navigation` package and follow the [setup instructions](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/react_native/integrated_libraries.md).
- If you use the [`react-navigation`](https://github.com/react-navigation/react-navigation) library, then add the `@datadog/mobile-react-navigation` package and follow the [setup instructions](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/react_native/integrated_libraries.md).

If you experience any issues setting up View tracking with `@datadog/mobile-react-navigation` you can see this Datadog [example application](https://github.com/DataDog/dd-sdk-reactnative-examples/tree/main/rum-react-navigation) as a reference.

## Clear all data{% #clear-all-data-4 %}

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

```
DdSdkReactNative.clearAllData();
```

## Modify or drop RUM events{% #modify-or-drop-rum-events-4 %}

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 Type               | Attribute key                   | Description                        |
| ------------------------ | ------------------------------- | ---------------------------------- |
| LogEvent                 | `logEvent.message`              | Message of the log.                |
| `logEvent.context`       | Custom attributes of the log.   |
| ActionEvent              | `actionEvent.context`           | Custom attributes of the action.   |
| ErrorEvent               | `errorEvent.message`            | Error message.                     |
| `errorEvent.source`      | Source of the error.            |
| `errorEvent.stacktrace`  | Stacktrace of the error.        |
| `errorEvent.context`     | Custom attributes of the error. |
| `errorEvent.timestampMs` | Timestamp of the error.         |
| ResourceEvent            | `resourceEvent.context`         | Custom attributes of the resource. |

Events include additional context:

| Event Type                                       | Context attribute key                                                   | Description                                                                                                                                                                                                      |
| ------------------------------------------------ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| LogEvent                                         | `logEvent.additionalInformation.userInfo`                               | Contains the global user info set by `DdSdkReactNative.setUserInfo`.                                                                                                                                             |
| `logEvent.additionalInformation.attributes`      | Contains the global attributes set by `DdSdkReactNative.addAttributes`. |
| ActionEvent                                      | `actionEvent.actionContext`                                             | [GestureResponderEvent](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/683ec4a2b420ff6bd3873a7338416ad3ec0b6595/types/react-native-side-menu/index.d.ts#L2) corresponding to the action or `undefined`. |
| `actionEvent.additionalInformation.userInfo`     | Contains the global user info set by `DdSdkReactNative.setUserInfo`.    |
| `actionEvent.additionalInformation.attributes`   | Contains the global attributes set by `DdSdkReactNative.addAttributes`. |
| ErrorEvent                                       | `errorEvent.additionalInformation.userInfo`                             | Contains the global user info set by `DdSdkReactNative.setUserInfo`.                                                                                                                                             |
| `errorEvent.additionalInformation.attributes`    | Contains the global attributes set by `DdSdkReactNative.addAttributes`. |
| ResourceEvent                                    | `resourceEvent.resourceContext`                                         | [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) corresponding to the resource or `undefined`.                                                                                  |
| `resourceEvent.additionalInformation.userInfo`   | Contains the global user info set by `DdSdkReactNative.setUserInfo`.    |
| `resourceEvent.additionalInformation.attributes` | Contains the global attributes set by `DdSdkReactNative.addAttributes`. |

## Retrieve the RUM session ID{% #retrieve-the-rum-session-id-4 %}

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-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{% #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](https://reactnative.dev/docs/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](https://github.com/DataDog/dd-sdk-reactnative-examples/tree/main/rum-react-navigation-async).

## Delaying the initialization{% #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{% #hybrid-app-monitoring %}

See [Monitor hybrid React Native applications](https://docs.datadoghq.com/real_user_monitoring/guide/monitor-hybrid-react-native-applications.md).
{% /section %}

{% section displayed-if="SDK is Kotlin Multiplatform" %}
This section only applies to users who meet the following criteria: SDK is Kotlin Multiplatform

If you have not set up the SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [Kotlin Multiplatform RUM setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform.md).

## Enrich user sessions{% #enrich-user-sessions-4 %}

Kotlin Multiplatform RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the [RUM Data Collection documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform/data_collected.md) 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{% #custom-views-3 %}

In addition to [tracking views automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform/advanced_configuration.md#automatically-track-views), 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{% #add-your-own-performance-timing-2 %}

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](https://docs.datadoghq.com/real_user_monitoring/explorer/search.md#setup-facets-and-measures) before graphing it in RUM analytics or in dashboards.

### Custom actions{% #custom-actions-3 %}

In addition to [tracking actions automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform/advanced_configuration.md#initialization-parameters), 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{% #enrich-resources-2 %}

When [tracking resources automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform.md#initialize-rum-ktor-plugin-to-track-network-events-made-with-ktor), 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{% #custom-resources-3 %}

In addition to [tracking resources automatically](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform.md#initialize-rum-ktor-plugin-to-track-network-events-made-with-ktor), 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{% #custom-errors-3 %}

To track specific errors, notify the monitor when an error occurs with the message, source, exception, and additional attributes. See the [Attributes collected documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform/data_collected.md).

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

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

### Add user properties{% #add-user-properties-3 %}

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

```
Datadog.addUserExtraInfo(extraInfo)
```

## Event and data management{% #event-and-data-management-2 %}

The Kotlin Multiplatform SDK first stores events. It only uploads these events when the [intake specification](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform.md#sending-data-when-device-is-offline) conditions are met.

### Clear all data{% #clear-all-data-5 %}

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

```
Datadog.clearAllData()
```

### Stop data collection{% #stop-data-collection-3 %}

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

```
Datadog.stopInstance()
```

### Set remote log threshold{% #set-remote-log-threshold-2 %}

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{% #track-custom-global-attributes-5 %}

In addition to the [default RUM attributes](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/kotlin_multiplatform/data_collected.md) 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{% #track-user-sessions-5 %}

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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format"
   alt="User API in RUM UI" /%}

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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{% #track-attributes-2 %}

```
// 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{% #track-background-events-2 %}

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)
```

{% alert level="info" %}
Tracking background events may lead to additional sessions, which can impact billing. For questions, [contact Datadog support](https://docs.datadoghq.com/help/).
{% /alert %}

## Initialization parameters{% #initialization-parameters-5 %}

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

{% dl %}

{% dt %}
`useSite(DatadogSite)`
{% /dt %}

{% dd %}
Switches target data to EU, US1, US3, US5, US1_FED, AP1, and AP2 sites.
{% /dd %}

{% dt %}
`setBatchSize([SMALL|MEDIUM|LARGE])`
{% /dt %}

{% dd %}
Defines the individual batch size for requests sent to Datadog.
{% /dd %}

{% dt %}
`setUploadFrequency([FREQUENT|AVERAGE|RARE])`
{% /dt %}

{% dd %}
Defines the frequency for requests made to Datadog endpoints (if requests are available).
{% /dd %}

{% dt %}
`setBatchProcessingLevel(LOW|MEDIUM|HIGH)`
{% /dt %}

{% dd %}
Defines the number of batches sent in each upload cycle.
{% /dd %}

{% dt %}
`trackCrashes(Boolean)`
{% /dt %}

{% dd %}
Allows you to control whether JVM/iOS crashes are tracked or not. The default value is `true`.
{% /dd %}

{% /dl %}

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

### Common configuration methods{% #common-configuration-methods %}

{% dl %}

{% dt %}
`trackLongTasks(durationThreshold)`
{% /dt %}

{% dd %}
Enables tracking tasks taking longer than `durationThreshold` on the main thread as long tasks in Datadog. See Automatically track long tasks for more information.
{% /dd %}

{% dt %}
`setVitalsUpdateFrequency([FREQUENT|AVERAGE|RARE|NEVER])`
{% /dt %}

{% dd %}
Sets the preferred frequency for collecting mobile vitals.
{% /dd %}

{% dt %}
`setSessionSampleRate(<sampleRate>)`
{% /dt %}

{% dd %}
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.)
{% /dd %}

{% dt %}
`setSessionListener(RumSessionListener)`
{% /dt %}

{% dd %}
Sets a listener to be notified on when a new RUM Session starts.
{% /dd %}

{% dt %}
`setTelemetrySampleRate`
{% /dt %}

{% dd %}
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`.
{% /dd %}

{% dt %}
`setViewEventMapper`
{% /dt %}

{% dd %}
Sets the ViewEventMapper for the RUM ViewEvent. You can use this interface implementation to modify the ViewEvent attributes before serialization.
{% /dd %}

{% dt %}
`setResourceEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ResourceEvent. You can use this interface implementation to modify the ResourceEvent attributes before serialization.
{% /dd %}

{% dt %}
`setActionEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ActionEvent. You can use this interface implementation to modify the ActionEvent attributes before serialization.
{% /dd %}

{% dt %}
`setErrorEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM ErrorEvent. You can use this interface implementation to modify the ErrorEvent attributes before serialization.
{% /dd %}

{% dt %}
`setLongTaskEventMapper`
{% /dt %}

{% dd %}
Sets the EventMapper for the RUM LongTaskEvent. You can use this interface implementation to modify the LongTaskEvent attributes before serialization.
{% /dd %}

{% dt %}
`trackBackgroundEvents`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`trackFrustrations`
{% /dt %}

{% dd %}
Enable/disable tracking of frustration signals.
{% /dd %}

{% /dl %}

### Android configuration methods{% #android-configuration-methods %}

These methods can be accessed only from Android source set.

{% dl %}

{% dt %}
`trackNonFatalAnrs(Boolean)`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`trackUserInteractions(Array<ViewAttributesProvider>)`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`useViewTrackingStrategy(strategy)`
{% /dt %}

{% dd %}
Defines the strategy used to track views. See Automatically track views for more information.
{% /dd %}

{% /dl %}

### iOS configuration methods{% #ios-configuration-methods %}

{% dl %}

{% dt %}
`trackUiKitViews(UIKitRUMViewsPredicate)`
{% /dt %}

{% dd %}
Enable automatic tracking of `UIViewController`s as RUM views. See Automatically track views for more information.
{% /dd %}

{% dt %}
`trackUiKitActions(UIKitRUMActionsPredicate)`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`setAppHangThreshold(Long)`
{% /dt %}

{% dd %}
Enables app hangs monitoring with the given threshold (in milliseconds). See [Add app hang reporting](https://docs.datadoghq.com/real_user_monitoring/error_tracking/mobile/ios.md#add-app-hang-reporting) for more information.
{% /dd %}

{% /dl %}

### Automatically track views{% #automatically-track-views-3 %}

#### Android{% #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:

{% dl %}

{% dt %}
`ActivityViewTrackingStrategy`
{% /dt %}

{% dd %}
Every activity in your application is considered a distinct view.
{% /dd %}

{% dt %}
`FragmentViewTrackingStrategy`
{% /dt %}

{% dd %}
Every fragment in your application is considered a distinct view.
{% /dd %}

{% dt %}
`MixedViewTrackingStrategy`
{% /dt %}

{% dd %}
Every activity or fragment in your application is considered a distinct view.
{% /dd %}

{% dt %}
`NavigationViewTrackingStrategy`
{% /dt %}

{% dd %}
Recommended for Android Jetpack Navigation library users. Each Navigation destination is considered a distinct view.
{% /dd %}

{% /dl %}

For instance, to set each fragment as a distinct view, use the following configuration in your [setup](https://app.datadoghq.com/rum/application/create):

```
// 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{% #ios %}

To automatically track views (`UIViewController`s), 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{% #automatically-track-long-tasks-2 %}

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{% #modify-or-drop-rum-events-5 %}

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 type           | Attribute key                                    | Description                                      |
| -------------------- | ------------------------------------------------ | ------------------------------------------------ |
| ViewEvent            | `view.referrer`                                  | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ActionEvent          | `action.target.name`                             | Target name.                                     |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ErrorEvent           | `error.message`                                  | Error message.                                   |
| `error.stack`        | Stacktrace of the error.                         |
| `error.resource.url` | URL of the resource.                             |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| ResourceEvent        | `resource.url`                                   | URL of the resource.                             |
| `view.referrer`      | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |
| LongTaskEvent        | `view.referrer`                                  | URL that linked to the initial view of the page. |
| `view.url`           | URL of the view.                                 |
| `view.name`          | Name of the view.                                |

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

## Retrieve the RUM session ID{% #retrieve-the-rum-session-id-5 %}

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
}
```
{% /section %}

{% section displayed-if="SDK is Roku" %}
This section only applies to users who meet the following criteria: SDK is Roku

If you have not set up the SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [Roku RUM setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/roku/setup.md).

## Track RUM resources{% #track-rum-resources %}

### roUrlTransfer{% #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{% #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{% #enrich-user-sessions-5 %}

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{% #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.

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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{% #track-custom-global-attributes-6 %}

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})
```
{% /section %}

{% section displayed-if="SDK is Unity" %}
This section only applies to users who meet the following criteria: SDK is Unity

If you have not set up the Datadog Unity SDK for RUM yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [RUM Unity setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/unity/setup.md). Learn how to set up OpenTelemetry with RUM Unity.

### Advanced initialization options{% #advanced-initialization-options %}

{% dl %}

{% dt %}
`Custom Endpoint`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`SDK Verbosity`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% dt %}
`Telemetry Sample Rate`
{% /dt %}

{% dd %}
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.
{% /dd %}

{% /dl %}

### Automatic view tracking{% #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{% #track-user-actions-2 %}

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{% #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{% #track-custom-resources-2 %}

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{% #track-custom-errors-2 %}

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{% #track-custom-global-attributes-7 %}

In addition to the [default RUM attributes](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/unity/data_collected.md) 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{% #set-a-custom-global-attribute-3 %}

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{% #track-user-sessions-6 %}

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

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format"
   alt="User API in the RUM UI" /%}

| Attribute   | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `usr.id`    | String | (Required) Unique user identifier.                                              |
| `usr.name`  | String | (Optional) User friendly name, displayed by default in the RUM UI.              |
| `usr.email` | String | (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{% #add-custom-user-attributes-2 %}

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{% #clear-all-data-6 %}

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

```
DatadogSdk.instance.ClearAllData();
```
{% /section %}



{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api-1.25bdf1f69bdca2ed94798fa98634f090.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api-1.25bdf1f69bdca2ed94798fa98634f090.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="" /%}

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/real_user_monitoring/browser/advanced_configuration/user-api.73b0cac9af174bfd4322133367d6e968.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="" /%}


