RUM Android Monitoring

Overview

Datadog Real User Monitoring (RUM) enables you to visualize and analyze the real-time performance and user journeys of your application’s individual users.

The Datadog Android SDK supports Android 4.4 (API level 19)+ and Android TV.

Setup

  1. Declare SDK as a dependency.
  2. Specify application details in UI.
  3. Initialize the library with application context.
  4. Initialize RUM Monitor, Interceptor and start sending data.

Declare SDK as dependency

Declare dd-sdk-android and the Gradle plugin as a dependency in your application module’s build.gradle file.

buildscript {
    dependencies {
        classpath("com.datadoghq:dd-sdk-android-gradle-plugin:x.x.x")
    }
}
plugins {
    id("com.datadoghq.dd-sdk-android-gradle-plugin")
    //(...)
}
android {
    //(...)
}
dependencies {
    implementation "com.datadoghq:dd-sdk-android:x.x.x" 
    //(...)
}

Specify application details in the UI

  1. Navigate to UX Monitoring > RUM Applications > New Application.
  2. Select android as the application type and enter an application name to generate a unique Datadog application ID and client token.
Create a RUM application in Datadog workflow

To ensure the safety of your data, you must use a client token. If you used only Datadog API keys to configure the dd-sdk-android library, they would be exposed client-side in the Android application’s APK byte code.

For more information about setting up a client token, see the Client Token documentation.

Initialize the library with application context

See ViewTrackingStrategy to enable automatic tracking of all your views (activities, fragments, and more), trackingConsent to add GDPR compliance for your EU users, and other configuration options to initialize the library.

    class SampleApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            val configuration = Configuration.Builder(
                    logsEnabled = true,
                    tracesEnabled = true,
                    crashReportsEnabled = true,
                    rumEnabled = true
                )
                .useSite(DatadogSite.US1)
                .trackInteractions()
                .trackLongTasks(durationThreshold)
                .useViewTrackingStrategy(strategy)
                .build()
            val credentials = Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>)
            Datadog.initialize(this, credentials, configuration, trackingConsent)
        }
    }
    public class SampleApplication extends Application { 
        @Override 
        public void onCreate() { 
            super.onCreate();
            final Configuration configuration = 
                    new Configuration.Builder(true, true, true, true)
                            .trackInteractions()
                            .trackLongTasks(durationThreshold)
                            .useViewTrackingStrategy(strategy)
                            .useSite(DatadogSite.US1)
                            .build();
               final Credentials credentials = new Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>);
               Datadog.initialize(this, credentials, configuration, trackingConsent); 
        }
    }

    class SampleApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            val configuration = Configuration.Builder(
                    logsEnabled = true,
                    tracesEnabled = true,
                    crashReportsEnabled = true,
                    rumEnabled = true
                )
                .useSite(DatadogSite.EU1)
                .trackInteractions()
                .trackLongTasks(durationThreshold)
                .useViewTrackingStrategy(strategy)
                .build()
            val credentials = Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>)
            Datadog.initialize(this, credentials, configuration, trackingConsent)
        }
    }
    public class SampleApplication extends Application { 
        @Override 
        public void onCreate() { 
            super.onCreate();
            final Configuration configuration = 
                    new Configuration.Builder(true, true, true, true)
                            .trackInteractions()
                            .trackLongTasks(durationThreshold)
                            .useViewTrackingStrategy(strategy)
                            .useSite(DatadogSite.EU1)
                            .build();
            Credentials credentials = new Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>);
            Datadog.initialize(this, credentials, configuration, trackingConsent); 
        }
    }

    class SampleApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            val configuration = Configuration.Builder(
                    logsEnabled = true,
                    tracesEnabled = true,
                    crashReportsEnabled = true,
                    rumEnabled = true
                )
                .useSite(DatadogSite.US3)
                .trackInteractions()
                .trackLongTasks(durationThreshold)
                .useViewTrackingStrategy(strategy)
                .build()
            val credentials = Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>)
            Datadog.initialize(this, credentials, configuration, trackingConsent)
        }
    }
    public class SampleApplication extends Application { 
        @Override 
        public void onCreate() { 
            super.onCreate();
            final Configuration configuration = 
                    new Configuration.Builder(true, true, true, true)
                            .trackInteractions()
                            .trackLongTasks(durationThreshold)
                            .useViewTrackingStrategy(strategy)
                            .useSite(DatadogSite.US3)
                            .build();
            Credentials credentials = new Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>);
            Datadog.initialize(this, credentials, configuration, trackingConsent); 
        }
    }

    class SampleApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            val configuration = Configuration.Builder(
                    logsEnabled = true,
                    tracesEnabled = true,
                    crashReportsEnabled = true,
                    rumEnabled = true
                )
                .useSite(DatadogSite.US5)
                .trackInteractions()
                .trackLongTasks(durationThreshold)
                .useViewTrackingStrategy(strategy)
                .build()
            val credentials = Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>)
            Datadog.initialize(this, credentials, configuration, trackingConsent)
        }
    }
    public class SampleApplication extends Application { 
        @Override 
        public void onCreate() { 
            super.onCreate();
            final Configuration configuration = 
                    new Configuration.Builder(true, true, true, true)
                            .trackInteractions()
                            .trackLongTasks(durationThreshold)
                            .useViewTrackingStrategy(strategy)
                            .useSite(DatadogSite.US5)
                            .build();
            Credentials credentials = new Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>);
            Datadog.initialize(this, credentials, configuration, trackingConsent); 
        }
    }

    class SampleApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            val configuration = Configuration.Builder(
                    logsEnabled = true,
                    tracesEnabled = true,
                    crashReportsEnabled = true,
                    rumEnabled = true
                )
                .useSite(DatadogSite.US1_FED)
                .trackInteractions()
                .trackLongTasks(durationThreshold)
                .useViewTrackingStrategy(strategy)
                .build()
            val credentials = Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>)
            Datadog.initialize(this, credentials, configuration, trackingConsent)
        }
    }
    public class SampleApplication extends Application { 
        @Override 
        public void onCreate() { 
            super.onCreate();
            final Configuration configuration = 
                    new Configuration.Builder(true, true, true, true)
                            .trackInteractions()
                            .trackLongTasks(durationThreshold)
                            .useViewTrackingStrategy(strategy)
                            .useSite(DatadogSite.US1_FED)
                            .build();
            Credentials credentials = new Credentials(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>, <APPLICATION_ID>);
            Datadog.initialize(this, credentials, configuration, trackingConsent); 
        }
    }

