HarmonyOS 7 接入 hiRetrieval 却没有故障日志?端侧参与、云端圈选、真正采集是三件事

应用在少量设备上出现 ArkTS OOM 或 GPU 内存问题,全量打开重日志又担心耗电和性能。HarmonyOS 7.0 / API 26.0.0 的应用灰度采集就是为这类定向排查提供手段。但它最容易造成的误判也很直接:端侧调用 participate() 返回了,开发者就以为日志一定会上传。参与灰度、被云端选中、在任务有效期内发生指定故障并上报,是三个不同阶段。

本文聚焦 hiRetrieval,不把它写成普通的实时日志 SDK。两个案例分别处理初始化顺序错误和“调用成功但没有日志”的排查。代码按华为开发者 API 26.0.0 参考页编写;当前没有 API 26.0.0 SDK、端云灰度任务和受控设备,因此只能验证纯控制逻辑,不能宣称完成真实故障采集。

端云分段排查图

能力边界先弄清

官方说明从 API 26.0.0 起支持应用灰度采集,可定向收集 RSS 内存泄漏、ArkTS-OOM、FD 内存泄漏和 GPU 内存泄漏等故障信息。端侧集成后,开发者仍需在云端平台注册认证并创建任务;平台根据时间、故障类别和圈选策略选出少量设备。设备收到任务、处于激活时间、应用运行且触发相应故障,才可能产生对应上报。端侧参与状态为 true,不等于本设备已经被选中,更不等于云端已有报告。

这个能力有成本。官方提醒增强采集会降低性能并增加功耗,所以不应该拿它当全量常开的埋点。应用隐私声明也需要包含 Performance Analysis Kit 的个人数据处理说明。上线前先核对云端权限、活动范围和隐私文案,不能只贴一段 API 调用代码就当接入完成。

案例一:先调用 participate,再 init,为什么报 36000001

init() 是初始化模块;participate(config) 表示本设备参与灰度活动。官方列出的错误码 36000001 对应初始化顺序问题。下面把两个动作收进一个入口,并且在任一步失败时停止后续调用。userType、deviceType、deviceModel 由项目按实际分类填写,不能把示例值当成真实用户或设备信息。

import { BusinessError } from '@kit.BasicServicesKit';
import { hiRetrieval } from '@kit.PerformanceAnalysisKit';

function joinGrayscale(): boolean {
  const config: hiRetrieval.HiRetrievalConfig = {
    userType: 'internal-test',
    deviceType: 'phone',
    deviceModel: 'test-cohort'
  };
  try {
    hiRetrieval.init();
    hiRetrieval.participate(config);
    return hiRetrieval.isParticipant();
  } catch (err) {
    const e = err as BusinessError;
    console.error(`hiRetrieval failed: ${e.code}, ${e.message}`);
    return false;
  }
}

这个函数返回 true 只说明端侧自查处于参与状态,不说明云端圈选成功。对照复现可以把 participate(config) 临时移到 init() 前面,观察错误码;确认后恢复正确顺序。真正投产时不要为了“复现错误”在用户设备上反复调用,以免产生不必要的端云状态变更。

另外别把所有错误都归为“没有初始化”:官方给 init() 列出的 36000002 是多实例应用不支持。若该错误出现在初始化阶段,调整调用顺序并不能解决,先检查应用是否运行在多实例形态;只有 participate() 报 36000001 才优先看初始化链。错误码和触发 API 要一起记录。

案例二:参与了也调用 run,为什么云端还是空的

官方定义 run() 为:设备正在参与灰度活动时运行模块;未参与时调用不生效。但参与也只是必要条件之一。排查链应按“本地参与状态 → 云端任务是否存在 → 本设备是否被圈选 → 任务是否在有效期 → 应用运行时是否触发指定故障 → 平台上报状态”逐段检查,不要只盯 run() 返回。

import { BusinessError } from '@kit.BasicServicesKit';
import { hiRetrieval } from '@kit.PerformanceAnalysisKit';

function runIfJoined(): void {
  try {
    hiRetrieval.init();
    if (!hiRetrieval.isParticipant()) {
      console.info('Device has not joined an application grayscale activity.');
      return;
    }
    const config = hiRetrieval.getCurrentConfig();
    const joinedAt = hiRetrieval.getLastParticipationTimestamp();
    console.info(`Joined at ${joinedAt}; type ${config.userType}`);
    hiRetrieval.run();
  } catch (err) {
    const e = err as BusinessError;
    console.error(`Grayscale run failed: ${e.code}, ${e.message}`);
  }
}

