feat: 启动监控维度字段 is_first_install 对齐为 app_install_status

- LaunchMonitor:维度字段改为 app_install_status(normal/new_install/over_written 三值),getAppInstallStatus() 以 StartManager 布尔值映射两值,over_written 待完整 workspace 对齐;分桶指标维度名与 record 同步
- demo LaunchDiagnostics 同步:appInstallStatus 以 preferences 自实现(无记录→new_install,有记录→normal),展示与类头注释更新,over_written 无法区分已注明
- 真机验证:首启 app_install_status=new_install,二次启动=normal

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
clz
2026-08-06 14:51:39 +08:00
parent 96d6f1b34e
commit 96f183c2c0
2 changed files with 23 additions and 17 deletions
@@ -24,8 +24,9 @@ enum DrawReportState {
* *
* 与 future_entry_demo 的 LaunchMonitor.ets 对应:本文件为无依赖演示实现 * 与 future_entry_demo 的 LaunchMonitor.ets 对应:本文件为无依赖演示实现
* (仅 hilog + 页面展示,不做 ELK 上传),追溯字段已同步系统时间拆解字段 * (仅 hilog + 页面展示,不做 ELK 上传),追溯字段已同步系统时间拆解字段
* 与 deviceInfo 环境字段;git_commit / is_first_install / build_mode 依赖 * 与 deviceInfo 环境字段;app_install_status 以 preferences 自实现(三值语义,
* biz_common 与 BuildProfile,演示工程不适用,故未同步。 * over_written 无法区分);git_commit / build_mode 依赖 biz_common 与
* BuildProfile,演示工程不适用,故未同步。
*/ */
export class LaunchDiagnostics { export class LaunchDiagnostics {
private static readonly WATCHER_NAME: string = 'startupDiagnosticsWatcher'; private static readonly WATCHER_NAME: string = 'startupDiagnosticsWatcher';
@@ -43,10 +44,10 @@ export class LaunchDiagnostics {
*/ */
private static watcherRegisterTime: number = 0; private static watcherRegisterTime: number = 0;
/** /**
* 是否安装后首次启动(维度):preferences 无启动记录即为首次,随后写入标记。 * 安装状态(维度):preferences 无启动记录视为 new_install,随后写入标记。
* 与生产实现(StartManager.getAppInstallStatus)语义等价,演示工程无 biz_common 依赖故自实现 * 与生产实现(app_install_status 三值)对齐;演示工程无法区分 over_written(覆盖安装保留数据时显示 normal)
*/ */
private static isFirstInstall: boolean = false; private static appInstallStatus: string = 'normal';
private static watcherInitialized: boolean = false; private static watcherInitialized: boolean = false;
private static drawReportState: DrawReportState = DrawReportState.IDLE; private static drawReportState: DrawReportState = DrawReportState.IDLE;
private static capturedEntryPage: string = '未捕获'; private static capturedEntryPage: string = '未捕获';
@@ -67,14 +68,14 @@ export class LaunchDiagnostics {
if (LaunchDiagnostics.watcherInitialized) { if (LaunchDiagnostics.watcherInitialized) {
return; return;
} }
// 首次安装标志preferences 无启动记录视为首次,随后写入并同步落盘;异常时按非首次处理 // 安装状态preferences 无启动记录视为 new_install,随后写入并同步落盘;异常时按 normal 处理
try { try {
const pref: preferences.Preferences = preferences.getPreferencesSync(context, { name: 'startup_demo' }); const pref: preferences.Preferences = preferences.getPreferencesSync(context, { name: 'startup_demo' });
LaunchDiagnostics.isFirstInstall = !pref.getSync('has_launched', false); LaunchDiagnostics.appInstallStatus = pref.getSync('has_launched', false) ? 'normal' : 'new_install';
pref.putSync('has_launched', true); pref.putSync('has_launched', true);
pref.flushSync(); pref.flushSync();
} catch (e) { } catch (e) {
LaunchDiagnostics.isFirstInstall = false; LaunchDiagnostics.appInstallStatus = 'normal';
} }
const filter: hiAppEvent.AppEventFilter = { const filter: hiAppEvent.AppEventFilter = {
@@ -288,7 +289,7 @@ export class LaunchDiagnostics {
`appattach_to_appforeground_dur=${appattachToAppForegroundDur}ms\n` + `appattach_to_appforeground_dur=${appattachToAppForegroundDur}ms\n` +
`device_type=${LaunchDiagnostics.getDeviceType()}, ` + `device_type=${LaunchDiagnostics.getDeviceType()}, ` +
`system_version=${LaunchDiagnostics.getSystemVersion()}\n` + `system_version=${LaunchDiagnostics.getSystemVersion()}\n` +
`is_first_install=${LaunchDiagnostics.isFirstInstall}\n` + `app_install_status=${LaunchDiagnostics.appInstallStatus}\n` +
`补报事件=${isBackfill ? '是(entry_page 不归因,按 unknown 处理)' : '否'}`; `补报事件=${isBackfill ? '是(entry_page 不归因,按 unknown 处理)' : '否'}`;
LaunchDiagnostics.lastAction = '已捕获有效冷启动 APP_LAUNCH'; LaunchDiagnostics.lastAction = '已捕获有效冷启动 APP_LAUNCH';
LaunchDiagnostics.logInfo(LaunchDiagnostics.lastLaunchDetail); LaunchDiagnostics.logInfo(LaunchDiagnostics.lastLaunchDetail);
@@ -190,7 +190,7 @@ export class LaunchMonitor {
start_type: startType, start_type: startType,
entry_page: isBackfillEvent ? 'unknown' : LaunchMonitor.capturedEntryPage, entry_page: isBackfillEvent ? 'unknown' : LaunchMonitor.capturedEntryPage,
app_version: LaunchMonitor.getAppVersion(), app_version: LaunchMonitor.getAppVersion(),
is_first_install: LaunchMonitor.getIsFirstInstall(), app_install_status: LaunchMonitor.getAppInstallStatus(),
response_latency: responseLatency, response_latency: responseLatency,
animation_finish_time: animationFinishTime, animation_finish_time: animationFinishTime,
startability_processstart_dur: startabilityProcessStartDur, startability_processstart_dur: startabilityProcessStartDur,
@@ -216,7 +216,7 @@ export class LaunchMonitor {
monitor.setDimension_1(startType.toString()) monitor.setDimension_1(startType.toString())
monitor.setDimension_2(isBackfillEvent ? 'unknown' : LaunchMonitor.capturedEntryPage) monitor.setDimension_2(isBackfillEvent ? 'unknown' : LaunchMonitor.capturedEntryPage)
monitor.setDimension_3(LaunchMonitor.getAppVersion()) monitor.setDimension_3(LaunchMonitor.getAppVersion())
monitor.setDimension_4(LaunchMonitor.getIsFirstInstall().toString()) monitor.setDimension_4(LaunchMonitor.getAppInstallStatus())
monitor.record(coldStartTime) monitor.record(coldStartTime)
HXLog.i(TAG, `Cold start bucket metric recorded: ${coldStartTime}ms`) HXLog.i(TAG, `Cold start bucket metric recorded: ${coldStartTime}ms`)
} catch (e) { } catch (e) {
@@ -238,7 +238,7 @@ export class LaunchMonitor {
builder.setDimension1Name('start_type') builder.setDimension1Name('start_type')
builder.setDimension2Name('entry_page') builder.setDimension2Name('entry_page')
builder.setDimension3Name('app_version') builder.setDimension3Name('app_version')
builder.setDimension4Name('is_first_install') builder.setDimension4Name('app_install_status')
builder.setBuckets([500, 600, 700, 800, 1000, 1500, 2000, 3000]) builder.setBuckets([500, 600, 700, 800, 1000, 1500, 2000, 3000])
HXEventMonitor.getEventFactory('launch').create(builder) HXEventMonitor.getEventFactory('launch').create(builder)
LaunchMonitor.bucketMetricInitialized = true LaunchMonitor.bucketMetricInitialized = true
@@ -259,9 +259,13 @@ export class LaunchMonitor {
return GIT_COMMIT return GIT_COMMIT
} }
/** 维度:是否安装后首次进入(StartManager 在 EntryAbility.onCreate 中已 init */ /**
private static getIsFirstInstall(): boolean { * 维度:安装状态(normal/new_install/over_written)。
return StartManager.getInstance().getAppInstallStatus() * 真实实现取三值安装来源;当前以 StartManager 布尔值映射(true→new_installfalse→normal),
* over_written 需安装来源信息,待完整 workspace 对齐。
*/
private static getAppInstallStatus(): string {
return StartManager.getInstance().getAppInstallStatus() ? 'new_install' : 'normal'
} }
} }
@@ -285,8 +289,9 @@ interface ColdStartMetricPayload {
entry_page: string entry_page: string
// 维度:应用内部版本号 // 维度:应用内部版本号
app_version: string app_version: string
// 维度:是否安装后首次启动(首次启动耗时显著偏高,需从常规分布中区分) // 维度:安装状态(normal 常规 / new_install 全新安装 / over_written 覆盖安装),
is_first_install: boolean // 首启耗时显著偏高,需从常规分布中区分
app_install_status: string
// 系统响应段:离手到动效开始耗时(ms,需 API 22+) // 系统响应段:离手到动效开始耗时(ms,需 API 22+)
response_latency: number response_latency: number
// 系统动效段:动效完成耗时(ms) // 系统动效段:动效完成耗时(ms)