The credentials for initialization require your application’s variant name and uses the value of BuildConfig.FLAVOR or an empty string if you don’t have variants. This enables the correct ProGuard mapping.txt file to automatically upload at build time so you can view de-obfuscated RUM error stack traces. For more information, see the guide to uploading Android source mapping files.

Initialize RUM Monitor and Interceptor

Configure and register the RUM Monitor. You only need to do it once in your application’s onCreate() method.

     val monitor = RumMonitor.Builder().build()
     GlobalRum.registerIfAbsent(monitor)
     final RumMonitor monitor = new RumMonitor.Builder().build();
     GlobalRum.registerIfAbsent(monitor);

To track your OkHttp requests as resources, add the provided Interceptor:

     val okHttpClient =  OkHttpClient.Builder()
         .addInterceptor(DatadogInterceptor())
         .build()
     final OkHttpClient okHttpClient =  new OkHttpClient.Builder()
         .addInterceptor(new DatadogInterceptor())
         .build();

This records each request processed by the OkHttpClient as a resource in RUM, with all the relevant information automatically filled (URL, method, status code, and error). Only the network requests that started when a view is active are tracked. To track requests when your application is in the background, create a view manually.

Note: If you also use multiple Interceptors, call DatadogInterceptor first.

You can also add an EventListener for the OkHttpClient to automatically track resource timing for third-party providers and network requests.

Further Reading

Additional helpful documentation, links, and articles: