From 4ed27f6f78ba08fcdaa514ff462400f8eb9e960b Mon Sep 17 00:00:00 2001 From: Rosa Trieu Date: Thu, 10 Oct 2024 11:59:36 -0700 Subject: [PATCH 01/54] android --- config/_default/menus/main.en.yaml | 90 ++- .../error_tracking/frontend/mobile/android.md | 2 +- .../mobile_and_tv_monitoring/_index.md | 22 +- .../advanced_configuration/android.md | 1 + .../android/_index.md | 34 + .../android/advanced_configuration.md | 630 ++++++++++++++++++ .../android/data_collected.md | 274 ++++++++ .../android/error_tracking.md | 287 ++++++++ .../android/integrated_libraries.md | 170 +++++ .../android/mobile_vitals.md | 5 + .../mobile_and_tv_monitoring/android/setup.md | 480 +++++++++++++ .../android/troubleshooting.md | 50 ++ .../android/web_view_tracking.md | 5 + layouts/partials/nav/left-nav.html | 3 +- .../rum/rum-getting-started-mobile-setup.html | 22 +- 15 files changed, 2030 insertions(+), 45 deletions(-) create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/_index.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/data_collected.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/setup.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting.md create mode 100644 content/en/real_user_monitoring/mobile_and_tv_monitoring/android/web_view_tracking.md diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml index 2f64a69e55dfa..6510529a021d6 100644 --- a/config/_default/menus/main.en.yaml +++ b/config/_default/menus/main.en.yaml @@ -6472,51 +6472,81 @@ menu: parent: rum identifier: mobile_and_tv_monitoring weight: 2 - - name: Setup - url: real_user_monitoring/mobile_and_tv_monitoring/setup + - name: Android and Android TV + url: real_user_monitoring/mobile_and_tv_monitoring/android parent: mobile_and_tv_monitoring - identifier: rum_mobile_setup + identifier: rum_mobile_android weight: 201 + - name: Setup + url: real_user_monitoring/mobile_and_tv_monitoring/android/setup + parent: rum_mobile_android + identifier: rum_mobile_android_setup + weight: 101 - name: Crash Reporting - url: real_user_monitoring/error_tracking/mobile + url: real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking + parent: rum_mobile_android + identifier: rum_mobile_android_crash + weight: 102 + - name: Advanced Configuration + url: real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration + parent: rum_mobile_android + identifier: rum_mobile_android_advanced_config + weight: 103 + - name: Data Collected + url: real_user_monitoring/mobile_and_tv_monitoring/android/data_collected + parent: rum_mobile_android + identifier: rum_mobile_android_data_collected + weight: 104 + - name: Mobile Vitals + url: real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals + parent: rum_mobile_android + identifier: rum_mobile_android_mobile_vitals + weight: 105 + - name: Web View Tracking + url: real_user_monitoring/mobile_and_tv_monitoring/android/web_view_tracking + parent: rum_mobile_android + identifier: rum_mobile_android_web_view_tracking + weight: 106 + - name: Integrated Libraries + url: real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries + parent: rum_mobile_android + identifier: rum_mobile_android_integrated_libraries + weight: 107 + - name: Troubleshooting + url: real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting + parent: rum_mobile_android + identifier: rum_mobile_android_troubleshooting + weight: 108 + - name: iOS and tvOS + url: real_user_monitoring/mobile_and_tv_monitoring/ios parent: mobile_and_tv_monitoring - identifier: rum_mobile_error_tracking + identifier: rum_mobile_ios weight: 202 - - name: Advanced Configuration - url: real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/ + - name: Flutter + url: real_user_monitoring/mobile_and_tv_monitoring/flutter parent: mobile_and_tv_monitoring - identifier: rum_mobile_advanced + identifier: rum_mobile_flutter weight: 203 - - name: Data Collected - url: real_user_monitoring/mobile_and_tv_monitoring/data_collected + - name: Kotlin Multiplatform + url: real_user_monitoring/mobile_and_tv_monitoring/kotlin_multiplatform parent: mobile_and_tv_monitoring - identifier: rum_mobile_data_collected + identifier: rum_mobile_kotlin weight: 204 - - name: Mobile Vitals - url: real_user_monitoring/mobile_and_tv_monitoring/mobile_vitals + - name: React Native + url: real_user_monitoring/mobile_and_tv_monitoring/react_native parent: mobile_and_tv_monitoring - identifier: rum_mobile_vitals + identifier: rum_mobile_react_native weight: 205 - - name: Web View Tracking - url: real_user_monitoring/mobile_and_tv_monitoring/web_view_tracking + - name: Roku + url: real_user_monitoring/mobile_and_tv_monitoring/roku parent: mobile_and_tv_monitoring - identifier: rum_mobile_web_view_tracking + identifier: rum_mobile_roku weight: 206 - - name: Integrated Libraries - url: real_user_monitoring/mobile_and_tv_monitoring/integrated_libraries + - name: Unity + url: real_user_monitoring/mobile_and_tv_monitoring/unity parent: mobile_and_tv_monitoring - identifier: rum_mobile_integrated_libraries + identifier: rum_mobile_unity weight: 207 - - name: Troubleshooting - url: real_user_monitoring/mobile_and_tv_monitoring/troubleshooting/ - parent: mobile_and_tv_monitoring - identifier: rum_mobile_troubleshooting - weight: 208 - - name: Supported Versions - url: real_user_monitoring/mobile_and_tv_monitoring/supported_versions/ - parent: mobile_and_tv_monitoring - identifier: rum_mobile_supported_versions - weight: 209 - name: Platform identifier: real_user_monitoring_platform url: real_user_monitoring/platform diff --git a/content/en/error_tracking/frontend/mobile/android.md b/content/en/error_tracking/frontend/mobile/android.md index 18acfc08ec41b..2d54322fc5c88 100644 --- a/content/en/error_tracking/frontend/mobile/android.md +++ b/content/en/error_tracking/frontend/mobile/android.md @@ -2,4 +2,4 @@ title: Android Crash Reporting and Error Tracking --- -{{< include-markdown "real_user_monitoring/error_tracking/mobile/android" >}} \ No newline at end of file +{{< include-markdown "real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking" >}} \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/_index.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/_index.md index 641ae406475a8..132a5db4e0733 100644 --- a/content/en/real_user_monitoring/mobile_and_tv_monitoring/_index.md +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/_index.md @@ -8,8 +8,26 @@ further_reading: text: 'Session Replay' --- +## Overview + +Datadog Mobile Real User Monitoring (RUM) provides insights into your mobile application's performance on Android, iOS, React Native, Flutter, Roku, and more. You can gain valuable visibility into your app's stability, identify and address app crashes, and asses any glitchiness that may impact user experience. + +Datadog correlates each user journey with relevant synthetic tests, backend metrics, traces, logs, and network performance, so you can detect and resolve poor user experience, optimize releases, and deliver high-performing applications to users. + ## Get started -Select an application type to start collecting RUM data: +Select a platform to start collecting RUM data on your application: + +{{< partial name="rum/rum-getting-started-mobile-setup.html" >}} + +## WIP + +## Track, prioritize, and fix app crashes + +## Troubleshoot mobile performance issues + +## Deployment tracking + +## Understand product usage and user demographics -{{< partial name="rum/rum-getting-started-mobile-setup.html" >}} \ No newline at end of file +## Visualize user journeys with Mobile Session Replay \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android.md index a0e4ad01c01e8..9fe2233c974f0 100644 --- a/content/en/real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android.md +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android.md @@ -5,6 +5,7 @@ type: multi-code-lang code_lang_weight: 10 aliases: - /real_user_monitoring/android/advanced_configuration/ + - /real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android further_reading: - link: https://github.com/DataDog/dd-sdk-android tag: "Source Code" diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/_index.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/_index.md new file mode 100644 index 0000000000000..e433fcde71751 --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/_index.md @@ -0,0 +1,34 @@ +--- +title: RUM Android and Android TV Monitoring +further_reading: +- link: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration + tag: Documentation + text: RUM Android Advanced Configuration +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: Source code for dd-sdk-android +- link: /real_user_monitoring + tag: Documentation + text: Explore Datadog RUM +--- +## 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 5.0+ (API level 21) and Android TV. It works for Android apps written using Java or Kotlin. + +## Start monitoring Android applications + +To get started with RUM for Android, create an application and configure the Android SDK. + +{{< whatsnext desc="This section includes the following topics:">}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/setup">}}Setup: Learn how to the Android RUM SDK, track background events, and send data when devices are online.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/crash_reporting">}}Crash Reporting: Add NDK/ANR crash reporting, get deobfuscated stack traces, then test your implementation.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration">}}Advanced Configuration: Enrich user sessions, manage events and data, track custom global attributes and widgets, review initialization parameters, modify or drop RUM events, and more.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals">}}Data Collected: Review data that the RUM Android SDK collects.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals">}}Mobile Vitals: Mobile vitals include a set of data points that can help compute insights about your mobile application.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries">}} + Integrated Libraries: Integrated libraries you can use for your Android and Android TV applications.{{< /nextlink >}} + {{< nextlink href="/real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting">}} + Troubleshooting: Common troubleshooting RUM Android SDK issues.{{< /nextlink >}} +{{< /whatsnext >}} diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration.md new file mode 100644 index 0000000000000..574963a934814 --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration.md @@ -0,0 +1,630 @@ +--- +title: RUM Android Advanced Configuration +aliases: + - /real_user_monitoring/android/advanced_configuration/ + - /real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android +further_reading: +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: Source code for dd-sdk-android +- link: /real_user_monitoring + tag: Documentation + text: Explore Datadog RUM +--- +## Overview + +If you have not set up the SDK yet, follow the [in-app setup instructions][1] or refer to the [Android RUM setup documentation][2]. + +## Enrich user sessions + +Android RUM automatically tracks attributes such as user activity, screens, errors, and network requests. See the [RUM Data Collection documentation][3] 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][4], 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`: + + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + fun onResume() { + GlobalRumMonitor.get().startView(viewKey, viewName, viewAttributes) + } + + fun onPause() { + GlobalRumMonitor.get().stopView(viewKey, viewAttributes) + } + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + public void onResume() { + GlobalRumMonitor.get().startView(viewKey, viewName, viewAttributes); + } + + public void onPause() { + GlobalRumMonitor.get().stopView(viewKey, viewAttributes); + } + ``` +{{% /tab %}} +{{< /tabs >}} + +### 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: +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + fun onHeroImageLoaded() { + GlobalRumMonitor.get().addTiming("hero_image") + } + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + public void onHeroImageLoaded() { + GlobalRumMonitor.get().addTiming("hero_image"); + } + ``` +{{% /tab %}} +{{< /tabs >}} + +Once the timing is sent, the timing is accessible as `@view.custom_timings.`. For example: `@view.custom_timings.hero_image`. You must [create a measure][10] before graphing it in RUM analytics or in dashboards. + +### Custom Actions + +In addition to [tracking actions automatically][5], 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`. + +Note the action type should be one of the following: "custom", "click", "tap", "scroll", "swipe", "back". + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + fun onUserInteraction() { + GlobalRumMonitor.get().addAction(actionType, name, actionAttributes) + } + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + public void onUserInteraction() { + GlobalRumMonitor.get().addAction(actionType, name, actionAttributes); + } + ``` +{{% /tab %}} +{{< /tabs >}} + +### Enrich resources + +When [tracking resources automatically][6], provide a custom `RumResourceAttributesProvider` instance to add custom attributes to each tracked network request. For example, if you want to track a network request's headers, create an implementation as follows, and pass it in the constructor of the `DatadogInterceptor`. + +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class CustomRumResourceAttributesProvider : RumResourceAttributesProvider { + override fun onProvideAttributes( + request: Request, + response: Response?, + throwable: Throwable? + ): Map { + val headers = request.headers + return headers.names().associate { + "headers.${it.lowercase(Locale.US)}" to headers.values(it).first() + } + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class CustomRumResourceAttributesProvider implements RumResourceAttributesProvider { + @NonNull + @Override + public Map onProvideAttributes( + @NonNull Request request, + @Nullable Response response, + @Nullable Throwable throwable + ) { + Map result = new HashMap<>(); + Headers headers = request.headers(); + + for (String key : headers.names()) { + String attrName = "headers." + key.toLowerCase(Locale.US); + result.put(attrName, headers.values(key).get(0)); + } + + return result; + } +} +``` +{{% /tab %}} +{{< /tabs >}} + +### Custom Resources + +In addition to [tracking resources automatically][6], 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. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + fun loadResource() { + GlobalRumMonitor.get().startResource(resourceKey, method, url, resourceAttributes) + try { + // do load the resource + GlobalRumMonitor.get().stopResource(resourceKey, resourceKind, additionalAttributes) + } catch (e: Exception) { + GlobalRumMonitor.get().stopResourceWithError(resourceKey, message, origin, e) + } + } + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + public void loadResource() { + GlobalRumMonitor.get().startResource(resourceKey, method, url, resourceAttributes); + try { + // do load the resource + GlobalRumMonitor.get().stopResource(resourceKey, resourceKind, additionalAttributes); + } catch (Exception e) { + GlobalRumMonitor.get().stopResourceWithError(resourceKey, message, origin, e); + } + } + ``` +{{% /tab %}} +{{< /tabs >}} + +### Custom Errors + +To track specific errors, notify the monitor when an error occurs with the message, source, exception, and additional attributes. Refer to the [Error Attributes documentation][9]. + +```kotlin + 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. + +```kotlin +fun addUserProperties(extraInfo: Map, sdkCore: SdkCore = getInstance()) { + sdkCore.addUserProperties(extraInfo) +} +``` + +## Event and data management + +The Android SDK first stores events and only uploads events when the [intake specifications][11] conditions are met. + +### Clear all data + +You have the option of deleting all unsent data stored by the SDK with the `clearAllData` API. + +```kotlin +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. + +```kotlin + 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 input/output, 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. + +```kotlin + fun setBackpressureStrategy(backpressureStrategy: BackPressureStrategy): Builder { + coreConfig = coreConfig.copy(backpressureStrategy = backpressureStrategy) + return this + } +``` + +See an [example of this API][12] 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). + +```kotlin + fun setRemoteLogThreshold(minLogThreshold: Int): Builder { + minDatadogLogsPriority = minLogThreshold + return this + } +``` + +## Track custom global attributes + +In addition to the [default RUM attributes][3] 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 easy to: +* Follow the journey of a given user +* Know which users are the most impacted by errors +* Monitor performance for your most important users + +{{< img src="real_user_monitoring/browser/advanced_configuration/user-api.png" alt="User API in RUM UI" >}} + +The following attributes are **optional**, you should provide **at least one** of them: + +| Attribute | Type | Description | +|------------|------|----------------------------------------------------------------------------------------------------| +| usr.id | String | Unique user identifier. | +| usr.name | String | User friendly name, displayed by default in the RUM UI. | +| usr.email | String | User email, displayed in the RUM UI if the user name is not present. It is also used to fetch Gravatars. | + +To identify user sessions, use the `setUserInfo` API, for example: + +```kotlin +Datadog.setUserInfo('1234', 'John Doe', 'john@doe.com') +``` + +### Track attributes + +```kotlin + // 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][7]. + + +## Initialization parameters + +You can use the following methods in `Configuration.Builder` when creating the Datadog configuration to initialize the library: + +`setFirstPartyHosts()` +: Defines hosts that have tracing enabled and have RUM resources categorized as `first-party`. **Note**: If you define custom tracing header types in the Datadog configuration and are using a tracer registered with `GlobalTracer`, make sure the same tracing header types are set for the tracer in use. + +`useSite(DatadogSite)` +: Switches target data to EU1, US1, US3, US5, US1_FED and AP1 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)` +: 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](#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](#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()` +: 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. + +`useCustomEndpoint` +: Use RUM to target a custom server. + +### 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][1]: + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + .useViewTrackingStrategy(FragmentViewTrackingStrategy(...)) + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + .useViewTrackingStrategy(new FragmentViewTrackingStrategy(...)) + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + + +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: + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + .useViewTrackingStrategy( + ActivityViewTrackingStrategy( + trackExtras = true, + componentPredicate = object : ComponentPredicate { + override fun accept(component: Activity): Boolean { + return true + } + + override fun getViewName(component: Activity): String? = null + }) + ) + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + .useViewTrackingStrategy(new ActivityViewTrackingStrategy( + true, + new ComponentPredicate() { + @Override + public boolean accept(Activity component) { + return true; + } + + @Override + public String getViewName(Activity component) { + return null; + } + } + )) + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + + +**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 + +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][8] factory: + +1. Add the Gradle dependency to the `dd-sdk-android-okhttp` library in the module-level `build.gradle` file: + + ```groovy + dependencies { + implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x" + } + ``` + +2. Add add the [EventListener][8] factory: + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val okHttpClient = OkHttpClient.Builder() + .addInterceptor(DatadogInterceptor()) + .eventListenerFactory(DatadogEventListener.Factory()) + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + OkHttpClient okHttpClient = new OkHttpClient.Builder() + .addInterceptor(new DatadogInterceptor()) + .eventListenerFactory(new DatadogEventListener.Factory()) + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + +### 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. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + // … + .trackLongTasks(durationThreshold) + .build() + ``` + +For example, to replace the default `100 ms` duration, set a custom threshold in your configuration. + + ```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + // … + .trackLongTasks(250L) // track tasks longer than 250ms as long tasks + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + // … + .trackLongTasks(durationThreshold) + .build(); + ``` + +For example, to replace the default `100 ms` duration, set a custom threshold in your configuration. + + ```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + // … + .trackLongTasks(250L) // track tasks longer than 250ms as long tasks + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + +## 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` when initializing the RUM Android SDK: + + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + // ... + .setErrorEventMapper(rumErrorEventMapper) + .setActionEventMapper(rumActionEventMapper) + .setResourceEventMapper(rumResourceEventMapper) + .setViewEventMapper(rumViewEventMapper) + .setLongTaskEventMapper(rumLongTaskEventMapper) + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + // ... + .setErrorEventMapper(rumErrorEventMapper) + .setActionEventMapper(rumActionEventMapper) + .setResourceEventMapper(rumResourceEventMapper) + .setViewEventMapper(rumViewEventMapper) + .setLongTaskEventMapper(rumLongTaskEventMapper) + .build(); + + ``` +{{% /tab %}} +{{< /tabs >}} + + When implementing the `EventMapper` interface, only some attributes are modifiable for each event type: + + | Event type | Attribute key | Description | + |---------------|--------------------|-------------------------------------------------| + | ViewEvent | `view.referrer` | URL that linked to the initial view of the page. | + | | `view.url` | URL of the view. | + | | `view.name` | Name of the view. | + | ActionEvent | | | + | | `action.target.name` | Target name. | + | | `view.referrer` | URL that linked to the initial view of the page. | + | | `view.url` | URL of the view. | + | | `view.name` | Name of the view. | + | ErrorEvent | | | + | | `error.message` | Error message. | + | | `error.stack` | Stacktrace of the error. | + | | `error.resource.url` | URL of the resource. | + | | `view.referrer` | URL that linked to the initial view of the page. | + | | `view.url` | URL of the view. | + | | `view.name` | Name of the view. | + | ResourceEvent | | | + | | `resource.url` | URL of the resource. | + | | `view.referrer` | URL that linked to the initial view of the page. | + | | `view.url` | URL of the view. | + | | `view.name` | Name of the view. | + | LongTaskEvent | | | + | | `view.referrer` | URL that linked to the initial view of the page. | + | | `view.url` | URL of the view. | + | | `view.name` | Name of the view. | + + **Note**: If you return null from the `EventMapper` 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: + +```kotlin +GlobalRumMonitor.get().getCurrentSessionId { sessionId -> + currentSessionId = sessionId +} +``` + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://app.datadoghq.com/rum/application/create +[2]: /real_user_monitoring/android +[3]: /real_user_monitoring/android/data_collected +[4]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#automatically-track-views +[5]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#initialization-parameters +[6]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#automatically-track-network-requests +[7]: https://github.com/DataDog/dd-sdk-android/tree/master/sample/kotlin/src/main/kotlin/com/datadog/android/sample/widget +[8]: https://square.github.io/okhttp/features/events/ +[9]: /real_user_monitoring/android/data_collected/#event-specific-attributes +[10]: /real_user_monitoring/explorer/search/#setup-facets-and-measures +[11]: /real_user_monitoring/android/setup/#sending-data-when-device-is-offline +[12]: https://github.com/DataDog/dd-sdk-android/blob/eaa15cd344d1723fafaf179fcebf800d6030c6bb/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt#L279 \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/data_collected.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/data_collected.md new file mode 100644 index 0000000000000..d44f6c07c455f --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/data_collected.md @@ -0,0 +1,274 @@ +--- +title: RUM Android Data Collected +aliases: +- /real_user_monitoring/android/data_collected/ +- /real_user_monitoring/mobile_and_tv_monitoring/android/data_collected/ +further_reading: +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: Source code for dd-sdk-android +- link: /real_user_monitoring + tag: Documentation + text: Explore Datadog RUM +--- + +## Overview + +The RUM Android SDK generates events that have associated metrics and attributes. Metrics are quantifiable values that can be used for measurements related to the event. Attributes are non-quantifiable values used to slice metrics data (group by) in analytics. + +Every RUM event has all of the [default attributes](#default-attributes), for example, the device type (`device.type`) and user information such as their name (`usr.name`) and their country (`geo.country`). + +There are additional [metrics and attributes that are specific to a given event type](#event-specific-metrics-and-attributes). For example, the metric `view.time_spent` is associated with "view" events and the attribute `resource.method` is associated with "resource" events. + +| Event Type | Retention | Description | +|----------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Session | 30 days | A session represents a real user journey on your mobile application. It begins when the user launches the application, and the session remains live as long as the user stays active. During the user journey, all RUM events generated as part of the session will share the same `session.id` attribute. **Note:** The session resets after 15 minutes of inactivity. If the application is killed by the OS, you can reset the session while the application is in the background. | +| View | 30 days | A view represents a unique screen (or screen segment) on your mobile application. A view starts and stops when the `onActivityResumed` and `onActivityPaused` callbacks are called through the `ActivityLifecycleCallbacks` interface. Each occurrence is classified as a distinct view. While a user stays on a view, RUM event attributes (Errors, Resources, and Actions) get attached to the view with a unique `view.id`. | +| Resource | 15 days | A resource represents network requests to first-party hosts, APIs, and third-party providers in your mobile application. All requests generated during a user session are attached to the view with a unique `resource.id`. | +| Error | 30 days | An error represents an exception or crash emitted by the mobile application attached to the view it is generated in. | +| Action | 30 days | An action represents user activity in your mobile application (such as an application launch, tap, swipe, or back). Each action is attached with a unique `action.id` attached to the view it gets generated in. | +| Long Task | 15 days | A long task event is generated for any task in the application that blocks the main thread for more than the specified duration threshold. | + +The following diagram illustrates the RUM event hierarchy: + +{{< img src="real_user_monitoring/data_collected/event-hierarchy.png" alt="RUM Event hierarchy" style="width:50%;" >}} + +## Application launch + +During initialization, the RUM Android SDK creates a view called "ApplicationLaunch". This view's start time matches the start of the Android process, and can be used to track your application launch time. + +The `ApplicationLaunch` view includes any logs, actions, and resources created before your first call to `startView`. Use the duration of this view to determine time to first view. This view has an action, `application_start`, with a duration that depends on Android version: + +- In *Android 7.0* and above, this view/action captures the period before any application code is executed (right before `Application.onCreate`) and when the first RUM event is recorded. +- In versions before *Android 7.0*, the view/action captures the period between the `RumFeature` class loads and when the first RUM event is recorded. + +## Default attributes + +RUM collects common attributes for all events and attributes specific to each event listed below [automatically][1]. You can also choose to enrich your user session data by tracking [additional events][2] or by [adding custom attributes][3] to default events specific to your application monitoring and business analytics needs. + +### Common core attributes + +| Attribute name | Type | Description | +|------------------|--------|-----------------------------| +| `date` | integer | Start of the event in milliseconds from epoch. | +| `type` | string | The type of the event (for example, `view` or `resource`). | +| `service` | string | The [unified service name][4] for this application used to correlate user sessions. | +| `application.id` | string | The Datadog application ID. | +| `application.name` | string | The Datadog application name. | + +### Device + +The following device-related attributes are attached automatically to all events collected by Datadog: + +| Attribute name | Type | Description | +|------------------------------------------|--------|-------------------------------------------------| +| `device.type` | string | The device type as reported by the device (System User-Agent). | +| `device.brand` | string | The device brand as reported by the device (System User-Agent). | +| `device.model` | string | The device model as reported by the device (System User-Agent). | +| `device.name` | string | The device name as reported by the device (System User-Agent). | +| `device.architecture` | string | The CPU architecture of the device that is reporting the error. | + +### Connectivity + +The following network-related attributes are attached automatically to Resource and Error events collected by Datadog: + +| Attribute name | Type | Description | +|------------------------------------------|--------|-------------------------------------------------| +| `connectivity.status` | string | Status of device network reachability (`connected`, `not connected`, or `maybe`). | +| `connectivity.interfaces` | string | The list of available network interfaces (for example, `bluetooth`, `cellular`, `ethernet`, or `wifi`). | +| `connectivity.cellular.technology` | string | The type of a radio technology used for cellular connection. | +| `connectivity.cellular.carrier_name` | string | The name of the SIM carrier. | + +### Operating system + +The following OS-related attributes are attached automatically to all events collected by Datadog: + +| Attribute name | Type | Description | +|------------------------------------------|--------|-------------------------------------------------| +| `os.name` | string | The OS name as reported by the device (System User-Agent). | +| `os.version` | string | The OS version as reported by the device (System User-Agent). | +| `os.version_major` | string | The OS version major as reported by the device (System User-Agent). | + +### Geo-location + +The below attributes are related to the geo-location of IP addresses. + +**Note:** If you want to stop collecting geo-location attributes, change the setting in your [application details][9]. + +| Attribute name | Type | Description | +|:--------------------------------------------|:-------|:-------------------------------------------------------------------------------------------------------------------------------------| +| `geo.country` | string | Name of the country. | +| `geo.country_iso_code` | string | ISO Code of the country (for example, `US` for the United States or `FR` for France). | +| `geo.country_subdivision` | string | Name of the first subdivision level of the country (for example, `California` in the United States or the `Sarthe` department in France). | +| `geo.continent_code` | string | ISO code of the continent (`EU`, `AS`, `NA`, `AF`, `AN`, `SA`, or `OC`). | +| `geo.continent` | string | Name of the continent (`Europe`, `Australia`, `North America`, `Africa`, `Antarctica`, `South America`, or `Oceania`). | +| `geo.city` | string | The name of the city (for example, `San Francisco`, `Paris`, or `New York`). | +### Global user attributes + +You can enable [tracking user info][5] globally to collect and apply user attributes to all RUM events. + +| Attribute name | Type | Description | +|------------------|--------|-----------------------------| +| `user.id` | string | Identifier of the user. | +| `usr.name` | string | Name of the user. | +| `usr.email` | string | Email of the user. | + + +## Event-specific metrics and attributes + +Metrics are quantifiable values that can be used for measurements related to the event. Attributes are non-quantifiable values used to slice metrics data (group by) in analytics. + +### Session metrics + +| Metric | Type | Description | +|------------|--------|----------------------------| +| `session.time_spent` | number (ns) | Time spent on a session. | +| `session.view.count` | number | Count of all views collected for this session. | +| `session.error.count` | number | Count of all errors collected for this session. | +| `session.resource.count` | number | Count of all resources collected for this session. | +| `session.action.count` | number | Count of all actions collected for this session. | +| `session.long_task.count` | number | Count of all long tasks collected for this session. + +### Session attributes + +| Attribute name | Type | Description | +|--------------------------------|--------|----------------------------------------------------------------------------------------------------------------| +| `session.id` | string | Unique ID of the session. | +| `session.type` | string | Type of the session (`user`). | +| `session.is_active` | boolean | Indicates if the session is currently active. The session ends if a user navigates away from the application or closes the browser window, and expires after 4 hours of activity or 15 minutes of inactivity. | +| `session.initial_view.url` | string | URL of the initial view of the session. | +| `session.initial_view.name` | string | Name of the initial view of the session. | +| `session.last_view.url` | string | URL of the last view of the session. | +| `session.last_view.name` | string | Name of the last view of the session. | +| `session.ip` | string | IP address of the session extracted from the TCP connection of the intake. If you want to stop collecting this attribute, change the setting in your [application details][8]. | +| `session.useragent` | string | System user agent info to interpret device info. | +| `session.has_replay` | boolean | Indicates if the session has a captured Session Replay recording attached to visually play the user experience. | + +### View metrics + +RUM action, error, resource, and long task events contain information about the active RUM view event at the time of collection. + + +| Metric | Type | Description | +|----------------------------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `view.time_spent` | number (ns) | Time spent on this view. | +| `view.long_task.count` | number | Count of all long tasks collected for this view. | +| `view.error.count` | number | Count of all errors collected for this view. | +| `view.resource.count` | number | Count of all resources collected for this view. | +| `view.action.count` | number | Count of all actions collected for this view. | +| `view.is_active` | boolean | Indicates whether the view corresponding to this event is considered active. | + +### View attributes + +| Attribute name | Type | Description | +|--------------------------------|--------|----------------------------------------------------------------------------------------------------------------| +| `view.id` | string | Unique ID of the initial view corresponding to the event. | +| `view.url` | string | Canonical name of the class corresponding to the event. | +| `view.name` | string | Customizable name of the view corresponding to the event. | + +### Resource metrics + + +| Metric | Type | Description | +|----------------------------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------| +| `duration` | number (ns) | Entire time spent loading the resource. | +| `resource.size` | number (bytes) | Resource size. | +| `resource.connect.duration` | number (ns) | Time spent establishing a connection to the server (connectEnd - connectStart). | +| `resource.ssl.duration` | number (ns) | Time spent for the TLS handshake. If the last request is not over HTTPS, this metric does not appear (connectEnd - secureConnectionStart). | +| `resource.dns.duration` | number (ns) | Time spent resolving the DNS name of the last request (domainLookupEnd - domainLookupStart). | +| `resource.redirect.duration` | number (ns) | Time spent on subsequent HTTP requests (redirectEnd - redirectStart). | +| `resource.first_byte.duration` | number (ns) | Time spent waiting for the first byte of response to be received (responseStart - RequestStart). | +| `resource.download.duration` | number (ns) | Time spent downloading the response (responseEnd - responseStart). | + +### Resource attributes + +| Attribute | Type | Description | +|--------------------------------|--------|-----------------------------------------------------------------------------------------| +| `resource.id` | string | Unique identifier of the resource. | +| `resource.type` | string | The type of resource being collected (for example, `xhr`, `image`, `font`, `css`, or `js`). | +| `resource.method` | string | The HTTP method (for example, `POST`, `GET`, `PATCH`, or `DELETE`). | +| `resource.status_code` | number | The response status code. | +| `resource.url` | string | The resource URL. | +| `resource.provider.name` | string | The resource provider name. Default is `unknown`. | +| `resource.provider.domain` | string | The resource provider domain. | +| `resource.provider.type` | string | The resource provider type (for example, `first-party`, `cdn`, `ad`, or `analytics`). | + +### Error attributes + +Front-end errors are collected with Real User Monitoring (RUM). The error message and stack trace are included when available. + +| Attribute | Type | Description | +|-----------------|--------|-------------------------------------------------------------------| +| `error.source` | string | Where the error originates from (for example, `webview`, `logger`, or `network`). | +| `error.type` | string | The error type (or error code in some cases). | +| `error.message` | string | A concise, human-readable one-line message explaining the event. | +| `error.stack` | string | The stack trace or complementary information about the error. | +| `error.issue_id` | string | The stack trace or complementary information about the error. | +| `error.category` | string | The high-level grouping for the type of error. Possible values are `ANR` or `Exception` | +| `error.file` | string | File where the error happened for the Error Tracking issue. | +| `error.is_crash` | boolean | Indicates whether the error caused the application to crash. | + +### Network errors + +Network errors include information about failing HTTP requests. The following facets are also collected: + +| Attribute | Type | Description | +|--------------------------------|--------|-----------------------------------------------------------------------------------------| +| `error.resource.status_code` | number | The response status code. | +| `error.resource.method` | string | The HTTP method (for example, `POST` or `GET`). | +| `error.resource.url` | string | The resource URL. | +| `error.resource.provider.name` | string | The resource provider name. Default is `unknown`. | +| `error.resource.provider.domain` | string | The resource provider domain. | +| `error.resource.provider.type` | string | The resource provider type (for example, `first-party`, `cdn`, `ad`, or `analytics`). | + +### Action timing metrics + +| Metric | Type | Description | +|--------------|--------|--------------------------| +| `action.loading_time` | number (ns) | The loading time of the action. | +| `action.long_task.count` | number | Count of all long tasks collected for this action. | +| `action.resource.count` | number | Count of all resources collected for this action. | +| `action.error.count` | number | Count of all errors collected for this action.| + +### Action attributes + +| Attribute | Type | Description | +|--------------|--------|--------------------------| +| `action.id` | string | UUID of the user action. | +| `action.type` | string | Type of the user action (for example, `tap` or `application_start`). | +| `action.name` | string | Name of the user action. | +| `action.target.name` | string | Element that the user interacted with. Only for automatically collected actions. | + +## Data storage + +Before data is uploaded to Datadog, it is stored in cleartext in your application's cache directory. This cache folder is protected by [Android's Application Sandbox][6], meaning that on most devices this data can't be read by other applications. However, if the mobile device is rooted, or someone tempers with the Linux kernel, the stored data might become readable. + +## Data upload + +The RUM Android SDK allows you to get the data you need to Datadog while considering user bandwidth impact. The Datadog SDK batches and uploads events as follows: + +- On _event collected_, the Datadog SDK appends uncompressed events to a batch file (using a tag-length-value, or TLV encoding format) +- On _upload_ (when the batch is considered "closed"), the Datadog SDK: + - Reads the batch and extract events + - Drops redundant View events in RUM (no optimizations in other tracks) + - Builds payloads specific to each track + - Compresses the payload and sends it + +## Direct Boot mode support + +If your application supports [Direct Boot mode][7], note that data captured before the device +is unlocked won't be captured, since the credential encrypted storage won't be available yet. + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#automatically-track-views +[2]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#enrich-user-sessions +[3]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#track-custom-global-attributes +[4]: /getting_started/tagging/unified_service_tagging/ +[5]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#track-user-sessions +[6]: https://source.android.com/security/app-sandbox +[7]: https://developer.android.com/training/articles/direct-boot +[8]: /data_security/real_user_monitoring/#ip-address +[9]: /data_security/real_user_monitoring/#geolocation diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking.md new file mode 100644 index 0000000000000..4a046742304c2 --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/error_tracking.md @@ -0,0 +1,287 @@ +--- +title: Android Crash Reporting and Error Tracking +description: Set up Error Tracking for your Android applications. +aliases: + - /real_user_monitoring/error_tracking/android + - /real_user_monitoring/error_tracking/mobile/android +further_reading: +- link: '/real_user_monitoring/error_tracking/' + tag: 'Documentation' + text: 'Get started with Error Tracking' +- link: '/real_user_monitoring/error_tracking/explorer' + tag: 'Documentation' + text: 'Visualize Error Tracking data in the Explorer' + +--- + +## Overview + +Error Tracking processes errors collected from the Android SDK. + +Enable Android Crash Reporting and Error Tracking to get comprehensive crash reports and error trends. With this feature, you can access: + +- Aggregated Android crash dashboards and attributes +- Deobfuscated Android crash reports +- Trend analysis with Android error tracking + +Your crash reports appear in [**Error Tracking**][1]. + +## Setup + +If you have not set up the Android SDK yet, follow the [in-app setup instructions][2] or see the [Android setup documentation][3]. + +1. Add the latest version of the [Android SDK][4] to your Gradle dependencies. +2. Configure your application's `env` and `variant` when [initializing the SDK][5]. +3. Run the Gradle tasks to upload your Proguard/R8 mapping file and NDK symbol files to Datadog to access deobfuscated stack traces. + +For any given error, you can access the file path, line number, and a code snippet for each frame of the related stack trace. + +### Add NDK crash reporting + +Your Android application may be running native code (C/C++) for performance or code reusability reasons. In order to enable NDK crash reporting, use the Datadog NDK plugin. + +1. Add the Gradle dependency by declaring the library as a dependency in your `build.gradle` file: + + ```groovy + dependencies { + implementation "com.datadoghq:dd-sdk-android-ndk:x.x.x" + //(...) + } + ``` +2. Enable NDK crash collection after initializing the SDK. + + ``` kotlin + NdkCrashReports.enable() + ``` + +### Add ANR reporting + +An "Application Not Responding" ([ANR][6]) is an Android-specific type of error that gets triggered when the application is unresponsive for too long. + +ANRs are only reported through the SDK (not through Logs). + +#### Report fatal ANRs +Fatal ANRs result in crashes. The application reports them when it's unresponsive, leading to the Android OS displaying a popup dialog to the user, who chooses to force quit the app through the popup. + +{{< img src="real_user_monitoring/error_tracking/rum-anr-fatal.png" alt="A fatal crash report in Error Tracking." >}} + +- In the **Error Tracking** page, fatal ANRs are grouped based on their similarity, which can result into several **individual issues** being created +- By default, Datadog catches fatal ANRs through the [ApplicationExitInfo API][7] (available since *[Android 30+][8]*), which can be read on the next app launch. +- In *[Android 29][9] and below*, reporting on fatal ANRs is not possible. + +#### Report non-fatal ANRs +Non-fatal ANRs may or may not have led to the application being terminated (crashing). + +{{< img src="real_user_monitoring/error_tracking/rum-anr-non-fatal.png" alt="A non-fatal crash report in Error Tracking." >}} + +- In the **Error Tracking** page, non-fatal ANRs are grouped under a **single** issue due to their level of noise +- 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. + +For any Android version, you can override the default setting for reporting non-fatal ANRs by setting `trackNonFatalAnrs` to `true` or `false` when initializing the SDK. + +## Get deobfuscated stack traces + +Mapping files are used to deobfuscate stack traces, which helps in debugging errors. Using a unique build ID that gets generated, Datadog automatically matches the correct stack traces with the corresponding mapping files. This ensures that regardless of when the mapping file was uploaded (either during pre-production or production builds), the correct information is available for efficient QA processes when reviewing crashes and errors reported in Datadog. + +Depending on the [Android Gradle plugin][1] version, the matching of stack traces and mapping files relies on different fields: + +- Version 1.13.0 uses the `build_id` field +- Older versions use a combination of the `service`, `version`, and `variant` fields + +### Upload your mapping file + +**Note**: Re-uploading a source map does not override the existing one if the version has not changed. + +{{< tabs >}} +{{% tab "US" %}} + +1. Add the [Android Gradle Plugin][1] to your Gradle project using the following code snippet. + + ```groovy + // In your app's build.gradle script + plugins { + id("com.datadoghq.dd-sdk-android-gradle-plugin") version "x.y.z" + } + ``` + +2. [Create a dedicated Datadog API key][2] and export it as an environment variable named `DD_API_KEY` or `DATADOG_API_KEY`. Alternatively, pass it as a task property, or if you have `datadog-ci.json` file in the root of your project, it can be taken from an `apiKey` property there. +3. Optionally, configure the plugin to upload files to the EU region by configuring the plugin in your `build.gradle` script: + + ```groovy + datadog { + site = "EU1" + } + ``` + +4. Run the upload task after your obfuscated APK builds: + + ```bash + ./gradlew uploadMappingRelease + ``` + +5. If running native code, run the NDK symbol upload task: + ```bash + ./gradlew uploadNdkSymbolFilesRelease + ``` + +**Note**: If your project uses additional flavors, the plugin provides an upload task for each variant with obfuscation enabled. In this case, initialize the Android SDK with a proper variant name (the necessary API is available in versions `1.8.0` and later). + + +[1]: https://github.com/DataDog/dd-sdk-android-gradle-plugin +[2]: https://app.datadoghq.com/organization-settings/api-keys +{{% /tab %}} +{{% tab "EU" %}} +1. Add the [Android Gradle Plugin][1] to your Gradle project using the following code snippet. + + ```groovy + // In your app's build.gradle script + plugins { + id("com.datadoghq.dd-sdk-android-gradle-plugin") version "x.y.z" + } + ``` + +2. [Create a dedicated Datadog API key][2] and export it as an environment variable named `DD_API_KEY` or `DATADOG_API_KEY`. Alternatively, pass it as a task property, or if you have `datadog-ci.json` file in the root of your project, it can be taken from an `apiKey` property there. +3. Configure the plugin to use the EU region by adding the following snippet in your app's `build.gradle` script file: + + ```groovy + datadog { + site = "EU1" + } + ``` + +4. Run the upload task after your obfuscated APK builds: + + ```bash + ./gradlew uploadMappingRelease + ``` + +5. If running native code, run the NDK symbol upload task: + ```bash + ./gradlew uploadNdkSymbolFilesRelease + ``` + +**Note**: If your project uses additional flavors, the plugin provides an upload task for each variant with obfuscation enabled. In this case, initialize the Android SDK with a proper variant name (the necessary API is available in versions `1.8.0` and later). + + +[1]: https://github.com/DataDog/dd-sdk-android-gradle-plugin +[2]: https://app.datadoghq.com/organization-settings/api-keys +{{% /tab %}} +{{< /tabs >}} + +#### List uploaded mapping files + +See the [RUM Debug Symbols][11] page to view all uploaded symbols. + +### Plugin Configuration Options + +There are several plugin properties that can be configured through the plugin extension. In case you are using multiple variants, you can set a property value for a specific flavor in the variant. + +For example, for a `fooBarRelease` variant, you can use the following configuration: + +```groovy +datadog { + foo { + versionName = "foo" + } + bar { + versionName = "bar" + } + fooBar { + versionName = "fooBar" + } +} +``` + +The task configuration for this variant is merged from all three flavor configurations provided in the following order: + +1. `bar` +2. `foo` +3. `fooBar` + +This resolves the final value for the `versionName` property as `fooBar`. + +| Property name | Description | +|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `versionName` | The version name of the application (by default, the version declared in the `android` block of your `build.gradle` script). | +| `serviceName` | The service name of the application (by default, the package name of your application as declared in the `android` block of your `build.gradle` script). | +| `site` | The Datadog site to upload your data to (US1, US3, US5, EU1, US1_FED, or AP1). | +| `remoteRepositoryUrl` | The URL of the remote repository where the source code was deployed. If this is not provided, this value is resolved from your Git configuration during the task execution time. | +| `checkProjectDependencies` | This property controls if the plugin should check if the Datadog Android SDK is included in the dependencies. If not, "none" is ignored, "warn" logs a warning, and "fail" fails the build with an error (default). | + +### Integrate with a CI/CD pipeline + +By default, the upload mapping task is independent from other tasks in the build graph. Run the task manually when you need to upload mapping. + +If you want to run this task in a CI/CD pipeline, and the task is required as part of the build graph, you can set the upload task to run after the mapping file is generated. + +For example: + +```groovy +tasks["minify${variant}WithR8"].finalizedBy { tasks["uploadMapping${variant}"] } +``` + +## Limitations + +### File sizing +{{< site-region region="us,us3,us5,eu,gov" >}} +Mapping files are limited to **500** MB. If your project has a mapping file larger than this, use one of the following options to reduce the file size: +{{< /site-region >}} +{{< site-region region="ap1" >}} +Mapping files are limited to **50** MB. If your project has a mapping file larger than this, use one of the following options to reduce the file size: +{{< /site-region >}} + +- Set the `mappingFileTrimIndents` option to `true`. This reduces your file size by 5%, on average. +- Set a map of `mappingFilePackagesAliases`: This replaces package names with shorter aliases. **Note**: Datadog's stacktrace uses the same alias instead of the original package name, so it's better to use this option for third party dependencies. + +```groovy +datadog { + mappingFileTrimIndents = true + mappingFilePackageAliases = mapOf( + "kotlinx.coroutines" to "kx.cor", + "com.google.android.material" to "material", + "com.google.gson" to "gson", + "com.squareup.picasso" to "picasso" + ) +} +``` + +### Collection +When looking at RUM Crash Reporting behaviors for Android, consider the following: + +- The crash can only be detected after the SDK is initialised. Given this, the recommendation is to initialize the SDK as soon as possible in your application's `onCreate` method. +- RUM crashes must be attached to a RUM view. If a crash occurs before a view is visible (typically an Activity or Fragment in an `onResume` state), or after the app is sent to the background by the end-user navigating away from it, the crash is muted and isn't reported for collection. To mitigate this, use the `trackBackgroundEvents()` [method][10] in your `RumConfiguration` builder. +- Only crashes that occur in sampled sessions are kept, meaning if a [session sampling rate is not 100%][11], some will not be reported. + +## Test your implementation + +To verify your Android Crash Reporting and Error Tracking configuration, you need to trigger a crash in your application and confirm that the error appears in Datadog. + +To test your implementation: + +1. Run your application on an Android emulator or a real device. +2. Execute some code containing an error or crash. For example: + + ```kotlin + fun onEvent() { + throw RuntimeException("Crash the app") + } + ``` + +3. After the crash happens, restart your application and wait for the Android SDK to upload the crash report in [**Error Tracking**][1]. + + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://app.datadoghq.com/rum/error-tracking +[2]: https://app.datadoghq.com/rum/application/create +[3]: /real_user_monitoring/mobile_and_tv_monitoring/android/setup/#setup +[4]: https://github.com/DataDog/dd-sdk-android/tree/develop/features/dd-sdk-android-rum +[5]: /real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android/?tabs=kotlin#initialization-parameters +[6]: https://developer.android.com/topic/performance/vitals/anr +[7]: https://developer.android.com/reference/android/app/ApplicationExitInfo +[8]: https://developer.android.com/tools/releases/platforms#11 +[9]: https://developer.android.com/tools/releases/platforms#10 +[10]: /real_user_monitoring/mobile_and_tv_monitoring/android/setup/#track-background-events +[11]: https://app.datadoghq.com/source-code/setup/rum \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries.md new file mode 100644 index 0000000000000..3cb2753734731 --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries.md @@ -0,0 +1,170 @@ +--- +title: RUM Android and Android TV Libraries +aliases: +- /real_user_monitoring/android/integrated_libraries/ +- /real_user_monitoring/mobile_and_tv_monitoring/android/integrated_libraries/ +further_reading: +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: Source code for dd-sdk-android +- link: /real_user_monitoring/mobile_and_tv_monitoring/integrated_libraries + tag: Documentation + text: Integrated Libraries +--- + +This page lists integrated libraries you can use for Android and Android TV applications. + +## Coil + +If you use Coil to load images in your application, see Datadog's [dedicated Coil library][1]. + +## Fresco + +If you use Fresco to load images in your application, see Datadog's [dedicated Fresco library][2]. + +## Glide + +If you use Glide to load images in your application, see Datadog's [dedicated Glide library][3]. + +## Jetpack Compose + +If you use Jetpack Compose in your application, see Datadog's [dedicated Jetpack Compose library][7]. + +## RxJava + +If you use RxJava in your application, see Datadog's [dedicated RxJava library][8]. + +## Picasso + +If you use Picasso, use it with the `OkHttpClient` that's been instrumented with the Datadog SDK for RUM and APM information about network requests made by Picasso. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val picasso = Picasso.Builder(context) + .downloader(OkHttp3Downloader(okHttpClient)) + // … + .build() + Picasso.setSingletonInstance(picasso) + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + final Picasso picasso = new Picasso.Builder(context) + .downloader(new OkHttp3Downloader(okHttpClient)) + // … + .build(); + Picasso.setSingletonInstance(picasso); + ``` +{{% /tab %}} +{{< /tabs >}} + +## Retrofit + +If you use Retrofit, use it with the `OkHttpClient` that's been instrumented with the Datadog SDK for RUM and APM information about network requests made with Retrofit. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val retrofitClient = Retrofit.Builder() + .client(okHttpClient) + // … + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + final Retrofit retrofitClient = new Retrofit.Builder() + .client(okHttpClient) + // … + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + +## SQLDelight + +If you use SQLDelight in your application, see Datadog's [dedicated SQLDelight library][4]. + +## SQLite + +Following SQLiteOpenHelper's [generated API documentation][5], you only have to provide the implementation of the +`DatabaseErrorHandler` -> `DatadogDatabaseErrorHandler` in the constructor. + +Doing this detects whenever a database is corrupted and sends a relevant +RUM error event for it. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + class : SqliteOpenHelper( + , + , + , + , + DatadogDatabaseErrorHandler()) { + // … + + } + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + public class extends SqliteOpenHelper { + public (){ + super(, + , + , + , + new DatadogDatabaseErrorHandler()); + } + } + ``` +{{% /tab %}} +{{< /tabs >}} + +## Apollo (GraphQL) + +If you use Apollo, use it with the `OkHttpClient` that's been instrumented with the Datadog SDK for RUM and APM information about all the queries performed through Apollo client. + +{{< tabs >}} +{{% tab "Kotlin" %}} + ```kotlin + val apolloClient = ApolloClient.builder() + .okHttpClient(okHttpClient) + .serverUrl() + .build() + ``` +{{% /tab %}} +{{% tab "Java" %}} + ```java + ApolloClient apolloClient = new ApolloClient.builder() + .okHttpClient(okHttpClient) + .serverUrl() + .build(); + ``` +{{% /tab %}} +{{< /tabs >}} + +## Android TV (Leanback) + +If you use the Leanback API to add actions into your Android TV application, see Datadog's [dedicated Android TV library][6]. + +## Kotlin Coroutines + +If you use Kotlin Coroutines, see Datadog's [dedicated library with extensions for RUM][9] and with [extensions for Trace][10]. + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://github.com/DataDog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-coil +[2]: https://github.com/DataDog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-fresco +[3]: https://github.com/DataDog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-glide +[4]: https://github.com/DataDog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-sqldelight +[5]: https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper +[6]: https://github.com/DataDog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-tv +[7]: https://github.com/Datadog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-compose +[8]: https://github.com/Datadog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-rx +[9]: https://github.com/Datadog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-rum-coroutines +[10]: https://github.com/Datadog/dd-sdk-android/tree/develop/integrations/dd-sdk-android-trace-coroutines \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals.md new file mode 100644 index 0000000000000..3ea8f0ae89b5f --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/mobile_vitals.md @@ -0,0 +1,5 @@ +--- +title: Android Mobile Vitals +--- + +{{< include-markdown "real_user_monitoring/mobile_and_tv_monitoring/mobile_vitals" >}} \ No newline at end of file diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/setup.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/setup.md new file mode 100644 index 0000000000000..3203275855ffd --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/setup.md @@ -0,0 +1,480 @@ +--- +title: RUM Android and Android TV Monitoring Setup +aliases: + - /real_user_monitoring/android/ + - /real_user_monitoring/setup/android +further_reading: +- link: /real_user_monitoring/mobile_and_tv_monitoring/advanced_configuration/android + tag: Documentation + text: RUM Android Advanced Configuration +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: Source code for dd-sdk-android +- link: /real_user_monitoring + tag: Documentation + text: Explore Datadog RUM +--- +## 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 5.0+ (API level 21) and Android TV. + +## Setup + +1. Declare Datadog RUM SDK as a dependency. +2. Specify application details in the UI. +3. Initialize Datadog SDK with application context. +4. Enable RUM feature to start sending data. +5. Initialize RUM Interceptor to track network events. + +### Declare the Datadog RUM SDK as a dependency + +Declare [dd-sdk-android-rum][1] and the [Gradle plugin][12] as a dependency in your **application module's** `build.gradle` file. + +```groovy +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-rum:x.x.x" + //(...) +} + +``` + +### Specify application details in the UI + +1. Navigate to [**Digital Experience** > **Add an Application**][2]. +2. Select `android` as the application type and enter an application name to generate a unique Datadog application ID and client token. +3. To instrument your web views, click the **Instrument your webviews** toggle. For more information, see [Web View Tracking][13]. +4. To disable automatic user data collection for either client IP or geolocation data, uncheck the boxes for those settings. For more information, see [RUM Android Data Collected][15]. + + {{< img src="real_user_monitoring/android/android-new-application.png" alt="Create a RUM application for Android in Datadog" style="width:90%;">}} + +To ensure the safety of your data, you must use a client token. If you used only [Datadog API keys][3] to configure the Datadog SDK, 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][4]. + +### Initialize Datadog SDK with application context + +In the initialization snippet, set an environment name, service name, and version number. In the examples below, `APP_VARIANT_NAME` specifies the variant of the application that generates data. For more information, see [Using Tags][14]. + +See [`trackingConsent`][6] to add GDPR compliance for your EU users, and [other configuration options][7] to initialize the library. + +{{< site-region region="us" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ).build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +{{< site-region region="eu" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ) + .useSite(DatadogSite.EU1) + .build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .useSite(DatadogSite.EU1) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +{{< site-region region="us3" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ) + .useSite(DatadogSite.US3) + .build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .useSite(DatadogSite.US3) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +{{< site-region region="us5" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ) + .useSite(DatadogSite.US5) + .build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .useSite(DatadogSite.US5) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +{{< site-region region="gov" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ) + .useSite(DatadogSite.US1_FED) + .build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .useSite(DatadogSite.US1_FED) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +{{< site-region region="ap1" >}} +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +class SampleApplication : Application() { + override fun onCreate() { + super.onCreate() + val configuration = Configuration.Builder( + clientToken = , + env = , + variant = + ) + .useSite(DatadogSite.AP1) + .build() + Datadog.initialize(this, configuration, trackingConsent) + } +} +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +public class SampleApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + Configuration configuration = + new Configuration.Builder(, , ) + .useSite(DatadogSite.AP1) + .build(); + Datadog.initialize(this, configuration, trackingConsent); + } +} +``` +{{% /tab %}} +{{< /tabs >}} +{{< /site-region >}} + +The initialization credentials require your application's variant name and uses the value of `BuildConfig.FLAVOR`. With the variant, RUM can match the errors reported from your application with the mapping files uploaded by the Gradle plugin. If you do not have variants, the credentials use an empty string. + +The Gradle plugin automatically uploads the appropriate ProGuard `mapping.txt` file at build time so you can view deobfuscated RUM error stack traces. For more information, see the [Track Android Errors][8]. + +### Sample RUM sessions + +To control the data your application sends to Datadog RUM, you can specify a sample rate for RUM sessions while [initializing the RUM feature][2] as a percentage between 0 and 100. + +```kotlin +val rumConfig = RumConfiguration.Builder(applicationId) + // Here 75% of the RUM sessions are sent to Datadog + .setSessionSampleRate(75.0f) + .build() +Rum.enable(rumConfig) +``` + +### Set tracking consent (GDPR compliance) + +To be compliant with the GDPR regulation, the SDK requires the tracking consent value at initialization. +Tracking consent can be one of the following values: + +- `TrackingConsent.PENDING`: (Default) The SDK starts collecting and batching the data but does not send it to the + collection endpoint. The SDK waits for the new tracking consent value to decide what to do with the batched data. +- `TrackingConsent.GRANTED`: The SDK starts collecting the data and sends it to the data collection endpoint. +- `TrackingConsent.NOT_GRANTED`: The SDK does not collect any data. You are not able to manually send any logs, traces, or + RUM events. + +To update the tracking consent after the SDK is initialized, call `Datadog.setTrackingConsent()`. The SDK changes its behavior according to the new consent. For example, if the current tracking consent is `TrackingConsent.PENDING` and you update it to: + +- `TrackingConsent.GRANTED`: The SDK sends all current batched data and future data directly to the data collection endpoint. +- `TrackingConsent.NOT_GRANTED`: The SDK wipes all batched data and does not collect any future data. + + +### Enable RUM feature to start sending data + +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin + val rumConfig = RumConfiguration.Builder(applicationId) + .trackInteractions() + .trackLongTasks(durationThreshold) + .useViewTrackingStrategy(strategy) + .build() + Rum.enable(rumConfig) +``` +{{% /tab %}} + +{{% tab "Java" %}} +```java + RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId) + .trackInteractions() + .trackLongTasks(durationThreshold) + .useViewTrackingStrategy(strategy) + .build(); + Rum.enable(rumConfig); +``` +{{% /tab %}} +{{< /tabs >}} + +See [`ViewTrackingStrategy`][5] to enable automatic tracking of all your views (activities, fragments, and more). + +### Initialize RUM Interceptor to track network events + +1. If you want to have distributed tracing, add and enable Trace feature, see [Datadog Android Trace Collection documentation][16] to learn how. +2. Add the Gradle dependency to the `dd-sdk-android-okhttp` library in the module-level `build.gradle` file: + + ```groovy + dependencies { + implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x" + } + ``` + +3. To track your OkHttp requests as resources, add the provided [Interceptor][9]: + +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +val tracedHostsWithHeaderType = mapOf( + "example.com" to setOf( + TracingHeaderType.DATADOG, + TracingHeaderType.TRACECONTEXT), + "example.eu" to setOf( + TracingHeaderType.DATADOG, + TracingHeaderType.TRACECONTEXT)) +val okHttpClient = OkHttpClient.Builder() + .addInterceptor(DatadogInterceptor.Builder(tracedHostsWithHeaderType).build()) + .build() +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +final Map> tracedHostsWithHeaderType = new HashMap<>(); +final Set datadogAndW3HeadersTypes = new HashSet<>(Arrays.asList(TracingHeaderType.DATADOG, TracingHeaderType.TRACECONTEXT)); +tracedHostsWithHeaderType.put("example.com", datadogAndW3HeadersTypes); +tracedHostsWithHeaderType.put("example.eu", datadogAndW3HeadersTypes); +OkHttpClient okHttpClient = new OkHttpClient.Builder() + .addInterceptor(new DatadogInterceptor.Builder(tracedHostsWithHeaderType).build()) + .build(); +``` +{{% /tab %}} +{{< /tabs >}} + + + +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][10]. + +**Note**: If you also use multiple Interceptors, add `DatadogInterceptor` first. + +You can also add an `EventListener` for the `OkHttpClient` to [automatically track resource timing][11] for third-party providers and network requests. + +## 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: + +{{< tabs >}} +{{% tab "Kotlin" %}} +```kotlin +.trackBackgroundEvents(true) +``` +{{% /tab %}} +{{% tab "Java" %}} +```java +.trackBackgroundEvents(true) +``` +{{% /tab %}} +{{< /tabs >}} +

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

