yx_tracking_flutter/0.总体目标与边界.md

457 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 一、总体目标与边界
## 1.1 目标
基于现有后端接口,建设一套统一的埋点 SDK覆盖
- 技术栈:
- Flutter**独立纯 Dart SDK**
- Android原生 Kotlin SDK
- iOS原生 Swift SDK
- 对齐后端接口:
- `GET /api/ExternalEventlogs/GetSystemAllDimInfo`
- `POST /api/ExternalEventlogs/AddEventListLog`
- `POST /api/ExternalEventlogs/AddEventLog`
- 三阶段演进:
- Phase 1可用性 + 安全稳定性
- Phase 2可维护性 + 配置化 + 调试
- Phase 3可观测性 + 动态策略 + 插件化
不绑定具体业务逻辑,但要能支持 OA、教育等各类场景。
## 1.2 统一事件数据模型
### 请求结构(与后端对齐)
jsonc
```
{
"system_code": "string",
"eventType": "string",
"userInfo": {
"userId": 0,
"userName": "string",
"account": "string"
},
"clientType": 1,
"clientTimestamp": 0,
"timestamp": "2026-01-26T08:29:44.734Z",
"deviceInfo": {
"os": "string",
"model": "string",
"screenResolution": "string"
},
"eventParams": {
// 事件上下文,例如 page、buttonId、url…
},
"customTags": {
// 扩展维度,业务可自定义
}
}
```
### 统一对外 API 设计(跨三端)
(伪接口,三端风格尽量保持一致)
ts
```
class Analytics {
static init(config: SDKConfig): void | Future<void>
static track(
eventType: string,
options?: {
eventParams?: Map<string, any>
customTags?: Map<string, any>
timestamp?: number // 毫秒级 client 时间,可不传
}
): void | Future<void>
static setUser(userInfo: UserInfo | null): void | Future<void>
static setDeviceInfo(deviceInfo: DeviceInfo): void | Future<void>
static flush(): void | Future<void>
static setDebug(enabled: boolean): void
}
```
`SDKConfig` 关键字段(统一):
- `systemCode: string`
- `endpointBaseUrl: string`(如 `https://host/api/ExternalEventlogs`
- `clientType: int`统一约定1=Android2=iOS3=Flutter
- `enableDebug: boolean`
- `batchSize: int`(默认 20
- `flushInterval: int`(秒,默认 15
- `maxCacheSize: int`(默认 5000
- `maxRetryCount: int`(默认 3
- `connectTimeout`, `readTimeout`
------
# 二、整体架构设计(通用视角)
SDK 内部统一分层:
1. **API 层Facade**
- 暴露 `init / track / flush / setUser / setDebug`
- 做参数校验、线程切换(原生)。
2. **EventManager事件管理层**
- 构造标准事件对象(填充 system_code、userInfo、deviceInfo、时间
- 写入本地队列;触发上传调度。
3. **Storage存储层**
- 事件持久化SQLite / 本地 KV
- 控制队列长度、过期清理。
4. **NetworkClient网络层**
- 封装调用:`AddEventListLog`(优先)、`AddEventLog`(可选降级)。
- 统一超时、重试、错误处理。
5. **Config / DimensionManager配置 & 维度)**
- 管理 SDKConfig。
- Phase 2+:拉取 `GetSystemAllDimInfo`,存本地。
6. **Validator / Debug校验 & 调试)**
- Phase 2+:基于配置做事件参数校验。
- 统一 debug 日志输出。
7. **Interceptors / Plugins插件层**
- Phase 3对事件发送前后提供 Hook。
------
# 三、三端实现策略
## 3.1 Flutter 独立 SDK纯 Dart
- 语言Dart
- 存储:推荐 `sqflite`SQLite`hive`KV
- `events(id, payload_json, retry_count, create_time)`
- 网络:`dio` 或 `http`
- 调度:
- `Timer.periodic` 实现定时 flush
- 控制并发:用一个「上传中」标志避免并发多次 flush
- 生命周期:
- SDK 已实现 `Analytics.bindLifecycleObserver()`,自动在后台/销毁时 flush
- 应用也可手动调用 `flush()`
## 3.2 Android SDK
- 语言Kotlin对 Java 兼容)
- 存储Room 或 SQLite 封装
- 网络OkHttp + Retrofit
- 线程Kotlin Coroutines + 单一上传协程
- 生命周期:`ProcessLifecycleOwner` 监听前后台 → 后台前触发 `flush`
## 3.3 iOS SDK
- 语言Swift暴露 ObjC 兼容 API
- 存储SQLite 或 Core Data 轻量封装
- 网络URLSession
- 生命周期:监听 `willResignActive` / `didEnterBackground` 调用 `flush`
------
# 四、三阶段规划(含架构与验收)
------
## Phase 1可用性 + 安全稳定性
### 4.1 目标
- 提供稳定、可用的基础事件采集 & 批量上报能力。
- 不影响业务性能和体验。
- 基本安全HTTPS预留签名扩展
### 4.2 能力范围
1. 初始化
- 校验并保存 `SDKConfig`
- 自动采集 `DeviceInfo`
- 初始化本地存储;
- 启动定时 flush 调度(根据 flushInterval
2. 事件写入track
- 检查 SDK 是否已 init
- 构造 Event
- `system_code` from config
- `eventType` from 调用
- `userInfo` from `setUser`
- `clientType` from config
- `clientTimestamp` = 当前毫秒时间戳
- `timestamp` = ISO8601 字符串
- `deviceInfo` from 初始化采集
- `eventParams`、`customTags` from 调用
- 事件入内存队列 + 异步持久化保存。
3. 缓存与发送策略
- 存储:
- SQLite / KV + 索引;
- 最大缓存条数:`maxCacheSize`,超限则删除最旧事件。
- 发送:
- 定时器触发 flush
- 队列长度 >= `batchSize` 可立即 flush
- 调用 `AddEventListLog` 批量上传;
- 如后端明确不支持,可选降级 `AddEventLog`
- 重试:
- 网络错误或 5xx 重试,最多 `maxRetryCount`,指数退避;
- 4xx 视为业务失败,不重试,直接丢弃该批,并记录错误(日志)。
4. 安全与稳定
- endpoint 必须为 HTTPS
- 预留请求 header 扩展(签名 / 时间戳 / nonce
- 所有 IO 和网络在后台线程 / async不阻塞 UI
- 所有异常在 SDK 内部捕获,不向上抛出导致崩溃。
### 4.3 开发要求
通用:
- 核心逻辑单元测试覆盖率 ≥ 80%(事件构造、缓存、上传、重试)。
- 使用统一的日志前缀(例如 `[AnalyticsSDK]`)。
- API 文档齐全,含参数说明和示例代码。
Flutter
- 不引入过重依赖,确保兼容常见 Flutter stable 版本;
- 高频 track 时(例如 10 次/秒)主 Isolate 无明显卡顿。
Android
- 支持主流 Android 版本(按照公司基线,例如 API 21+
- 在 debug 版开启详细日志release 版关闭。
iOS
- 支持主流 iOS 版本(例如 iOS 12+
- 保证在 App 退后台 / 杀进程前能尽可能 flush。
### 4.4 Phase 1 验收标准
功能:
- 三端均可:
`init → setUser → track → flush` 全流程成功;
- 离线:
- 断网时事件成功写入本地;
- 恢复网络后自动/手动 flush可在后端查看到补发数据
- 批量:
- 实际调用 `AddEventListLog`
- 后端数据结构与约定一致(字段正确)。
稳定:
- 连续调用 track 1 万次以内无崩溃;
- 事件缓存满时按预期丢弃最旧数据,不影响业务。
安全:
- 所有请求通过 HTTPS
- 默认不输出包含 userInfo 的敏感日志(除非显式 enableDebug
文档:
- 各端接入指南(集成、初始化、上报示例);
- 一份基础 FAQ常见错误、排查方式
------
## Phase 2可维护性 + 配置化 + 调试能力
### 5.1 目标
- 降低埋点维护成本;
- 支持通过后端配置管理事件和维度;
- 提供调试和校验工具,提高埋点正确率。
### 5.2 能力范围
1. 利用 `GetSystemAllDimInfo` 下发配置
- SDK 在 init 后或定期调用:
- 获取 `systemInfo`、`systemEventTypes`、`systemCustonTas`
- 转换成本地配置对象,缓存到本地(带 version / lastModified
ts
```
type EventDefinition = {
eventCode: string
eventName: string
description?: string
}
type TagDefinition = {
tagName: string
tagType: string // string/int/bool/enum
isRequired: boolean
description?: string
}
```
- 失败不影响事件发送(降级为无配置模式)。
1. 事件校验
-`track` 时(主要在 debug 模式启用):
- 校验 `eventType` 是否存在于 `systemEventTypes`
- 使用 `systemCustonTas` 检查:
- 必填 tag 是否存在;
- 类型是否匹配(尝试容错转换)。
- 错误处理:
- Debug 模式:
- 在日志中详细打印:未注册事件、缺失字段、类型错误;
- 可配置:是否禁止发送这类事件。
- Release 模式:
- 仍发送,但在 `customTags` 中附加:
- `_sdk_invalid_event`
- `_sdk_missing_tags`
- `_sdk_type_error_fields`
1. 调试工具
- 日志级:
- `setDebug(true)` 时:
- 打印每条事件的 JSON
- 打印发送结果(状态码、错误内容)。
- Demo 内调试页面(建议):
- 支持:
- 查看缓存事件数量 / 最近 N 条事件摘要;
- 按钮触发 flush。
1. 队列与策略优化(基本)
- 事件过期时间(例如默认 7 天);
- 网络状态感知(原生):
- Wi-Fi 下更高频 / 大批次;
- 蜂窝网络下减少频率 / 批量。
### 5.3 开发要求
- 新增模块:
- `ConfigManager`:拉取与缓存后端维度配置;
- `Validator`:统一事件校验逻辑。
- 兼容 Phase 1
- 未取到配置时,一切行为回退到 Phase 1 模式;
- 增加测试:
- 事件存在 / 不存在;
- 必填字段缺失;
- 类型错误时的行为。
### 5.4 Phase 2 验收标准
功能:
- 初始化后,可以成功调用 `GetSystemAllDimInfo` 并本地缓存;
- 在 debug 模式下:
- 未配置的 `eventType` 调用时有明确日志提示;
- 缺失必填 tag / 类型错误能被检测并打印提示。
调试体验:
- 开发可以在本地:
- 看到完整事件 JSON
- 根据提示迅速发现埋点错漏。
可维护性:
- 后端新增事件配置systemEventTypes 中新增)后,不发版即可在客户端调用新事件;
- 对关键事件,可以通过配置 + SDK 校验,显著减少埋点错误。
------
## Phase 3可观测性 + 动态策略 + 插件化
### 6.1 目标
- 让 SDK 自身「可被监控、可被远程控制」;
- 支持高级使用场景:采样、动态开关、插件扩展。
### 6.2 能力范围
1. SDK 自身监控埋点
- 内部采集 SDK 运行指标(作为特殊事件上报):
- 发送成功计数 / 失败计数 / 重试次数;
- 平均延迟;
- 队列当前长度 / 溢出丢弃数;
- 周期性上报(如每 N 分钟一次)。
1. 动态策略控制
- 通过配置(可在 `GetSystemAllDimInfo` 扩展,或单独接口)下发策略,如:
jsonc
```
{
"enabled": true,
"eventSettings": {
"EVENT_A": { "enabled": true, "sampleRate": 1.0 },
"EVENT_B": { "enabled": false, "sampleRate": 0.0 },
"EVENT_C": { "enabled": true, "sampleRate": 0.1 }
}
}
```
- SDK 在 `track` 时:
- 若事件被标记 `enabled=false` → 直接丢弃;
-`sampleRate < 1` → 按采样率丢弃部分事件(哈希或随机)。
1. 插件 / 拦截器机制
- 接口示例(通用设计):
ts
```
interface EventInterceptor {
beforeSend(event: Event): Event | null | Promise<Event | null>
afterSend(event: Event, result: SendResult): void | Promise<void>
}
```
- SDK 提供:
- `registerInterceptor(interceptor)` / `addInterceptor` 方法;
- 内置拦截器debug 打印、公共字段填充等。
典型用途:
- 业务统一追加自定义 `customTags`(如租户 ID、业务线 ID
- 将部分发送失败事件写入本地日志,便于问题排查。
1. 版本管理
- 事件级 schemaVersion 预留:
-`customTags``eventParams` 中加入 `_schema_version`
- SDK 版本上报:
- 每条事件默认携带 `_sdk_version``_platform`,便于后端统计版本分布。
### 6.3 开发要求
- 性能:
- 插件链路运行开销可控(单条事件处理在毫秒级以内);
- 隔离:
- 单个插件抛出的异常不会影响主流程和其他插件;
- 文档:
- 清晰说明策略配置字段及含义;
- 插件开发 & 使用指南。
### 6.4 Phase 3 验收标准
- 自监控:
- 后端可以查看 SDK 的发送成功率、失败率、队列长度等;
- 动态控制:
- 通过配置关闭某个 eventType 后,客户端不再上报该事件;
- 调整 sampleRate 后,事件量按预期变化;
- 插件:
- 样例插件能实现:
- 自动附加业务 tag
- 记录失败事件到本地日志。
------
这版方案已经:
- 明确Flutter 为独立纯 Dart SDK与 Android/iOS 平行;
- 统一:三端对外 API、数据结构、阶段目标和验收标准
- 预留:维度配置、校验、动态策略、插件机制的扩展空间。