Advanced Configuration

このページは日本語には対応しておりません。随時翻訳に取り組んでいます。
翻訳に関してご質問やご意見ございましたら、お気軽にご連絡ください

SDK


Overview

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

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

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

Enrich user sessions

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

Custom views

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

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

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

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

Custom actions

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

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

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

Capture resource headers

When tracking resources automatically, you can capture HTTP request and response headers on RUM Resources by calling trackResourceHeaders on the DatadogInterceptor.Builder.

Captured headers appear on the RUM Resource event under resource.request.headers and resource.response.headers. You can query them in the RUM Explorer.

val interceptor = DatadogInterceptor.Builder(tracedHosts)
    .trackResourceHeaders()
    .build()
DatadogInterceptor interceptor = new DatadogInterceptor.Builder(tracedHosts)
    .trackResourceHeaders()
    .build();

With no arguments, trackResourceHeaders captures a predefined set of common headers:

DirectionHeaders
Requestcache-control, content-type
Responseage, cache-control, content-encoding, content-length, content-type, etag, expires, server-timing, vary, x-cache

To capture additional headers on top of the defaults, configure a ResourceHeadersExtractor and pass it to trackResourceHeaders. To skip the defaults, set includeDefaults = false.

Sensitive headers, such as tokens and API keys, are filtered out automatically, even if you list them explicitly.

Custom resource attributes

When tracking resources automatically, provide a custom RumResourceAttributesProvider to the DatadogInterceptor.Builder to add custom attributes to each tracked network request.

For example, if you want to surface an OkHttp request tag as a custom attribute on the resource, create an implementation as follows:

class CustomRumResourceAttributesProvider : RumResourceAttributesProvider {
    override fun onProvideAttributes(
        request: Request,
        response: Response?,
        throwable: Throwable?
    ): Map<String, Any?> {
        return mapOf("request.kind" to request.tag(String::class.java).orEmpty())
    }
}
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<>();
        String kind = request.tag(String.class);
        result.put("request.kind", kind != null ? kind : "");
        return result;
    }
}

Custom resources

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

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

Custom errors

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

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

Add user properties

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

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

Event and data management

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

Clear all data

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

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

Stop data collection

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

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

Control event buildup

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

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

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

See an example of this API being used.

Set remote log threshold

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

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

Track custom global attributes

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

Track user sessions

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

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

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

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

Track attributes

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

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

Track widgets

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

Initialization parameters

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

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

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

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

Automatically track views

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

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

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

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

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

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

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

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

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

Automatically track network requests

Basic network instrumentation

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

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

Cronet network instrumentation

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

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

Apollo instrumentation

  1. Set up RUM monitoring with Datadog Android RUM.

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

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

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

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

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

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

Automatically track long tasks

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

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

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

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

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

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

Modify or drop RUM events

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

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

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

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

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

Retrieve the RUM session ID

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

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

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

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

Enrich user sessions

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

Custom views

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

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

For example:

import DatadogRUM

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

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

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

DDRUMMonitor *rum = [DDRUMMonitor shared];

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

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

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

    [rum stopViewWithViewController:self attributes:nil];
}

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

Custom actions

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

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

For example:

import DatadogRUM

// in your `UIViewController`:

let rum = RUMMonitor.shared()

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

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

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

Custom resources

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

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

For example:

import DatadogRUM

// in your network client:

let rum = RUMMonitor.shared()

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

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

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

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

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

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

Custom errors

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

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

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

Track custom global attributes

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

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

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

Set a custom global attribute

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

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

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

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

Track user sessions

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

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

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

For example:

import DatadogCore

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

Track background events

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

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

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

import DatadogRUM

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

Initialization parameters

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

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

RUM configuration

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

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

Automatically track views

You can automatically track views with UIKit and SwiftUI.

UIKit

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

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

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

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

class YourCustomPredicate: UIKitRUMViewsPredicate {

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

@end

@implementation YourCustomPredicate

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

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

    return nil;
}

@end

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

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

class YourCustomPredicate: UIKitRUMViewsPredicate {

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

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

@end

@implementation YourCustomPredicate

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

    return nil;
}

@end

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

SwiftUI

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

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

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

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

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

@interface CustomSwiftUIPredicate : NSObject <DDSwiftUIRUMViewsPredicate>
@end

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

Notes:

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

Automatically track user actions

UIKit

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

SwiftUI

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

Notes:

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

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

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

@interface CustomSwiftUIActionsPredicate : NSObject <DDSwiftUIRUMActionsPredicate>
@end

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

Action reporting by iOS version

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

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

Automatically track network requests

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

(Optional) Enable detailed timing breakdown

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

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

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

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

