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

# Flutter SDK 高级配置

> 配置 Flutter RUM SDK 的采样率、远程配置、隐私同意、事件过滤、分布式追踪和符号文件上传

本文介绍 Flutter SDK 的进阶配置项。所有配置都通过 `DatadogConfiguration` 与 `DatadogRumConfiguration` 传入。

## 采样率

```dart theme={null}
DatadogRumConfiguration(
  applicationId: '<APPLICATION_ID>',
  sessionSamplingRate: 100.0, // 会话采样率
  traceSampleRate: 20.0,      // resource 上的追踪采样率
);
```

## 远程配置

`flashcat_flutter_plugin` 0.2.0 起，会话采样率可以在控制台 **应用管理 → 远程配置** 页签在线调整，无需改代码、重新发版。该功能默认关闭，需要在初始化时开启：

```dart theme={null}
DatadogRumConfiguration(
  applicationId: '<APPLICATION_ID>',
  sessionSamplingRate: 100.0,        // 控制台未下发时使用的采样率
  remoteConfigurationEnabled: true,
);
```

开启后，配置由插件底层的原生 Android / iOS SDK 拉取，行为与原生端一致：

* 控制台发布的采样率对**下一个新会话**生效，进行中的会话不受影响。
* 下发的值会持久化到本地，冷启动后的第一个会话即按上次下发的采样率抽样。
* 请求失败、超时或响应无法识别时，沿用已生效的值，不会清空；控制台停用远程配置后，恢复使用初始化时的 `sessionSamplingRate`。
* Flutter SDK 只读取**会话采样率**与**自定义配置项**两项，其余配置项不生效。自定义配置项可通过 `getRemoteConfig()` 读取，未开启远程配置或尚未拿到配置时返回 `null`：

```dart theme={null}
final custom = await DatadogSdk.instance.rum?.getRemoteConfig();
// 数字经平台通道传回时，可能是 int 也可能是 double（取决于平台），统一按 num 读取
final threshold = (custom?['threshold'] as num?)?.toDouble();
```

需要按业务规则决定采样时，可通过 `beforeSampling` 回调干预：每次新建会话时，它收到即将生效的采样率（`sessionSampleRate`）与控制台的自定义配置项（`custom`），返回新的采样率即可覆盖，返回 `null` 表示不干预。回调同步执行，需保持轻量；返回 0–100 以外的值、抛出异常或执行超时，都会沿用原生 SDK 的判定。未开启远程配置时回调同样会执行，此时 `sessionSampleRate` 是本地设置的值，`custom` 为 `null`。

```dart theme={null}
DatadogRumConfiguration(
  applicationId: '<APPLICATION_ID>',
  remoteConfigurationEnabled: true,
  beforeSampling: (context) {
    // 例如：控制台自定义配置项 debugUsers 里的用户全量采集，其余沿用下发的采样率
    final debugUsers = context.custom?['debugUsers'];
    if (debugUsers is List && debugUsers.contains(currentUserId)) {
      return 100;
    }
    return null;
  },
);
```

若要不受采样率限制地采集当前用户（例如排查特定用户的问题），可调用 `DatadogSdk.instance.rum?.setForcedSession()`：若当前会话未被采中，会立即结束并开启一个采集的新会话，此后直到进程结束的会话一律采集；该设置无法撤销，重启 App 后恢复。

<Note>
  如果 Flutter 是挂接到一个已经初始化过的原生 SDK 上（add-to-app 场景），`remoteConfigurationEnabled` 与 `beforeSampling` 必须由原生侧在初始化 RUM 时配置，见 [iOS SDK 高级配置](/zh/rum/sdk/ios/advanced-config) 与 [Android SDK 高级配置](/zh/rum/sdk/android/advanced-config)；`getRemoteConfig()` 与 `setForcedSession()` 仍可在 Dart 侧调用。
</Note>

<Warning>
  自定义配置项会下发到客户端，任何持有 Client Token 的人都能读到。请勿在其中存放密钥、访问令牌或个人敏感信息。
</Warning>

