# 一、总体目标与边界 ## 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 static track( eventType: string, options?: { eventParams?: Map customTags?: Map timestamp?: number // 毫秒级 client 时间,可不传 } ): void | Future static setUser(userInfo: UserInfo | null): void | Future static setDeviceInfo(deviceInfo: DeviceInfo): void | Future static flush(): void | Future static setDebug(enabled: boolean): void } ``` `SDKConfig` 关键字段(统一): - `systemCode: string` - `endpointBaseUrl: string`(如 `https://host/api/ExternalEventlogs`) - `clientType: int`(统一约定:1=Android,2=iOS,3=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 afterSend(event: Event, result: SendResult): void | Promise } ``` - 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、数据结构、阶段目标和验收标准; - 预留:维度配置、校验、动态策略、插件机制的扩展空间。