Notes:

  • Without URLSessionInstrumentation, network requests are still tracked. Enabling it provides detailed timing breakdown for performance analysis.
  • In registered-delegate mode (URLSessionInstrumentation.enableDurationBreakdown), the data parameter passed to resourceAttributesProvider is subject to constraints. See below for full details.
  • To filter out specific requests from being tracked, use the resourceEventMapper in RUM.Configuration (see Modify or drop RUM events).

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

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

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

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


import DatadogRUM

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

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

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

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

@import DatadogRUM;

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

[DDRUM enableWith:configuration];

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

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

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

Note: data can be nil for reasons unrelated to response size, such as tasks without a completion handler (for example, async/await) or download tasks. In registered-delegate mode (when using URLSessionInstrumentation.enableDurationBreakdown), data is additionally nil in these cases:

  • Media responses (image/*, video/*, audio/*, application/octet-stream): the body is never buffered.
  • Responses of other types whose body exceeds 512 KB—the buffered data is discarded entirely, not truncated.

Capture resource headers

When tracking network requests automatically, you can capture HTTP request and response headers on RUM Resources by setting trackResourceHeaders on RUM.Configuration.URLSessionTracking. This option is disabled by default.

Captured headers appear on the RUM Resource event under resource.request.headers and resource.response.headers and are queryable in the RUM Explorer.

Use .defaults to capture a predefined set of common headers:

RUM.enable(
  with: RUM.Configuration(
    applicationID: "<rum application id>",
    urlSessionTracking: RUM.Configuration.URLSessionTracking(
        trackResourceHeaders: .defaults
    )
  )
)

The following headers are captured with .defaults:

DirectionHeaders
Requestcache-control, content-type
Responseage, cache-control, content-encoding, content-length, content-type, etag, expires, server-timing, vary, x-cache

To capture additional headers on top of the defaults, use .custom with .matchHeaders. For example, to also capture x-request-id and x-datadog-trace on both request and response:

RUM.enable(
  with: RUM.Configuration(
    applicationID: "<rum application id>",
    urlSessionTracking: RUM.Configuration.URLSessionTracking(
        trackResourceHeaders: .custom([
            .defaults,
            .matchHeaders(["x-request-id", "x-datadog-trace"])
        ])
    )
  )
)

Note: Sensitive headers (such as tokens, API keys, and cookies) are filtered out automatically, even if listed explicitly.

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

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

Apollo instrumentation

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

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

  1. Set up RUM monitoring with Datadog iOS RUM.

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

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

    Alternatively, you can add it using Xcode:

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

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

import Apollo

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

Add the Datadog interceptor to your Apollo Client setup:

import Apollo
import DatadogApollo

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

Configure network instrumentation using the provided DatadogApolloDelegate and DatadogApolloURLSession:

import Apollo
import DatadogApollo
import DatadogCore

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

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

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

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

Create an interceptor provider with the Datadog interceptor:

import Apollo
import DatadogApollo

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

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

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

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

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

    let datadogInterceptor = DatadogApolloInterceptor(sendGraphQLPayloads: true)
    

Automatically track errors

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

import DatadogLogs

let logger = Logger.create()

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

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

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

import DatadogTrace

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

Modify or drop RUM events

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Retrieve the RUM session ID

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

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

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

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

The trackingConsent setting can be one of the following values:

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

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

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

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

Add user properties

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

import DatadogCore

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

Data management

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

Clear all data

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

import DatadogCore

Datadog.clearAllData()

Stop data collection

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

import DatadogCore

Datadog.stopInstance()

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

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

Initialization parameters

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

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

RUM configuration

Use the following parameters for the DatadogRumConfiguration class.

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

Tracking from background isolates

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

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

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

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

  // Your background work
}

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

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

Automatically track resources

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

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

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

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

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

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

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

Capture resource headers

When tracking resources automatically, you can capture HTTP request and response headers on RUM Resources by setting trackResourceHeaders on DatadogRumConfiguration. This option applies to all Datadog HTTP tracking clients (Tracking HTTP Client, DatadogClient, Dio Interceptor, and GQL Link), but does not apply to the gRPC Interceptor. This option is disabled by default.

Captured headers appear on the RUM Resource event under resource.request.headers and resource.response.headers. You can query them in the RUM Explorer.

DatadogRumConfiguration(
  applicationId: '<rum-application-id>',
  trackResourceHeaders: ResourceHeadersExtractor(),
)

With no arguments, ResourceHeadersExtractor captures a predefined set of safe headers:

DirectionHeaders
Requestcache-control, content-type
Responseage, cache-control, content-encoding, content-length, content-type, etag, expires, server-timing, vary, x-cache

To capture additional headers in addition to the defaults, pass them through captureHeaders. To skip the defaults, set includeDefaults: false.

DatadogRumConfiguration(
  applicationId: '<rum-application-id>',
  trackResourceHeaders: ResourceHeadersExtractor(
    captureHeaders: ['x-request-id', 'x-custom-header'],
  ),
)

Sensitive headers, such as tokens and API keys, are filtered out automatically, even if you list them explicitly.

Track resources from other packages

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

Enrich user sessions

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

Notify the SDK that your view finished loading

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

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

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

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

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

Add your own performance timing

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

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

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

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

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

Track user actions

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

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

For example:

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

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

Track custom resources

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

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

For example:

// in your network client:

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

// Later

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

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

Track custom errors

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

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

Track custom global attributes

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

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

Set a custom global attribute

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

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

Track user sessions

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

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

To identify user sessions, use DatadogSdk.setUserInfo.

For example:

DatadogSdk.instance.setUserInfo("1234", "John Doe", "[email protected]");

Add custom user attributes

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

To remove an existing attribute, set it to null.

For example:

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

Clear all data

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

DatadogSdk.instance.clearAllData();

Modify or drop RUM events

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

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

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

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

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

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

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

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

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

Retrieve the RUM session ID

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

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

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

Flutter-specific performance metrics

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

OpenTelemetry setup

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

Datadog header generation

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

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

You can use this object during initial configuration:

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

You can then enable tracing as usual.

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

Check first party hosts

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

For example:

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

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

Jest testing

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

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

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

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

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

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

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

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

Initialization parameters

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

Core configuration

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

RUM configuration

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

Logs configuration

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

Trace configuration

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

Manual instrumentation

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

Send logs

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

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

Manually track RUM views

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

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

Manually track RUM actions

You can manually track RUM actions:

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

To track a continuous action:

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

Manually track RUM errors

You can manually track RUM errors:

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

Manually track RUM resources

You can manually track RUM resources:

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

Notify the SDK that your view finished loading

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

DdRum.addViewLoadingTime(true);

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

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

Note: This API is experimental.

Add custom timings

You can add custom timings:

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

Manually send spans

You can send spans manually:

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

Track custom global attributes

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

Track user sessions

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

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

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

DdSdkReactNative.setUserInfo({
    id: '1337',
    name: 'John Smith',
    email: '[email protected]',
    extraInfo: {
        type: 'premium'
    }
});

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

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

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

DdSdkReactNative.clearUserInfo();

Global attributes

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

Add multiple global attributes

Use addAttributes to add or update several attributes at once.

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

Add a single global attribute

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

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

If the attribute already exists, its value is overwritten.

Remove a single global attribute

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

DdSdkReactNative.removeAttribute('campaign_origin');

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

Remove multiple global attributes

Use removeAttributes to remove several attributes at once.

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

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

Track view navigation

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

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

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

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

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

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

Clear all data

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

DdSdkReactNative.clearAllData();

Modify or drop RUM events

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

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

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

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

        traceConfiguration: {}
    }
)

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

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

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

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

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

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

Events include additional context:

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

Retrieve the RUM session ID

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

You can access the RUM session ID at runtime with:

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

const rumSessionId = await DdRum.getCurrentSessionId();

Resource timings

Resource tracking provides the following timings:

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

Initializing asynchronously

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

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

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

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

When initializing the SDK asynchronously, the SDK uses React Native's requestIdleCallback to run the initialization code after all animations and UI rendering have settled.

If requestIdleCallback is not available, the SDK uses React Native's InteractionManager.runAfterInteractions to delay its initialization.

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

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

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

Delaying the initialization

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

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

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

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

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

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

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

Where your configuration has the following keys:

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

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

Hybrid app monitoring

See Monitor hybrid React Native applications.

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

Enrich user sessions

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

Custom views

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

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

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

Add your own performance timing

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

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

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

Custom actions

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

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

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

Enrich resources

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

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

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

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

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

Custom resources

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

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

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

Custom errors

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

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

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

Add user properties

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

Datadog.addUserExtraInfo(extraInfo)

Event and data management

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

Clear all data

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

Datadog.clearAllData()

Stop data collection

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

Datadog.stopInstance()

Set remote log threshold

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

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

Track custom global attributes

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

Track user sessions

Adding user information to your RUM sessions helps you to:

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

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

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

Track attributes

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

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

Track background events

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

Add the following snippet during RUM configuration:

.trackBackgroundEvents(true)

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

Initialization parameters

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

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

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

Common configuration methods

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

Android configuration methods

These methods can be accessed only from Android source set.

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

iOS configuration methods

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

Automatically track views

Android

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

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

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

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

internal expect fun platformSpecificSetup(
    rumConfigurationBuilder: RumConfiguration.Builder
)

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

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

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

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

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

iOS

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

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

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

class YourCustomPredicate: UIKitRUMViewsPredicate {

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

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

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

Automatically track long tasks

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

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

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

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

Modify or drop RUM events

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

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

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

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

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

Retrieve the RUM session ID

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

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

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

If you haven't set up the C++ SDK yet, follow the in-app setup instructions or see the RUM C++ setup documentation.

Instrument your application

The C++ SDK is a low-level library that is not coupled to a UI framework. As such, it does not automatically instrument your application. User interactions and changes in application state must be manually recorded by calling the appropriate RUM API.

Track views

A RUM session is organized into views. Each view represents a distinct user-facing screen, scene, or state in your application. All actions, resources, and errors are associated with the current view.

Each view has a string key that uniquely identifies it within your application. An optional name provides a human-readable label in the Datadog UI; if omitted, name defaults to the value of key. Only one view is active at a time: StartView implicitly stops the previous view.

// Begin tracking the main menu
rum->StartView("main_menu", "Main Menu");

// Transition to a gameplay view — implicitly stops "main_menu"
rum->StartView("gameplay_level1", "Level 1");

// Explicitly stop a view
rum->StopView("gameplay_level1");
/* Begin tracking the main menu */
dd_rum_start_view(rum, "main_menu", "Main Menu", NULL);

/* Transition to a gameplay view — implicitly stops "main_menu" */
dd_rum_start_view(rum, "gameplay_level1", "Level 1", NULL);

/* Explicitly stop a view */
dd_rum_stop_view(rum, "gameplay_level1", NULL);

Track actions

Actions record user interactions in the context of the current view. The SDK supports two kinds:

  • Discrete actions (AddAction): momentary events such as a button press. No explicit stop is required.
  • Continuous actions (StartAction / StopAction): events that span a duration of up to 10 seconds, such as a drag or scroll.

Available action types are Tap, Click, Scroll, Swipe, and Custom. Only one non-Custom action may be active at a time; AddAction with type Custom is always accepted regardless of other active actions.

// Record a discrete button tap
rum->AddAction(datadog::RumActionType::Tap, "confirm_button");

// Record the start and end of a scroll
rum->StartAction(datadog::RumActionType::Scroll, "item_list");
// ... user scrolls ...
rum->StopAction(datadog::RumActionType::Scroll);
/* Record a discrete button tap */
dd_rum_add_action(rum, DD_RUM_ACTION_TYPE_TAP, "confirm_button", NULL);

/* Record the start and end of a scroll */
dd_rum_start_action(rum, DD_RUM_ACTION_TYPE_SCROLL, "item_list", NULL);
/* ... user scrolls ... */
dd_rum_stop_action(rum, DD_RUM_ACTION_TYPE_SCROLL, NULL, NULL);

Track resources

Resources track HTTP requests (or any analogous network operation) made in the context of the current view. Each resource is identified by a key string that must be unique among all concurrently active resources; this is how StopResource and StopResourceWithError identify which request has completed.

// Record the start of an HTTP request
rum->StartResource("req-profile", datadog::RumResourceMethod::Get,
                   "https://api.example.com/profile");

// When the response arrives, record completion
rum->StopResource("req-profile", /*status_code=*/200, /*size=*/response_body_size,
                  datadog::RumResourceType::Native);

// If the request fails (no valid response received):
// rum->StopResourceWithError("req-profile", "Connection timeout",
//                            "NetworkError", /*stack=*/"", /*is_network=*/true);
/* Record the start of an HTTP request */
dd_rum_start_resource(rum, "req-profile", DD_RUM_RESOURCE_METHOD_GET,
                      "https://api.example.com/profile", NULL);

/* When the response arrives, record completion */
dd_rum_stop_resource(rum, "req-profile", 200, response_body_size,
                     DD_RUM_RESOURCE_TYPE_NATIVE, NULL);

/* If the request fails (no valid response received):
dd_rum_stop_resource_with_error(rum, "req-profile", "Connection timeout",
                                "NetworkError", "", true, 0, NULL); */

Use StopResourceWithError instead of StopResource when the request fails due to a network error or when processing the response produces an error.

Track errors

Custom errors can be reported in the context of the current view with AddError. The source field classifies where the error originates: use Source for bugs in application code, Network for connectivity issues, and Custom as a general-purpose catch-all. The type and stack_trace parameters are optional.

rum->AddError(datadog::RumErrorSource::Source,
              "Failed to deserialize save data",
              "SerializationError");
dd_rum_add_error(rum, DD_RUM_ERROR_SOURCE_SOURCE,
                 "Failed to deserialize save data",
                 "SerializationError", NULL, NULL);

Track operations

Operations let you measure multi-step workflows (such as login, checkout, or file upload) that may span multiple views. The SDK emits events when an operation starts and ends; Datadog aggregates these into duration and success-rate metrics.

The operations API is in preview and may change in future releases.

rum->StartOperation("user_login");

if (login_succeeded) {
    rum->SucceedOperation("user_login");
} else {
    rum->FailOperation("user_login", datadog::RumOperationFailureReason::Error);
}
dd_rum_start_operation(rum, "user_login", NULL, NULL);

if (login_succeeded) {
    dd_rum_succeed_operation(rum, "user_login", NULL, NULL);
} else {
    dd_rum_fail_operation(rum, "user_login", DD_RUM_FAILURE_REASON_ERROR, NULL, NULL);
}

For full details, see Operations Monitoring.

To update the SDK's tracking consent after initialization, call SetTrackingConsent on the core at any time. The SDK adjusts its behavior immediately:

  • Granted: The SDK sends all pending and future data to Datadog.
  • Pending: The SDK continues collecting data and storing it locally, but does not send it to Datadog.
  • NotGranted: The SDK deletes all pending data and stops collecting new data.
core->SetTrackingConsent(datadog::TrackingConsent::Granted);
dd_core_set_tracking_consent(core, DD_TRACKING_CONSENT_GRANTED);

Custom attributes

Custom attributes are key-value pairs that you attach to RUM events to enrich them with application-specific context. They can be scoped globally or per-view, as well as being applied to individual actions, resources, errors, or operations.

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

For example, to apply a set of custom attributes to all RUM events sent from that point forward:

rum->AddAttribute("account.tier", datadog::Attribute::String("premium"));
rum->AddAttribute("feature.new_ui", datadog::Attribute::Bool(true));

// Remove a global attribute
rum->RemoveAttribute("feature.new_ui");
dd_attribute_t tier_attr = dd_attribute_string("premium");
dd_rum_add_attribute(rum, "account.tier", &tier_attr);
dd_attribute_free(&tier_attr);

/* Remove a global attribute */
dd_rum_remove_attribute(rum, "feature.new_ui");

Note: Avoid spaces or special characters in attribute key names. For example, use "account_tier" instead of "Account Tier". Keys with spaces or special characters cannot be used as facets in the Datadog UI.

View attributes

View attributes attach to the current view only and do not persist to subsequent views. Where a view attribute and a global attribute share the same key, the view attribute takes precedence.

rum->AddViewAttribute("ui.variant", datadog::Attribute::String("A"));

// Remove a view attribute
rum->RemoveViewAttribute("ui.variant");
dd_attribute_t variant_attr = dd_attribute_string("A");
dd_rum_add_view_attribute(rum, "ui.variant", &variant_attr);
dd_attribute_free(&variant_attr);

/* Remove a view attribute */
dd_rum_remove_view_attribute(rum, "ui.variant");

Track user and account information

User information

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

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

To identify user sessions, call SetUserInfo on the core:

core->SetUserInfo("1234", "John Doe", "[email protected]");
dd_core_set_user_info(core, "1234", "John Doe", "[email protected]", NULL);

To add extra properties to the current user without replacing the existing user info, use AddUserExtraInfo. To remove all user information, call ClearUserInfo.

Account information

A parallel API is available for associating an account (such as an organization, workspace, or tenant) with the current session.

AttributeTypeDescription
acc.idString(Required) Unique account identifier.
acc.nameString(Optional) Account name, displayed in the Datadog UI.
core->SetAccountInfo("org-456", "Acme Corp");
dd_core_set_account_info(core, "org-456", "Acme Corp", NULL);

Use AddAccountExtraInfo to merge additional properties, and ClearAccountInfo to remove all account information.

Diagnostic logging

By default, the SDK prints warnings and errors to stderr. Both the threshold and the handler are configurable.

The threshold controls which severity levels are emitted. Levels below the threshold are silently dropped:

// Emit all messages (debug, status, warning, error)
config.SetDiagnosticThreshold(datadog::DiagnosticLevel::Debug);

// Emit only errors
config.SetDiagnosticThreshold(datadog::DiagnosticLevel::Error);
/* Emit all messages (debug, status, warning, error) */
dd_core_config_set_diagnostic_threshold(&config, DD_DIAGNOSTIC_LEVEL_DEBUG);

/* Emit only errors */
dd_core_config_set_diagnostic_threshold(&config, DD_DIAGNOSTIC_LEVEL_ERROR);

The handler controls what happens when a message is emitted. Supply a callback to route SDK messages into your own logging system. The text field in the message is only valid during the handler invocation - copy it if you need to store it persistently.

config.SetDiagnosticHandler([&](const datadog::DiagnosticMessage& message) {
    my_logger.write(message.text);
});

// Pass nullptr to suppress all diagnostic output
config.SetDiagnosticHandler(nullptr);
void my_handler(const dd_diagnostic_message_t* message, void* userdata) {
    my_logger_t* logger = (my_logger_t*)userdata;
    my_logger_write(logger, message->text);
}

/* Wire up the handler and supply a context pointer */
dd_core_config_set_diagnostic_handler(&config, my_handler);
dd_core_config_set_diagnostic_handler_userdata(&config, &my_logger);

/* Pass NULL to suppress all diagnostic output */
dd_core_config_set_diagnostic_handler(&config, NULL);

Application storage path

The storage path you configure must be a directory used exclusively by your application. The SDK assumes ownership of the .datadog/ subdirectory it creates there, freely creating and deleting files within it during normal operation.

If SetApplicationStoragePath is not called, the SDK defaults to the current working directory. This is not recommended; the SDK emits a diagnostic warning at startup if no path is explicitly configured.

To accept the current working directory and suppress the warning, pass "." explicitly:

// Recommended: use a dedicated directory owned by your application
config.SetApplicationStoragePath("/var/data/myapp");

// Accepted: explicitly use the current working directory
config.SetApplicationStoragePath(".");
/* Recommended: use a dedicated directory owned by your application */
dd_core_config_set_application_storage_path(&config, "/var/data/myapp");

/* Accepted: explicitly use the current working directory */
dd_core_config_set_application_storage_path(&config, ".");

SDK configuration reference

Required parameters

The following parameters are required to initialize the SDK. The first three are passed to CoreConfig; application_id is passed to RumConfig.

ParameterDescription
client_tokenThe client token associated with your RUM Application.
serviceApplication or service name, used for unified service tagging.
envDeployment environment, such as prod or staging.
application_idThe ID of your RUM Application.

Additional parameters

CoreConfig accepts these optional parameters:

ParameterDescription
versionApplication version string, used to filter sessions by release and track error rates across versions. Set with SetVersion().
variantBuild flavor or configuration, such as free or pro. Attached to all events as metadata.
siteDatadog data center for your organization. Defaults to us1. See Getting Started with Datadog Sites for available values.

Upload tuning

These parameters control how the SDK batches and uploads event data. The defaults work well for most applications; adjust them for resource-constrained environments or to tune upload latency.

ParameterOptionsDefaultDescription
batch_sizeSmall, Medium, LargeMediumControls how soon a batch of events is considered ready for upload. Smaller batches produce more frequent, smaller HTTP requests; larger batches produce fewer, larger requests.
upload_frequencyFrequent, Average, RareAverageControls how often upload cycles are initiated. More frequent cycling reduces the time between when an event is recorded and when it is sent to Datadog.
batch_processing_levelLow, Medium, HighMediumMaximum number of batches processed in a single upload cycle. Higher values increase throughput but may produce bursts of HTTP requests.
config.SetBatchSize(datadog::BatchSize::Small);
config.SetUploadFrequency(datadog::UploadFrequency::Frequent);
config.SetBatchProcessingLevel(datadog::BatchProcessingLevel::High);
dd_core_config_set_batch_size(&config, DD_BATCH_SIZE_SMALL);
dd_core_config_set_upload_frequency(&config, DD_UPLOAD_FREQUENCY_FREQUENT);
dd_core_config_set_batch_processing_level(&config, DD_BATCH_PROCESSING_LEVEL_HIGH);

Stop the current session

Call StopSession to explicitly end the current RUM session. The next call to StartView(), StartAction(), or AddAction() automatically starts a new session. If the new session is triggered by an action, the last active view from the previous session is restarted in the new session.

rum->StopSession();
dd_rum_stop_session(rum);

Stop the SDK

C++

In C++, Core and Rum are managed as std::shared_ptr references. The SDK stops automatically when the last reference to the core is released, so no explicit cleanup is required in typical usage.

To stop the SDK before it goes out of scope, call Stop() explicitly:

core->Stop();

C

The C API requires explicit resource management. Call the matching destroy function for every object created through the C API. Call dd_core_stop to halt all background activity, then free each feature, then free the core:

dd_core_stop(core);
dd_rum_destroy(rum);
dd_core_destroy(core);

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

Enrich user sessions

.NET MAUI RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the RUM Data Collected documentation for the events and default attributes the SDK reports. You can also enrich user session information and gain finer control over what's collected by tracking custom events.

Custom views

In addition to tracking views automatically, you can track specific views manually. Stop tracking when the view is no longer visible.

// Start a view
DdRum.StartView("home_screen", "Home");

// Stop the view
DdRum.StopView("home_screen");

Add your own performance timing

In addition to RUM's default attributes, you can measure where your application is spending its time with 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:

void OnHeroImageLoaded()
{
    DdRum.AddTiming("hero_image");
}

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

Set the view loading time

The SDK can record how long a view took to become interactive. Call AddViewLoadingTime from the page code that knows when the view is fully ready:

// Record the view's loading time once
DdRum.AddViewLoadingTime(overwrite: false);

Pass overwrite: true to replace a previously-recorded value for the same view.

Add view attributes

AddViewAttribute and RemoveViewAttribute attach key-value pairs to the active view event. Call AddViewAttribute after the view has been started by the SDK — with automatic view tracking enabled, override OnNavigatedTo on your page (not the constructor or OnAppearing). By the time OnNavigatedTo runs, the SDK has already called StartView for the destination, so the attribute is attached to the right view.

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
    DdRum.AddViewAttribute("screen_variant", "A");
}

