Files
harmony-crash-analysis-report/apm_launch_monitor_config.md
clz 96d6f1b34e docs: 按真实落地实现更新接入方案第 4-6 章
- 维度字段 is_first_install 改为 app_install_status(normal/new_install/over_written 三值,与 StartManager 安装状态对齐)
- 新增 5.1 模块策略下发:链路 B 为策略驱动(无策略时 create/record 空转并打印 eventId has not created!),策略 JSON 对齐 EventStrategyBean.fromJson(config 嵌套 + status/sampling_rate/interval/aggre_time/aggre_count),含字段说明表与判定生效步骤
- §6 补回标题与开头段:链路 A/B 分工、链路 B API 已随 HXLaunchMonitorPlugin 编译验证(不再待确认)、插件形态(仿 HXCrashMonitorPlugin,startPlugin 建指标,APMHelper 注册)
- §7 验收标准同步策略激活条件与编译验证状态
- 新增 8.9 真实应用验证:首启 1141ms(new_install)/ 二次 1717ms(normal),链路 B 待策略下发复测;8.8 注明 demo(boolean)与生产(三值)差异
- 新增真机文档 apm_launch_monitor_config.md(真实 workspace 落地配置,含策略 JSON 与链路 A 字段定义)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-06 14:47:15 +08:00