控制台侧的配置项、发布与生效方式见 [应用管理 · 远程配置](/zh/rum/quickstart/app-management#远程配置)。

## 隐私同意

`TrackingConsent` 控制是否采集与上报数据，适配 GDPR 等合规要求：

| 取值 | 行为 |
| - | - |
| `TrackingConsent.granted` | 采集并上报 |
| `TrackingConsent.notGranted` | 不采集 |
| `TrackingConsent.pending` | 先缓存，待用户授权后决定上报或丢弃 |

```dart theme={null}
// 初始化时传入
await DatadogSdk.runApp(configuration, TrackingConsent.pending, () async {
  runApp(const MyApp());
});

// 用户授权后更新
DatadogSdk.instance.setTrackingConsent(TrackingConsent.granted);
```

## 事件过滤与脱敏

事件映射器在事件上报前执行，返回 `null` 丢弃事件，或修改后返回。可用于脱敏敏感字段、去除噪声、重命名视图。

```dart theme={null}
DatadogRumConfiguration(
  applicationId: '<APPLICATION_ID>',
  viewEventMapper: (event) => event,
  actionEventMapper: (event) => event,
  resourceEventMapper: (event) {
    // 例如去除 URL 中的 query token
    return event;
  },
  errorEventMapper: (event) => event,
  longTaskEventMapper: (event) => event,
);
```

## 分布式追踪

对 `firstPartyHosts` 命中的域名，SDK 会注入 W3C `traceparent`，实现前端 RUM 与后端 APM 的链路关联。追踪需要配合网络采集（`enableHttpTracking()`）。

```dart theme={null}
import 'package:flashcat_flutter_plugin/flashcat_flutter_plugin.dart';
import 'package:flashcat_tracking_http_client/flashcat_tracking_http_client.dart';

DatadogConfiguration(
  clientToken: '<CLIENT_TOKEN>',
  env: 'production',
  site: FlashcatSite.cn,
  firstPartyHosts: ['api.example.com', 'gateway.example.com'],
  rumConfiguration: DatadogRumConfiguration(
    applicationId: '<APPLICATION_ID>',
    traceSampleRate: 100.0,
  ),
)..enableHttpTracking();
```

## 自定义上报地址

私有化部署时，通过 `customEndpoint` 覆盖默认上报地址：

```dart theme={null}
DatadogRumConfiguration(
  applicationId: '<APPLICATION_ID>',
  customEndpoint: 'https://your-ingest.example.com/api/v2/rum',
);
```

<Warning>
  `customEndpoint` 是最终的 RUM intake URL，不是仅包含协议和域名的基础地址。它必须包含 `/api/v2/rum`；如果部署在路径前缀下，还需要保留该前缀，例如 `https://example.com/flashduty/api/v2/rum`。
</Warning>

## WebView 追踪

Flutter 页面内嵌 WebView 时，可通过 `flashcat_webview_tracking` 把 WebView 中的 Browser RUM 事件关联到当前原生 RUM 会话。

```yaml pubspec.yaml theme={null}
dependencies:
  flashcat_flutter_plugin: ^0.2.0
  webview_flutter: ^4.0.4
  flashcat_webview_tracking: ^0.1.1
```

```dart theme={null}
import 'package:flashcat_flutter_plugin/flashcat_flutter_plugin.dart';
import 'package:flashcat_webview_tracking/flashcat_webview_tracking.dart';
import 'package:webview_flutter/webview_flutter.dart';

final webViewController = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..trackDatadogEvents(
    DatadogSdk.instance,
    ['myapp.example'],
  )
  ..loadRequest(Uri.parse('https://myapp.example'));
```

传给 `trackDatadogEvents` 的是允许关联的主机名列表。主机名会匹配其子域名，但不支持通配符。WebView 加载的页面必须已经接入 <a href="/zh/rum/sdk/web/sdk-integration">Flashduty Browser SDK</a>；Android 还必须启用 `JavaScriptMode.unrestricted`，否则无法建立关联。

## 符号文件上传

要把崩溃与错误堆栈还原到源码位置，需要上传符号文件。Flutter 应用可能同时包含 Dart 与原生帧：

| 栈帧类型 | 所需文件 | 生成方式 |
| - | - | - |
| Dart（Android） | Flutter symbols | `flutter build apk --split-debug-info=<dir> --obfuscate` |
| Dart（iOS） | 暂不支持，见下方说明 | — |
| iOS Native | dSYM | Xcode 构建产物 |
| Android Native | mapping 文件 | R8 / ProGuard 产物 |

<Warning>
  **iOS 的 Dart 堆栈暂不支持符号化。** Flutter 为 Apple 平台生成的符号文件是 Mach-O 格式，平台当前只能解析 Android 侧的 ELF 格式，因此 iOS 的 `.symbols` 上传会被拒绝。iOS 原生崩溃不受影响，上传 dSYM 即可符号化。

  如果您的应用同时发布 iOS 和 Android，`--obfuscate` 仍可开启：Android 的 Dart 堆栈会正常还原，iOS 的 Dart 堆栈则保持混淆状态。若 iOS 的可读堆栈更重要，则该端构建时不要开启 `--obfuscate`。
</Warning>

使用 FlashCat CLI 上传符号文件：

```bash theme={null}
# 需要 @flashcatcloud/flashcat-cli ≥ 0.2.0
FLASHCAT_API_KEY=<API_KEY> flashcat-cli flutter-symbols upload <symbols-dir> \
  --service <SERVICE_NAME> --release-version <VERSION>
```

<Note>
  符号文件与崩溃事件是通过构建产物的 **build ID** 关联的，`service` 与 `release-version` 不参与匹配。因此二者与 SDK 初始化值不一致时，符号解析依然正常，只影响控制台「源码映射」列表中的归类与筛选。建议仍保持一致——尤其注意 Flutter 的构建号后缀（如 `1.2.3+45`）容易造成两边不一致。

  真正必须对上的是 build ID：`--split-debug-info` 产出的 `app.<platform>-<arch>.symbols`、APK 内 `libapp.so`、以及控制台「源码映射 → Flutter」列表中的 Build ID 三者必须相同。每次改动 Dart 代码都会生成新的 build ID，所以**符号上传必须纳入每一次发布构建**，否则该版本的堆栈会静默退化为不解析。
</Note>

## 其他配置

| 配置 | 默认值 | 说明 |
| - | - | - |
| `nativeCrashReportEnabled` | false | 是否采集原生崩溃 |
| `detectLongTasks` | true | 是否采集 long task |
| `longTaskThreshold` | 0.1s | long task 判定阈值 |
| `trackBackgroundEvents` | false | 是否采集应用后台期间的事件 |
| `vitalUpdateFrequency` | `VitalsFrequency.average` | 原生移动端性能指标的采集频率；设为 `null` 关闭 |
| `reportFlutterPerformance` | false | 是否额外采集 Flutter build / raster timing |
| `trackNonFatalAnrs` | 平台默认 | 是否采集非致命 ANR；Android 30+ 默认关闭，Android 29 及以下默认开启 |
| `appHangThreshold` | null | iOS App Hang 的判定阈值（秒）；`null` 表示关闭 |
| `batchSize` / `uploadFrequency` | — | 上报批量大小与频率，权衡实时性与耗电 |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.