// Later, to remove it:
DdRum.RemoveViewAttribute("screen_variant");

Custom actions

In addition to tracking actions automatically, you can track specific custom user actions (such as taps, clicks, and scrolls) with DdRum.AddAction. For continuous action tracking (for example, a user scrolling a list), use StartAction and StopAction.

// Single-shot action
DdRum.AddAction(RumActionType.Tap, "Login Button");

// Continuous action
DdRum.StartAction(RumActionType.Scroll, "Feed Scroll");
// ... user scrolling ...
DdRum.StopAction(RumActionType.Scroll, "Feed Scroll");

Custom resources

In addition to tracking resources automatically, you can track specific custom resources (such as network requests and third-party provider APIs) with DdRum.StartResource and DdRum.StopResource. Provide a stable resource key, the HTTP method, and the URL when you start, and the status code, kind, and size when you stop.

DdRum.StartResource("api-call-1", RumResourceMethod.Get, "https://api.example.com/users");
// ... fetch the resource ...
DdRum.StopResource("api-call-1", 200, RumResourceKind.Xhr, 2048);

Track long-running operations

Use the operation API to track multi-step flows such as a checkout, file upload, or onboarding sequence. Operations span across views.

// Start the operation
DdRum.StartOperation(
    "checkout",
    operationKey: "op-1",
    new Dictionary<string, object> { { "step", "payment" } });

