> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashcat.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK 高级配置

> 深入配置 Android RUM SDK 的高级功能，包括自定义事件、用户追踪、采样控制和数据安全

<Note>
  **关于依赖和包名的说明**

  Flashduty Android SDK 完全兼容 Datadog 开源协议，代码中的 import 语句使用 `com.datadog.android.*` 包名。您可以无缝复用 Datadog 生态的文档、示例和最佳实践，同时享受 Flashduty 平台的服务。
</Note>

Android RUM SDK 提供丰富的高级配置选项，帮助您根据业务需求定制数据收集和上下文信息。

<Info>
  **支持的配置场景：**

  * 丰富用户会话 - 添加自定义视图、操作、资源和错误信息
  * 保护敏感数据 - 屏蔽个人身份信息等敏感数据
  * 关联用户会话 - 将用户会话与内部用户标识关联
  * 控制数据量 - 通过采样和事件过滤优化数据收集
  * 增强上下文 - 为数据添加自定义属性
</Info>

## 丰富用户会话

### 自定义视图

当使用 `ActivityViewTrackingStrategy` 或 `FragmentViewTrackingStrategy` 时，RUM SDK 会自动追踪视图。您也可以在视图变为可见或可交互时手动发送自定义 RUM 视图。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

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

    fun onPause() {
        GlobalRumMonitor.get().stopView(viewKey, attributes)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

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

    public void onPause() {
        GlobalRumMonitor.get().stopView(viewKey, attributes);
    }
    ```
  </Tab>
</Tabs>

<Note>
  **参数说明：**

  * `viewKey` (String) - 视图的唯一标识符，同一个 `viewKey` 用于调用 `startView()` 和 `stopView()`
  * `viewName` (String) - 视图的名称
  * `attributes` (`Map<String, Any?>`) - 附加到视图的属性（可选）
</Note>

### 自定义操作

除了自动追踪的用户交互，您还可以追踪特定的自定义用户操作（如点击、滑动、点赞）。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor
    import com.datadog.android.rum.RumActionType

    fun onUserInteraction() {
        GlobalRumMonitor.get().addAction(
            RumActionType.TAP,
            name,
            attributes
        )
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;
    import com.datadog.android.rum.RumActionType;

    public void onUserInteraction() {
        GlobalRumMonitor.get().addAction(
            RumActionType.TAP,
            name,
            attributes
        );
    }
    ```
  </Tab>
</Tabs>

<Accordion title="RumActionType 枚举值">
  | 类型                     | 描述    | 使用场景    |
  | ---------------------- | ----- | ------- |
  | `RumActionType.TAP`    | 点击操作  | 按钮、图标点击 |
  | `RumActionType.SCROLL` | 滚动操作  | 列表、页面滚动 |
  | `RumActionType.SWIPE`  | 滑动操作  | 滑动切换、手势 |
  | `RumActionType.CLICK`  | 单击操作  | 通用点击    |
  | `RumActionType.CUSTOM` | 自定义操作 | 业务特定操作  |
</Accordion>

### 自定义资源

除了自动追踪的资源，您还可以手动追踪特定的自定义资源（如网络请求、第三方库加载）。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor
    import com.datadog.android.rum.RumResourceKind

    fun loadResource() {
        GlobalRumMonitor.get().startResource(resourceKey, method, url, attributes)
    }

    fun resourceLoadSuccess() {
        GlobalRumMonitor.get().stopResource(
            resourceKey, statusCode, size, 
            RumResourceKind.NATIVE, attributes
        )
    }

    fun resourceLoadError() {
        GlobalRumMonitor.get().stopResourceWithError(
            resourceKey, statusCode, message, source, throwable
        )
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;
    import com.datadog.android.rum.RumResourceKind;

    public void loadResource() {
        GlobalRumMonitor.get().startResource(resourceKey, method, url, attributes);
    }

    public void resourceLoadSuccess() {
        GlobalRumMonitor.get().stopResource(
            resourceKey, statusCode, size, 
            RumResourceKind.NATIVE, attributes
        );
    }

    public void resourceLoadError() {
        GlobalRumMonitor.get().stopResourceWithError(
            resourceKey, statusCode, message, source, throwable
        );
    }
    ```
  </Tab>
</Tabs>

<Accordion title="RumResourceKind 资源类型">
  | 类型         | 描述            | 适用场景    |
  | ---------- | ------------- | ------- |
  | `BEACON`   | 信标请求          | 统计上报    |
  | `FETCH`    | Fetch 请求      | 现代异步请求  |
  | `XHR`      | XHR 请求        | 传统 Ajax |
  | `DOCUMENT` | 文档资源          | HTML 文档 |
  | `IMAGE`    | 图片资源          | 图片加载    |
  | `JS`       | JavaScript 资源 | JS 文件   |
  | `FONT`     | 字体资源          | 字体文件    |
  | `CSS`      | CSS 资源        | 样式文件    |
  | `MEDIA`    | 媒体资源          | 音视频文件   |
  | `NATIVE`   | 原生资源          | 原生模块加载  |
  | `OTHER`    | 其他资源          | 未分类资源   |
</Accordion>

### 自定义错误

要记录特定错误，当异常发生时通知 RUM SDK：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().addError(
        message,
        source,
        throwable,
        attributes
    )
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    GlobalRumMonitor.get().addError(
        message,
        source,
        throwable,
        attributes
    );
    ```
  </Tab>
</Tabs>

<Note>
  更多错误上报详情，请参阅 [Android 异常上报](/zh/rum/error-tracking/erro-reporting/android)。
</Note>

### 自定义计时

除了 RUM SDK 默认的性能指标，您还可以使用 `addTiming` API 测量关键操作的耗时。计时是相对于当前 RUM 视图开始时间的偏移量。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    fun onHeroImageLoaded() {
        GlobalRumMonitor.get().addTiming("hero_image")
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    public void onHeroImageLoaded() {
        GlobalRumMonitor.get().addTiming("hero_image");
    }
    ```
  </Tab>
</Tabs>

<Tip>
  设置计时后，可通过 `@view.custom_timings.<timing_name>` 访问，例如 `@view.custom_timings.hero_image`。
</Tip>

### 添加用户属性

RUM SDK 会自动追踪用户属性。您还可以添加额外的自定义用户属性，例如用户计划、用户组等。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().setUserInfo(
        id = "1234",
        name = "John Doe",
        email = "john@doe.com",
        extraInfo = mapOf(
            "plan" to "premium",
            "group" to "vip"
        )
    )
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;
    import java.util.HashMap;
    import java.util.Map;

    Map<String, Object> extraInfo = new HashMap<>();
    extraInfo.put("plan", "premium");
    extraInfo.put("group", "vip");

    GlobalRumMonitor.get().setUserInfo(
        "1234",
        "John Doe",
        "john@doe.com",
        extraInfo
    );
    ```
  </Tab>
</Tabs>

<Tip>
  自定义用户属性可用于在分析看板中分组和过滤数据，帮助您了解不同用户群体的使用情况。
</Tip>

## 事件和数据管理

### 清除所有数据

使用 `clearAllData` 清除当前存储在 SDK 中的所有未发送数据：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.Datadog

    Datadog.clearAllData()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.Datadog;

    Datadog.clearAllData();
    ```
  </Tab>
</Tabs>

### 停止数据收集

使用 `stopInstance` 停止收集数据并清除所有本地数据：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.Datadog

    Datadog.stopInstance()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.Datadog;

    Datadog.stopInstance();
    ```
  </Tab>
</Tabs>

<Warning>
  调用 `stopInstance()` 后，SDK 将完全停止工作，需要重新初始化才能恢复数据收集。
</Warning>

### 控制事件批量上传

RUM SDK 会自动批量上传事件。您可以通过配置参数控制批量上传的行为：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.core.configuration.Configuration
    import com.datadog.android.core.configuration.UploadFrequency

    val configuration = Configuration.Builder(
        clientToken = clientToken,
        env = environmentName,
        variant = appVariantName
    )
        .setBatchSize(batchSize)
        .setUploadFrequency(UploadFrequency.FREQUENT)
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.core.configuration.Configuration;
    import com.datadog.android.core.configuration.UploadFrequency;

    Configuration configuration = new Configuration.Builder(
        clientToken, environmentName, appVariantName
    )
        .setBatchSize(batchSize)
        .setUploadFrequency(UploadFrequency.FREQUENT)
        .build();
    ```
  </Tab>
</Tabs>

<Accordion title="UploadFrequency 上传频率">
  | 频率         | 描述   | 适用场景         |
  | ---------- | ---- | ------------ |
  | `FREQUENT` | 频繁上传 | 实时性要求高的场景    |
  | `AVERAGE`  | 平均上传 | 默认值，平衡性能和实时性 |
  | `RARE`     | 少量上传 | 节省流量和电量      |
</Accordion>

### 设置远程日志阈值

您可以为远程记录的消息定义最低日志级别。低于该级别的日志不会发送到 Flashduty：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.log.Logs
    import com.datadog.android.log.LogsConfiguration
    import android.util.Log

    val logsConfig = LogsConfiguration.Builder()
        .setRemoteSampleRate(100f)
        .setRemoteLogThreshold(Log.WARN)
        .build()
        
    Logs.enable(logsConfig)
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.log.Logs;
    import com.datadog.android.log.LogsConfiguration;
    import android.util.Log;

    LogsConfiguration logsConfig = new LogsConfiguration.Builder()
        .setRemoteSampleRate(100f)
        .setRemoteLogThreshold(Log.WARN)
        .build();
        
    Logs.enable(logsConfig);
    ```
  </Tab>
</Tabs>

<Note>
  设置 `Log.WARN` 阈值后，只有 WARN、ERROR 级别的日志会被上传，DEBUG 和 INFO 级别的日志将被过滤。
</Note>

## 追踪自定义全局属性

除了由 RUM SDK 自动捕获的默认属性外，您还可以向 RUM 事件添加额外的上下文信息，例如自定义属性。

<Check>
  **自定义属性的用途：**

  * 根据业务信息（如购物车状态、用户等级、广告活动）过滤和分组用户行为
  * 跟踪特定用户的浏览路径
  * 了解哪些用户受错误影响最大
  * 监控关键用户的性能表现
</Check>

### 追踪用户会话

要识别用户会话，在初始化 SDK 后使用 `setUserInfo` API：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().setUserInfo(
        id = "1234",
        name = "John Doe",
        email = "john@doe.com"
    )
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    GlobalRumMonitor.get().setUserInfo("1234", "John Doe", "john@doe.com", null);
    ```
  </Tab>
</Tabs>

<Note>
  **参数说明：**

  * `id` (String) - 唯一用户标识符
  * `name` (String) - 用户友好名称，默认在 RUM UI 中显示
  * `email` (String) - 用户电子邮件，若无名称则显示邮件
  * 以上属性均为可选，建议至少提供一个
</Note>

### 追踪属性

全局属性会被附加到所有 RUM 事件中，用于添加通用的上下文信息。

**添加全局属性：**

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().addAttribute("key", "value")
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    GlobalRumMonitor.get().addAttribute("key", "value");
    ```
  </Tab>
</Tabs>

**删除全局属性：**

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().removeAttribute("key")
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    GlobalRumMonitor.get().removeAttribute("key");
    ```
  </Tab>
</Tabs>

## 追踪 Widgets

<Note>
  Widgets 不会自动追踪。要监控 Widget 的交互，需要手动调用 API。
</Note>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor
    import com.datadog.android.rum.RumActionType

    fun onWidgetClicked() {
        GlobalRumMonitor.get().addAction(
            RumActionType.TAP,
            "widget_clicked",
            mapOf("widget_name" to "HomeWidget")
        )
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;
    import com.datadog.android.rum.RumActionType;
    import java.util.HashMap;
    import java.util.Map;

    public void onWidgetClicked() {
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("widget_name", "HomeWidget");
        GlobalRumMonitor.get().addAction(
            RumActionType.TAP,
            "widget_clicked",
            attributes
        );
    }
    ```
  </Tab>
</Tabs>

## 初始化参数

在初始化 Flashduty Android SDK 时，您可以使用 `Configuration.Builder` 配置多种选项。

### 自动追踪视图

要自动追踪视图（Activities、Fragments），在初始化时使用 `useViewTrackingStrategy`：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.RumConfiguration
    import com.datadog.android.rum.tracking.ActivityViewTrackingStrategy

    val rumConfig = RumConfiguration.Builder(applicationId)
        .useViewTrackingStrategy(ActivityViewTrackingStrategy(true))
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.RumConfiguration;
    import com.datadog.android.rum.tracking.ActivityViewTrackingStrategy;

    RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
        .useViewTrackingStrategy(new ActivityViewTrackingStrategy(true))
        .build();
    ```
  </Tab>
</Tabs>

<Accordion title="可用的追踪策略">
  | 策略                               | 参数                              | 描述                       | 适用场景                  |
  | -------------------------------- | ------------------------------- | ------------------------ | --------------------- |
  | `ActivityViewTrackingStrategy`   | `trackExtras`                   | 追踪每个 Activity 为一个单独的视图   | 传统 Activity 架构        |
  | `FragmentViewTrackingStrategy`   | `trackArguments`                | 追踪每个 Fragment 为一个单独的视图   | Fragment 为主的应用        |
  | `MixedViewTrackingStrategy`      | `trackExtras`, `trackArguments` | 同时追踪 Activity 和 Fragment | 混合架构应用                |
  | `NavigationViewTrackingStrategy` | `navigationViewId`              | 追踪 Navigation 组件的目的地     | 使用 Jetpack Navigation |
</Accordion>

### 自动追踪网络请求

要自动追踪 HTTP 网络请求，请参考 [SDK 接入指南](./sdk-integration#配置网络追踪可选) 中的 OkHttp 拦截器配置。

### 自动追踪 Apollo GraphQL 请求

如果您使用 Apollo GraphQL 客户端进行网络调用，可以启用自动追踪。

<Steps>
  <Step title="添加 Apollo 依赖">
    在应用的 `build.gradle` 文件中添加依赖：

    ```groovy build.gradle theme={null}
    dependencies {
        implementation "cloud.flashcat:dd-sdk-android-apollo:<latest-version>"
    }
    ```

    <Tip>
      请访问 [Maven Central 版本页面](https://central.sonatype.com/artifact/cloud.flashcat/dd-sdk-android-core/versions) 获取最新版本号。
    </Tip>
  </Step>

  <Step title="配置 Apollo Client">
    <Tabs>
      <Tab title="Kotlin">
        ```kotlin theme={null}
        import com.apollographql.apollo.ApolloClient
        import com.apollographql.apollo.network.okHttpClient
        import com.datadog.android.apollo.DatadogApolloInterceptor

        val apolloClient = ApolloClient.Builder()
            .serverUrl("GraphQL endpoint")
            .addInterceptor(DatadogApolloInterceptor())
            .okHttpClient(okHttpClient)
            .build()
        ```
      </Tab>

      <Tab title="Java">
        ```java theme={null}
        import com.apollographql.apollo.ApolloClient;
        import com.datadog.android.apollo.DatadogApolloInterceptor;

        ApolloClient apolloClient = new ApolloClient.Builder()
            .serverUrl("GraphQL endpoint")
            .addInterceptor(new DatadogApolloInterceptor())
            .okHttpClient(okHttpClient)
            .build();
        ```
      </Tab>
    </Tabs>

    <Check>
      Flashduty 追踪头将自动添加到您的 GraphQL 请求中，使其能够被追踪。
    </Check>
  </Step>
</Steps>

<Warning>
  **限制说明：**

  * 仅支持 Apollo 版本 **4**
  * 仅追踪 `query` 和 `mutation` 类型的操作，不追踪 `subscription` 操作
</Warning>

**启用 GraphQL Payload 发送（可选）：**

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    DatadogApolloInterceptor(sendGraphQLPayloads = true)
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    new DatadogApolloInterceptor(true)
    ```
  </Tab>
</Tabs>

### 自动追踪长任务

在主线程上执行的长时间运行的操作可能会影响应用的视觉性能和响应性。SDK 可以自动检测并追踪长任务。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.RumConfiguration

    // 使用默认阈值（100ms）
    val rumConfig = RumConfiguration.Builder(applicationId)
        .trackLongTasks(durationThreshold)
        .build()

    // 自定义阈值（250ms）
    val rumConfig = RumConfiguration.Builder(applicationId)
        .trackLongTasks(250L)
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.RumConfiguration;

    // 使用默认阈值（100ms）
    RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
        .trackLongTasks(durationThreshold)
        .build();

    // 自定义阈值（250ms）
    RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
        .trackLongTasks(250L)
        .build();
    ```
  </Tab>
</Tabs>

<Note>
  默认阈值为 **100ms**。您可以根据应用性能要求调整此阈值。
</Note>

## 修改或丢弃 RUM 事件

要在批量处理之前修改 RUM 事件的某些属性，或完全丢弃某些事件，请在初始化时提供 `EventMapper<T>` 的实现。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.RumConfiguration

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

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.RumConfiguration;

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

### 可修改的事件属性

当实现 `EventMapper<T>` 接口时，每种事件类型只有部分属性可以修改：

<AccordionGroup>
  <Accordion title="ViewEvent 可修改属性">
    | 属性键             | 描述             |
    | --------------- | -------------- |
    | `view.referrer` | 链接到页面初始视图的 URL |
    | `view.url`      | 视图的 URL        |
    | `view.name`     | 视图的名称          |
  </Accordion>

  <Accordion title="ActionEvent 可修改属性">
    | 属性键                  | 描述             |
    | -------------------- | -------------- |
    | `action.target.name` | 目标名称           |
    | `view.referrer`      | 链接到页面初始视图的 URL |
    | `view.url`           | 视图的 URL        |
    | `view.name`          | 视图的名称          |
  </Accordion>

  <Accordion title="ErrorEvent 可修改属性">
    | 属性键                  | 描述             |
    | -------------------- | -------------- |
    | `error.message`      | 错误消息           |
    | `error.stack`        | 错误的堆栈跟踪        |
    | `error.resource.url` | 资源的 URL        |
    | `view.referrer`      | 链接到页面初始视图的 URL |
    | `view.url`           | 视图的 URL        |
    | `view.name`          | 视图的名称          |
  </Accordion>

  <Accordion title="ResourceEvent 可修改属性">
    | 属性键             | 描述             |
    | --------------- | -------------- |
    | `resource.url`  | 资源的 URL        |
    | `view.referrer` | 链接到页面初始视图的 URL |
    | `view.url`      | 视图的 URL        |
    | `view.name`     | 视图的名称          |
  </Accordion>

  <Accordion title="LongTaskEvent 可修改属性">
    | 属性键             | 描述             |
    | --------------- | -------------- |
    | `view.referrer` | 链接到页面初始视图的 URL |
    | `view.url`      | 视图的 URL        |
    | `view.name`     | 视图的名称          |
  </Accordion>
</AccordionGroup>

<Warning>
  如果从 `EventMapper<T>` 实现中返回 `null`，则事件将被丢弃，不会发送到 Flashduty。
</Warning>

### 示例：丢弃敏感错误

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    val rumConfig = RumConfiguration.Builder(applicationId)
        .setErrorEventMapper { errorEvent ->
            if (errorEvent.error.message?.contains("sensitive_data") == true) {
                null // 丢弃包含敏感数据的错误
            } else {
                errorEvent
            }
        }
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
        .setErrorEventMapper(errorEvent -> {
            if (errorEvent.error.message != null &&
                errorEvent.error.message.contains("sensitive_data")) {
                return null; // 丢弃包含敏感数据的错误
            } else {
                return errorEvent;
            }
        })
        .build();
    ```
  </Tab>
</Tabs>

## 获取 RUM Session ID

检索 RUM Session ID 对于故障排查很有帮助。您可以将 Session ID 附加到支持请求、电子邮件或错误报告中，以便支持团队在 Flashduty 中找到用户会话。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.GlobalRumMonitor

    GlobalRumMonitor.get().getCurrentSessionId { sessionId ->
        currentSessionId = sessionId
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.GlobalRumMonitor;

    GlobalRumMonitor.get().getCurrentSessionId(sessionId -> {
        currentSessionId = sessionId;
    });
    ```
  </Tab>
</Tabs>

<Tip>
  您可以在运行时访问 RUM Session ID，而无需等待 `sessionStarted` 事件。
</Tip>

## 采样控制

默认情况下，RUM 会收集所有会话的数据。您可以通过 `sessionSampleRate` 参数设置采样率来减少收集的会话数量。

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.rum.RumConfiguration

    val rumConfig = RumConfiguration.Builder(applicationId)
        .setSessionSampleRate(90.0f) // 采集 90% 的会话
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.rum.RumConfiguration;

    RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
        .setSessionSampleRate(90.0f) // 采集 90% 的会话
        .build();
    ```
  </Tab>
</Tabs>

<Note>
  采样率范围：**0.0 - 100.0**

  * `100.0` - 收集所有会话（默认）
  * `50.0` - 收集 50% 的会话
  * `0.0` - 不收集任何会话
</Note>

<Warning>
  被采样丢弃的会话将不收集任何页面视图及其相关遥测数据。
</Warning>

## 用户跟踪同意

为遵守 GDPR、CCPA 等隐私法规，RUM 允许在初始化时设置用户跟踪同意状态。

### 同意状态说明

| 状态                            | 行为                   | 使用场景      |
| ----------------------------- | -------------------- | --------- |
| `TrackingConsent.GRANTED`     | 开始收集数据并发送到 Flashduty | 用户已同意数据收集 |
| `TrackingConsent.NOT_GRANTED` | 不收集任何数据              | 用户拒绝数据收集  |
| `TrackingConsent.PENDING`     | 收集数据但不发送             | 等待用户确认    |

<Note>
  如果初始化时使用 `TrackingConsent.PENDING`，SDK 将开始收集数据，但在同意状态更改为 `GRANTED` 之前不会发送。
</Note>

### 更改同意状态

您可以通过 `setTrackingConsent` API 在初始化后更改同意状态：

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.datadog.android.Datadog
    import com.datadog.android.privacy.TrackingConsent

    Datadog.setTrackingConsent(TrackingConsent.GRANTED)
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.datadog.android.Datadog;
    import com.datadog.android.privacy.TrackingConsent;

    Datadog.setTrackingConsent(TrackingConsent.GRANTED);
    ```
  </Tab>
</Tabs>

## 最佳实践

<AccordionGroup>
  <Accordion title="视图追踪">
    * 确保在适当的生命周期方法中调用 `startView` 和 `stopView`，避免视图重复追踪
    * 为每个视图使用唯一的 `viewKey`
  </Accordion>

  <Accordion title="资源追踪">
    * 使用自定义资源追踪时，确保每个 `startResource` 都有对应的 `stopResource` 或 `stopResourceWithError` 调用
    * 避免追踪内部资源或过于频繁的请求
  </Accordion>

  <Accordion title="事件修改">
    * 修改事件时，只有表格中列出的属性可以修改，其他属性的修改将被忽略
    * 返回 `null` 可丢弃整个事件
  </Accordion>

  <Accordion title="性能优化">
    * 合理设置采样率和批量上传频率，平衡数据量与性能开销
    * 避免在事件回调中执行耗时操作
  </Accordion>
</AccordionGroup>

## 相关文档

<CardGroup cols={3}>
  <Card title="SDK 接入" icon="plug" href="/zh/rum/sdk/android/sdk-integration">
    了解如何接入 Android SDK
  </Card>

  <Card title="数据收集" icon="database" href="/zh/rum/sdk/android/data-collection">
    了解 SDK 收集的数据类型
  </Card>

  <Card title="兼容性" icon="check" href="/zh/rum/sdk/android/compatible">
    了解 SDK 兼容性要求
  </Card>
</CardGroup>