+
+ +## Sending data when device is offline + +RUM ensures availability of data when your user device is offline. In case of low-network areas, or when the device battery is too low, all the RUM events are first stored on the local device in batches. + +Each batch follows the intake specification. They are sent as soon as the network is available, and the battery is high enough to ensure the Datadog SDK does not impact the end user's experience. If the network is not available while your application is in the foreground, or if an upload of data fails, the batch is kept until it can be sent successfully. + +This means that even if users open your application while offline, no data is lost. To ensure the SDK does not use too much disk space, the data on the disk is automatically discarded if it gets too old. + + +## Kotlin Extensions + +### `Closeable` extension + +You can monitor `Closeable` instance usage by using `useMonitored` method, it will report any error happened to Datadog and close the resource afterwards. + +```kotlin +val closeable: Closeable = ... +closeable.useMonitored { + // Your code here +} + +``` + +### Track local assets as RUM resources + +You can track access to the assets by using `getAssetAsRumResource` extension method: + +```kotlin +val inputStream = context.getAssetAsRumResource(fileName) +``` + +Usage of the local resources can be tracked by using `getRawResAsRumResource` extension method: + +```kotlin +val inputStream = context.getRawResAsRumResource(id) +``` + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://github.com/DataDog/dd-sdk-android/tree/develop/features/dd-sdk-android-rum +[2]: https://app.datadoghq.com/rum/application/create +[3]: /account_management/api-app-keys/#api-keys +[4]: /account_management/api-app-keys/#client-tokens +[5]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#automatically-track-views +[6]: #set-tracking-consent-gdpr-compliance +[7]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#initialization-parameters +[8]: /real_user_monitoring/error_tracking/android/#upload-your-mapping-file +[9]: https://square.github.io/okhttp/interceptors/ +[10]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#custom-views +[11]: /real_user_monitoring/mobile_and_tv_monitoring/android/advanced_configuration/#automatically-track-network-requests +[12]: https://github.com/DataDog/dd-sdk-android-gradle-plugin +[13]: /real_user_monitoring/android/web_view_tracking/ +[14]: /getting_started/tagging/using_tags/#rum--session-replay +[15]: /real_user_monitoring/android/data_collected/ +[16]: /tracing/trace_collection/dd_libraries/android/?tab=kotlin diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting.md new file mode 100644 index 0000000000000..f59370321632a --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/troubleshooting.md @@ -0,0 +1,50 @@ +--- +title: Troubleshooting RUM Android SDK issues +description: Learn how to troubleshoot issues with Android Monitoring. +aliases: +- /real_user_monitoring/mobile_and_tv_monitoring/troubleshooting/android +further_reading: +- link: https://github.com/DataDog/dd-sdk-android + tag: "Source Code" + text: dd-sdk-android Source code +- link: /real_user_monitoring + tag: Documentation + text: Explore Real User Monitoring +--- + +## Overview + +If you experience unexpected behavior with Datadog RUM, use this guide to resolve issues quickly. If you continue to have trouble, contact [Datadog Support][1] for further assistance. + +## Check if Datadog RUM is initialized +Use the utility method `isInitialized` to check if the SDK is properly initialized: + +```kotlin +if (Datadog.isInitialized()) { + // your code here +} +``` + +## Debugging +When writing your application, you can enable development logs by calling the `setVerbosity` method. All internal messages in the library with a priority equal to or higher than the provided level are then logged to Android's Logcat: + +```kotlin +Datadog.setVerbosity(Log.INFO) +``` + +## Migrating to 2.0.0 + +If you've been using the SDK v1, there are some breaking changes introduced in version `2.0.0`. See the [migration guide][2] for more information. + +## "Deobfuscation failed" warning + +A warning appears when deobfuscation fails for a stack trace. If the stack trace is not obfuscated to begin with, you can ignore this warning. Otherwise, use the [RUM Debug Symbols page][3] to view all your uploaded mapping files. See [Investigate Obfuscated Stack Traces with RUM Debug Symbols][4]. + +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: /help +[2]: https://github.com/DataDog/dd-sdk-android/blob/develop/MIGRATION.MD +[3]: https://app.datadoghq.com/source-code/setup/rum +[4]: /real_user_monitoring/guide/debug-symbols diff --git a/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/web_view_tracking.md b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/web_view_tracking.md new file mode 100644 index 0000000000000..eb75ef3e4de1a --- /dev/null +++ b/content/en/real_user_monitoring/mobile_and_tv_monitoring/android/web_view_tracking.md @@ -0,0 +1,5 @@ +--- +title: RUM Android Web View Tracking +--- + +{{< include-markdown "real_user_monitoring/mobile_and_tv_monitoring/web_view_tracking" >}} \ No newline at end of file diff --git a/layouts/partials/nav/left-nav.html b/layouts/partials/nav/left-nav.html index 38f73fdfce8bc..ebe6b93f63f2a 100644 --- a/layouts/partials/nav/left-nav.html +++ b/layouts/partials/nav/left-nav.html @@ -68,7 +68,8 @@ {{ if .HasChildren }}