// On success
DdRum.SucceedOperation("checkout", operationKey: "op-1");

// On failure
DdRum.FailOperation(
    "checkout",
    OperationFailure.Error,
    operationKey: "op-1",
    new Dictionary<string, object> { { "error_code", 500 } });

Custom errors

To track a specific error, notify the SDK with the message, source, and a stack trace string. See the Attributes collected documentation.

DdRum.AddError("Something went wrong", RumErrorSource.Source, "stacktrace here");

Track custom global attributes

In addition to the default RUM attributes captured by the SDK, you can attach contextual information — such as feature flags, experiment IDs, plan tier, or other business attributes — to every event the SDK sends.

Track user sessions

Adding user information to your RUM sessions helps you:

  • Follow the journey of a given user
  • Identify which users are most impacted by errors
  • Monitor performance for your most important users
AttributeTypeDescription
usr.idString(Required) Unique user identifier.
usr.nameString(Optional) User friendly name, displayed by default in the RUM UI.
usr.emailString(Optional) User email, displayed in the RUM UI when the user name isn't present.
// Set the user (id is required)
DdSdk.SetUserInfo("user-123", "Jane Doe", "[email protected]",
    new Dictionary<string, object> { { "plan", "premium" } });

// Append extra fields to the user later (merges with what's already there)
DdSdk.AddUserExtraInfo(new Dictionary<string, object> { { "subscription", "annual" } });

// Clear the user (for example, on sign-out)
DdSdk.ClearUserInfo();

Track account sessions

For B2B applications, DdSdk.SetAccountInfo attaches an account identity to every event. Use it together with — not instead of — user info.

DdSdk.SetAccountInfo("acct-456", "Acme Corp",
    new Dictionary<string, object> { { "tier", "enterprise" } });

DdSdk.AddAccountExtraInfo(new Dictionary<string, object> { { "region", "us-east" } });

DdSdk.ClearAccountInfo();

Track global attributes

Global attributes are attached to every RUM, Log, and Trace event the SDK emits.

// Add one attribute
DdSdk.AddAttribute("plan", "premium");

// Add several at once
DdSdk.AddAttributes(new Dictionary<string, object>
{
    { "plan", "premium" },
    { "experiment", "new-checkout-flow" }
});

// Remove one
DdSdk.RemoveAttribute("experiment");

// Remove several
DdSdk.RemoveAttributes(new List<string> { "plan", "experiment" });

Customize automatic tracking

By default, the SDK automatically tracks:

  • Views: MAUI page navigations via Application.PageAppearing (one app-level event covering Shell route changes, Navigation.PushAsync, and modals). For Shell apps, the destination route is resolved at Shell.Navigating time and used as the view name (for example, MainPage/DetailPage).
  • Actions: User interactions with buttons, switches, checkboxes, pickers, and gesture recognizers. Button and ImageButton taps fire on Pressed (not Clicked) so the action is recorded against the source view before any navigation triggered by a Clicked handler can shift the active view. A consequence is that an abandoned press (finger dragged off the button before release) is recorded as a tap.
  • Resources: HTTP requests via DiagnosticListener (every HttpClient request, including those issued by third-party libraries).

To customize or disable any of these, configure DdRumConfiguration:

DdRum.Enable(new DdRumConfiguration
{
    ApplicationId = "<APPLICATION_ID>",

    // Disable an automatic tracker
    AutomaticViewTracking = false,
    AutomaticActionTracking = false,
    AutomaticResourceTracking = false,

    // Or customize the view name
    ViewNamePredicate = (page) => page switch
    {
        MainPage => "Home",
        _ => null  // use the default name
    },

    // Skip specific pages from view tracking
    ViewTrackingPredicate = (page) => page is not SplashPage,

    // Filter or modify auto-tracked actions
    ActionEventMapper = (action) =>
    {
        if (action.Name.Contains("Debug")) return null;  // drop
        return action;
    },

    // Filter or modify auto-tracked resources
    ResourceEventMapper = (resource) =>
    {
        if (resource.Url.Contains("analytics")) return null;  // drop
        return resource;
    },
});

View naming priority

View names are resolved in this order:

  1. Custom ViewNamePredicate (if set and returns a non-null value).
  2. Resolved Shell route (forward and back navigations both produce absolute paths like MainPage/DetailPage).
  3. Page class name.

Pages pushed via Navigation.PushAsync (which Shell internally assigns synthetic D_FAULT_… routes) fall through to the page class name.

Action target naming priority

Action target names are resolved in this order:

  1. AutomationId
  2. StyleId (the x:Name attribute)
  3. The control's type name

Use ActionEventMapper to override the resolved name further.

Known limitation: gesture-driven navigation

TapGestureRecognizer.Tapped and SwipeGestureRecognizer.Swiped only fire on completion. If a tap or swipe handler triggers a navigation, the resulting action is bucketed under the destination view rather than the source. This applies only to Views with explicit gesture recognizers; Button and ImageButton taps are unaffected.

Modify or drop RUM events

Use ErrorEventMapper to modify or drop error events before they're sent to Datadog. The mapper receives a DdRumErrorEvent with Message, Source, Stacktrace, Context, and TimestampMs properties, and applies to both automatic and manual errors.

DdRum.Enable(new DdRumConfiguration
{
    ApplicationId = "<APPLICATION_ID>",
    ErrorEventMapper = errorEvent =>
    {
        // Attach extra context to every error
        errorEvent.Context["team"] = "mobile";

        // Drop errors matching a pattern
        if (errorEvent.Message.Contains("ignore-this"))
            return null;

        // Modify the message
        errorEvent.Message = "[MyApp] " + errorEvent.Message;

        return errorEvent;
    }
});

Return null to drop the event entirely.

