From 23fb52e2126183f906c9d3325b2f062861af1319 Mon Sep 17 00:00:00 2001 From: Xavier Gouchet Date: Thu, 26 May 2022 09:24:42 +0200 Subject: [PATCH 1/5] Document the RumResourceAttributesProvider --- docs/configure_rum_android_sdk.md | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/configure_rum_android_sdk.md b/docs/configure_rum_android_sdk.md index 2671ca71d1..7f2e6151af 100644 --- a/docs/configure_rum_android_sdk.md +++ b/docs/configure_rum_android_sdk.md @@ -80,6 +80,53 @@ In addition to [tracking actions automatically][5], you can also track specific {{% /tab %}} {{< /tabs >}} +### Enrich resources + +When [tracking resources automatically][6], you can provide a custom `RumResourceAttributesProvider` instance, allowing you to add custom attributes to each tracked network request. For example, if you want to track a network request's headers, you can create an implementation as follow, 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)); + } + + return result; + } +} +``` +{{% /tab %}} +{{< /tabs >}} + ### Custom Resources In addition to [tracking resources automatically][6], you can also track specific custom resources (network requests, third party provider APIs, etc.) with methods (`GET`, `POST`, etc.) 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. From 1e627f144cc8f486a58b6b40da5a8e3e4baabf54 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 26 May 2022 15:12:18 -0700 Subject: [PATCH 2/5] Doc Review --- docs/configure_rum_android_sdk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configure_rum_android_sdk.md b/docs/configure_rum_android_sdk.md index 7f2e6151af..7194b26eac 100644 --- a/docs/configure_rum_android_sdk.md +++ b/docs/configure_rum_android_sdk.md @@ -9,7 +9,7 @@ Android RUM automatically tracks attributes such as user activity, screens, erro ### Custom Views -In addition to [tracking views automatically][4], you can also track specific distinct views (activities, fragments, etc.) 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`: +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 >}} @@ -61,7 +61,7 @@ Once the timing is sent, the timing will be accessible as `@view.custom_timings. ### Custom Actions -In addition to [tracking actions automatically][5], you can also track specific custom user actions (taps, clicks, scrolls, etc.) with `RumMonitor#addUserAction`. For continuous action tracking (for example, tracking a user scrolling a list), use `RumMonitor#startUserAction` and `RumMonitor#stopUserAction`. +In addition to [tracking actions automatically][5], you can also track specific custom user actions (such as taps, clicks, and scrolls) with `RumMonitor#addUserAction`. For continuous action tracking (for example, tracking a user scrolling a list), use `RumMonitor#startUserAction` and `RumMonitor#stopUserAction`. {{< tabs >}} {{% tab "Kotlin" %}} From 543b698bad03894725e99925b1378e9557875208 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 26 May 2022 15:21:21 -0700 Subject: [PATCH 3/5] Doc Review --- docs/configure_rum_android_sdk.md | 61 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/docs/configure_rum_android_sdk.md b/docs/configure_rum_android_sdk.md index 7194b26eac..741a8cd4b2 100644 --- a/docs/configure_rum_android_sdk.md +++ b/docs/configure_rum_android_sdk.md @@ -57,7 +57,7 @@ In addition to RUM’s default attributes, you can measure where your applicatio {{% /tab %}} {{< /tabs >}} -Once the timing is sent, the timing will be accessible as `@view.custom_timings.` (For example, `@view.custom_timings.hero_image`). You must [create a measure](https://docs.datadoghq.com/real_user_monitoring/explorer/?tab=measures#setup-facets-and-measures) before graphing it in RUM analytics or in dashboards. +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](https://docs.datadoghq.com/real_user_monitoring/explorer/?tab=measures#setup-facets-and-measures) before graphing it in RUM analytics or in dashboards. ### Custom Actions @@ -129,7 +129,7 @@ public class CustomRumResourceAttributesProvider implements RumResourceAttribute ### Custom Resources -In addition to [tracking resources automatically][6], you can also track specific custom resources (network requests, third party provider APIs, etc.) with methods (`GET`, `POST`, etc.) 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. +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" %}} @@ -172,9 +172,10 @@ To track specific errors, notify the monitor when an error occurs with the messa ## Track custom global attributes -In addition to the [default RUM attributes][3] captured by the mobile 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 slice and dice 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). +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 slice and dice 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 @@ -222,7 +223,7 @@ You can use the following methods in `Configuration.Builder` when creating the D : Defines the strategy used to track views. Depending on your application's architecture, you can choose one of several implementations of [`ViewTrackingStrategy`][4] or implement your own. `addPlugin(DatadogPlugin, Feature)` -: Adds a plugin implementation for a specific feature (`CRASH`, `LOG`, `TRACE`, `RUM`). The plugin is registered once the feature is initialized and unregistered when the feature is stopped. +: Adds a plugin implementation for a specific feature (`CRASH`, `LOG`, `TRACE`, or `RUM`). The plugin is registered once the feature is initialized and unregistered when the feature is stopped. `trackLongTasks(durationThreshold)` : Enables tracking tasks taking longer than `durationThreshold` on the main thread as long tasks in Datadog. @@ -254,7 +255,7 @@ You can use the following methods in `Configuration.Builder` when creating the D ### Automatically track views -To automatically track your views (activities, fragments, etc.), provide a tracking strategy at initialization. Depending on your application's architecture, you can choose one of the following strategies: +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. @@ -289,14 +290,14 @@ For instance, to set each fragment as a distinct view, use the following configu {{< /tabs >}} -**Tip**: 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. +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. **Note**: By default, the library does not track any views. 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 (third-party providers, network requests) such as time to first byte or DNS resolution, customize the `okHttpClient` to add the [EventListener][8] factory: +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: {{< tabs >}} {{% tab "Kotlin" %}} @@ -358,7 +359,7 @@ For example, to replace the default `100 ms` duration, set a custom threshold in ## 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 SDK: +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 >}} @@ -389,34 +390,34 @@ To modify some attributes in your RUM events, or to drop some of the events enti {{% /tab %}} {{< /tabs >}} - As you will notice when implementing the `EventMapper` interface, only some of the attributes are modifiable for each event type as follows: + 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 | + | 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 | + | | `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 | + | | `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 | + | | `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 | + | | `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. @@ -432,7 +433,7 @@ val monitor = RumMonitor.Builder() GlobalRum.registerIfAbsent(monitor) ``` - ## Further Reading +## Further Reading {{< partial name="whats-next/whats-next.html" >}} From 9ab6eeaf3249065424b545ce8bcd99909eec8325 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 26 May 2022 15:22:08 -0700 Subject: [PATCH 4/5] Copy Nit --- docs/configure_rum_android_sdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure_rum_android_sdk.md b/docs/configure_rum_android_sdk.md index 741a8cd4b2..66bb8a7cf6 100644 --- a/docs/configure_rum_android_sdk.md +++ b/docs/configure_rum_android_sdk.md @@ -82,7 +82,7 @@ In addition to [tracking actions automatically][5], you can also track specific ### Enrich resources -When [tracking resources automatically][6], you can provide a custom `RumResourceAttributesProvider` instance, allowing you to add custom attributes to each tracked network request. For example, if you want to track a network request's headers, you can create an implementation as follow, and pass it in the constructor of the `DatadogInterceptor`. +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" %}} From 6b88176f47dbf69ea47205bc28d23fa4d9bdaa41 Mon Sep 17 00:00:00 2001 From: Xavier Gouchet Date: Fri, 27 May 2022 14:07:47 +0200 Subject: [PATCH 5/5] Java sample nitpick --- docs/configure_rum_android_sdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure_rum_android_sdk.md b/docs/configure_rum_android_sdk.md index 66bb8a7cf6..d7e6373d7c 100644 --- a/docs/configure_rum_android_sdk.md +++ b/docs/configure_rum_android_sdk.md @@ -117,7 +117,7 @@ public class CustomRumResourceAttributesProvider implements RumResourceAttribute for (String key : headers.names()) { String attrName = "headers." + key.toLowerCase(Locale.US); - result.put(attrName, headers.values(key)); + result.put(attrName, headers.values(key).get(0)); } return result;