getLastParticipationTimestamp() 返回的是上次参与的 Unix 毫秒时间戳;若从未参与,官方说明返回 0。它能帮助查“端侧究竟有没有参与过”,却不能证明当前存在活跃云端任务。getCurrentConfig() 用于核对当前端侧配置,也不能代替云端圈选结果。两者都不要作为“日志已到云端”的成功标志。

实际排查可留一张证据表,而不是只看一个返回值:端侧记录 isParticipant、上次参与时间和配置;云端核对任务 ID、故障类别、圈选结果和生效时间;最后对照受控设备发生的故障时间与平台报告。没有云端任务或设备未被选中时,不应为了“产生日志”在普通用户设备上故意制造 OOM。

如果用户退出测试范围或灰度结束,可以在初始化后调用 hiRetrieval.quit();官方定义为退出活动,退出后设备不再参与云端圈选。不要把 quit() 写成“立即删除既有云端日志”,文档没有这样的承诺。退出后再用 isParticipant() 自查本地状态,同时在云端核对任务范围。

怎样验证,不要用一次布尔值糊弄过去

我把本地能验证和必须端云联动的证据分开:

检查点可观察结果不能据此推断
未初始化先参与捕获 36000001业务网络一定故障
isParticipant() 为 true本设备处于参与状态已被云端圈选或已上传日志
getLastParticipationTimestamp() 非 0曾经参与过当前任务仍有效
run() 调用结束端侧执行入口被调用指定故障已经发生
云端任务报告出现平台收到相应任务数据所有设备都被采集

本地无 API 26 环境时,可以先把判断逻辑抽成一个小函数并用假状态验证:

export function joinAndRun(client, config) {
  client.init();
  client.participate(config);
  if (!client.isParticipant()) return { ran: false, reason: 'not-participant' };
  client.run();
  return { ran: true, reason: 'participant' };
}

用 node --test 给这个纯逻辑模型做了六组本地检查:初始化先于参与;未参与时不调用 run;初始化抛错后不执行后续步骤;模拟 36000002 和 36000001 分别中断于不同环节;再用七种假状态逐段选择下一个应核对的证据。这里的错误码是测试替身主动抛出的,不是设备实测。模型没有导入 HarmonyOS SDK,它只验证我们自己的调用顺序和排查分支,不能代替 SDK 编译、设备圈选或云端报告。要完成端到端验收,应在受控测试设备上创建限定时间与故障类别的任务,记录设备选择结果和上报报告,再比较任务前后的功耗与性能影响。

本地模型输入下一步核对不能直接得出的结论
participant=false端侧初始化与参与调用云端任务是否有故障
已参与,taskExists=false云端任务配置与时间范围设备已被圈选
有任务,selected=false圈选规则与设备范围run() 失效
已圈选,withinWindow=false任务激活时间故障类型正确
时间匹配,faultMatches=false故障类别与实际事件上报失败
故障匹配,reportVisible=false平台接收和报告状态一定是客户端未运行

这张表只是排查顺序,taskExists/selected 等字段需要从平台真实任务取得;文章没有提供读取这些状态的端侧 API,也没有伪造一份云端报告。

什么时候该用、什么时候别用

已经能用常规日志和故障分析定位的普通问题,不必上灰度采集。它适合线上少数设备、复现率低、常规采样信息不足的内存与稳定性故障。先提出明确的故障类型与观察窗口,再设定最小圈选范围;任务结束后退出或收束范围。这样得到的报告才有上下文,也不会把用户设备长期当成调试环境。

本文代码只覆盖官方 API 的端侧入口,未包含云端注册、圈选任务创建和真实故障触发。**本机未安装 API 26.0.0 SDK,未做真机运行或云端采集验证。**实际项目接入时应在 DevEco Studio API 26.0.0 工程中编译、在支持设备上运行,并核对隐私声明与平台任务结果。

参考:华为开发者《应用灰度采集介绍》:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hiretrieval-intro ;hiRetrieval API 参考: https://developer.huawei.com/consumer/en/doc/harmonyos-references/js-apis-hiretrieval 。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