ActionEventMapper and ResourceEventMapper work the same way and apply to actions and resources captured by the automatic trackers.

Stop the current session

Call DdRum.StopSession to terminate the current RUM session. A new session is created the next time an event is recorded (for example, a new view or a tap).

DdRum.StopSession();

Proxy configuration

To route all SDK traffic through a proxy, pass a ProxyConfiguration when initializing the SDK:

DdSdk.Initialize(new DdSdkConfiguration
{
    ClientToken = "<CLIENT_TOKEN>",
    Environment = "<ENV_NAME>",
    TrackingConsent = TrackingConsent.Granted,
    ProxyConfiguration = new ProxyConfiguration
    {
        Type = ProxyType.Http,
        Address = "proxy.example.com",
        Port = 8080,
        Username = "user",       // optional, HTTP/HTTPS only
        Password = "password"    // optional, HTTP/HTTPS only
    }
});

Supported proxy types: Http, Https, Socks. Authentication is supported for HTTP and HTTPS proxies only.

The same configuration can be loaded from a JSON file:

{
  "ClientToken": "<CLIENT_TOKEN>",
  "Environment": "<ENV_NAME>",
  "ProxyConfiguration": {
    "Type": "Http",
    "Address": "proxy.example.com",
    "Port": 8080,
    "Username": "user",
    "Password": "password"
  }
}

Custom endpoints

For testing against a local mock server, an on-premises Datadog deployment, or a corporate proxy, the Logs and Traces features accept a custom endpoint at enable time:

DdLogs.Enable(new DdLogsConfiguration
{
    CustomEndpoint = "https://logs-proxy.example.com/v1/input"
});

DdTrace.Enable(new DdTraceConfiguration
{
    CustomEndpoint = "https://traces-proxy.example.com/v1/input"
});

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

Track RUM resources

roUrlTransfer

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

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

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

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

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

sub performRequest()

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

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

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

Streaming resources

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

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

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

Enrich user sessions

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

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

Identifying your users

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

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

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

    m.global.setField("datadogUserInfo", { id: 42, name: "Abcd Efg", email: "[email protected]"})

Track custom global attributes

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

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

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

Advanced initialization options

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

Automatic view tracking

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

Track user actions

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

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

For example:

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

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

Track resources

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

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

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

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

Track custom resources

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

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

For example:

// in your network client:

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

// Later

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

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

Track custom errors

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

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

Track custom global attributes

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

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

Set a custom global attribute

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

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

Track user sessions

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

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

To identify user sessions, use DatadogSdk.SetUserInfo.

For example:

DatadogSdk.Instance.SetUserInfo("1234", "John Doe", "[email protected]");

Add custom user attributes

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

To remove an existing attribute, set it to null.

For example:

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

Clear all data

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

DatadogSdk.instance.ClearAllData();