128 lines
5.8 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.
# 启动性能监控(冷启动耗时)接入配置
> 作者:cheliangzhao
> 日期:2026-08-06
> 涉及模块:`entry`HAP 入口)+ `@kernel/app_monitor_event`APM 事件 SDK
> 对应需求:冷启动耗时(`cold_start_time`)采集与看板聚合
---
## 1. 背景与目标
统计同花顺期货鸿蒙版**冷启动耗时**,覆盖三条启动入口(`Index` / `LauncherPage` / `NetworkAnomalyPage`),区分冷启动 / 补投递四种场景,实现启动性能的持续观测与劣化告警。
采集分两条通道:
- **链路 A(Elk 追溯,已上线验证)**:把冷启动指标结构化 JSON 经 `ElkService` 异步上报,字段最全,可明细定位。
- **链路 BHXEventMonitor 分桶,需后台策略开启后生效)**:由 SDK 按桶自动归集,负责看板聚合曲线。
> ⚠️ 链路 B 是**策略驱动**的:SDK 侧在 `EventMonitorStrategy` 找不到 `launch` 模块的开启策略时,`create()/record()` 一律空转并打印 `Monitor.Event cold_start_time eventId has not created!`。应用侧无法绕开,必须由 **APM 后台下发对应模块策略**才能激活。
---
## 2. 链路 A:Elk 追溯(已生效,无需后台操作)
上报字段(`LaunchElkBuilder`,业务来源 `launch`):
| 字段 | 类型 | 说明 |
|------|------|------|
| `cold_start_time` | number | 冷启动耗时 ms = 系统事件 `extend_time` |
| `start_type` | number | 启动类型(当前只统计 `0`=冷启动) |
| `entry_page` | string | 入口页(`Index`/`LauncherPage`/`NetworkAnomalyPage`;补投递为 `unknown` |
| `app_version` | string | 应用内部版本号 |
| `app_install_status` | string | `normal`/`new_install`/`over_written` |
| `response_latency` | number | 离手到动效开始(需 API 22+) |
| `animation_finish_time` | number | 动效完成耗时 |
| `startability_processstart_dur` | number | 进程创建段(仅冷启动) |
| `appattach_to_appforeground_dur` | number | 进程挂载段(仅冷启动) |
| `git_commit` | string | 代码级追溯,劣化定位用 |
| `is_backfill` | boolean | 是否系统补投递的上次启动遗留事件 |
---
## 3. 链路 BHXEventMonitor 分桶指标(需后台开启)
### 3.1 后台需下发的模块策略
SDK 由 `HXEventMonitorPlugin.parseMonitorStrategy()` 读取,注入到 `EventStrategyBean` 后按模块打开。请为 **module=`launch`** 下发如下配置:
```json
{
"module": "launch",
"config": {
"status": 1,
"sampling_rate": 1.0,
"interval": 5000,
"aggre_time": 60000,
"aggre_count": 10
}
}
```
字段说明(对齐 `EventStrategyBean.fromJson`,仅这些字段生效):
| 字段 | 取值 | 说明 |
|------|------|------|
| `module` | `launch` | 必须与代码 `HXEventMonitor.getEventFactory('launch')` 一致 |
| `status` | `1` | **必须 `1`STATUS_OPEN**;否则 `isOpen()` 为 false`create/record` 全空转 |
| `sampling_rate` | `0~1` | 抽样率,`isOpen()``status==1 && 抽样通过` 才生效 |
| `interval` | ms | 采集间隔 |
| `aggre_time` | ms | 聚合时间阈值,达到即触发一次 push |
| `aggre_count` | 条 | 聚合数量阈值,达到即触发一次 push |
### 3.2 指标定义
| 项 | 值 |
|----|----|
| 模块名 `module` | `launch` |
| 指标名 `metric` | `cold_start_time` |
| 值域 | 冷启动耗时 ms`extend_time` |
| 分桶 `buckets` | `[500, 600, 700, 800, 1000, 1500, 2000, 3000]`(按实测 600–800ms 主体细分,尾部留劣化锚点) |
| 维度1 `start_type` | 冷启动 `0` |
| 维度2 `entry_page` | `Index`/`LauncherPage`/`NetworkAnomalyPage`/`unknown`(补投递) |
| 维度3 `app_version` | 应用内部版本号 |
| 维度4 `app_install_status` | `normal`/`new_install`/`over_written` |
### 3.3 判定生效
后台下发后,重启应用,冷启动日志中:
- ✅ 消失:`Monitor.Event cold_start_time eventId has not created!`
- ✅ 出现:`Cold start bucket metric recorded: <ms>` 与 SDK 聚合 push 日志
- ✅ 看板出现 `launch` 模块 `cold_start_time` 桶分布
---
## 4. 相关代码与文件
| 文件 | 作用 |
|------|------|
| `entry/src/main/ets/monitor/LaunchMonitor.ets` | APP_LAUNCH 订阅、Elk 上报、首帧 `reportDrawnCompleted`、桶指标定义与 record |
| `entry/src/main/ets/monitor/LaunchMonitor.ets``ensureColdStartMetric` | 创建 `launch/cold_start_time` 桶指标(幂等) |
| `entry/src/main/ets/monitor/plugin/HXLaunchMonitorPlugin.ets` | 仿 `HXCrashMonitorPlugin` 接入的启动插件,在 `startPlugin()` 建指标 |
| `entry/src/main/ets/monitor/APMHelper.ets` | 注册 `HXLaunchMonitorPlugin` 及配置类、`.plugin(...)` 列表 |
| `entry/src/main/ets/entryability/EntryAbility.ets` | `onCreate` 早注册 `LaunchMonitor.init()` |
| `entry/src/main/ets/pages/Index.ets` / `LauncherPage.ets` / `network/NetworkAnomalyPage.ets` | 首帧 `HOME_ROOT` 监听 + `reportFirstFrameOnDraw`/`dispose` |
### 打点时序
```
EntryAbility.onCreate → LaunchMonitor.init()(注册 APP_LAUNCH watcher
入口页 aboutToAppear → reportFirstFrameOnDraw(HOME_ROOT) → 首帧 draw → reportDrawnCompleted()
系统产生 APP_LAUNCH 事件(冷启动)→ onReceive
├─ 链路A: ElkService 上传冷启动 JSON(字段见 §2)
└─ 链路B: HXEventMonitor record(cold_start_time)(依赖 launch 策略,见 §3
补投递:icon_input_time 早于 watcher 注册 > 2000ms → 判为 backfillentry_page=unknown
```
---
## 5. 真机验证结论(2026-08-06nova 14 Pro
| 场景 | 结果 |
|------|------|
| 全新安装首启(`new_install` | 链路 A`cold_start_time=1141ms`Entry=IndexElk 上报 ✅ |
| 二次冷启动(`normal` | 链路 A`cold_start_time=1717ms`Elk 上报 ✅ |
| 链路 B(分桶) | ❌ 待后台下发 `launch` 策略(§3.1)后复测 |
编译:`./claude_tool/claude_compile.sh → BUILD_SUCCESS`