hm-metricx-cj
功能简介
hm-metricx-cj 是一款适用于鸿蒙应用的线上性能监控框架。 hm-metricx-cj 系统性地采集和分析监控指标数据,帮助开发团队及时发现性能瓶颈和异常,持续优化应用质量,提升用户体验。
hm-metricx-cj 目前支持的监控范围包括:Crash、Freeze、异常退出原因、FPS、滑动掉帧率、交互响应延迟、内存、CPU、热量,电量、流量、存储。
使用说明
集成方式
i.
获取 hm-metricx-cj 源码。
ii.
在 DevEco Studio 中点击 Build -> Make module 'hm-metricx-cj' 编译生成har包 hm_metricx_cj.har 。har包产物路径在 hm_metricx_cj/build/default/outputs/default 目录下。
iii.
将 hm_metricx_cj.har 放到工程模块的har目录下。在工程模块的 oh-package.json5 中配置依赖 "hm_metricx_cj": "file:./har/hm_mtricx_cj.har" 。
并且在工程模块的 src/main/cangjie/cjpm.toml 中配置依赖:
[dependencies]
[dependencies.ohos_app_cangjie_hm_metricx_cj]
path = "../../../oh_modules/hm_metricx_cj/src/main/cangjie"
按需打包
如需使用按需打包功能,请修改以下目录中的 hvigorfile.ts 文件第 9-11 行配置:
hm-metricx-cj/
└── ApmApplication/
└── hm_metricx_cj/
└── hvigorfile.ts
const INCLUDE_FEATURES: string[] = [
'thermal', 'traffic', 'battery',
];
INCLUDE_FEATURES 中填写需要保留的功能项即可,最终打包结果将按该配置生效。
监控Crash
hm_metricx_cj 提供
public func initCrashHandler(
applicationContext: common.ApplicationContext, -- 上下文
persistentDir: Path, --自定义存入地址
callbacks:CrashCallbacks, -- 回调类
config!: CrashConfig = CrashConfig() -- 配置类
): Unit
public class CMemMonitorConfig {
let shouldBeClusteredToThisSo: (soName: String) -> Bool
public init(shouldBeClusteredToThisSo: (soName: String) -> Bool){
this.shouldBeClusteredToThisSo = shouldBeClusteredToThisSo
}
}
接口对ArkTS/仓颉/Native层引发的崩溃进行监控。
initCrashHandler 需要的入参说明如下:
applicationContext: ApplicationContext指定应用上下文。persistentDir: Path指定中间日志文件和内存快照的持久化目录。callbacks:CrashCallbacks 回调类入参,里面包括:
-
collectCrashInfo: () -> JsonValue
用于在发生 ArkTS / 仓颉层引发的 crash 时,收集若干自定义的业务 / 系统信息,例如页面浏览路径等,并以 JSON 形式返回。 -
reportCrashInfo: (crashInfo: CrashInfo) -> Unit
用于在发生 ArkTS / 仓颉层引发的 crash 时,将收集完毕的崩溃信息进行上报,入参为CrashInfo类型对象。
crashconfig!: CrashConfig = CrashConfig():配置类入参,里面包括:
lastNHilogNumber: Int64指定lastNHilog的条数。systemLogNumber: Int64指定系统级日志systemLog的条数。memMonitor: Option<CMemMonitorConfig>指定是否开启C内存详情监控,Option.None表示不开启,传入CMemMonitorConfig对象表示开启,CMemMonitorConfig类表示C内存详情监控的配置项。
CMemMonitorConfig 参数说明:
shouldBeClusteredToThisSo用于在按照so聚合类别中,指定内存分配数据是否被聚合到该so。
CrashInfo 包含以下信息:
language崩溃发生所处的语言层meminfo崩溃发生时的应用内存信息timestamp崩溃发生的时间戳pid崩溃进程IDpname崩溃进程名stacktrace崩溃调用栈hilogHilog日志tid崩溃线程IDtname崩溃线程名fdsFD及其对应路径limits进程资源限制threadsOS线程ID与线程名extraInfocollectCrashInfo/reportNativeCrashInfo收集的自定义的业务/系统信息crashLogPath系统生成的faultlog文件路径dumpOnOOMPath导出的仓颉内存快照地址appVersion应用版本rawFile系统生成的faultlog文件的原始内容systemLog系统级日志lastNHilog最新的N条hilog日志dumpTime导出仓颉内存快照的时间historyRawFiles所有历史系统生成的crash日志文件的内容nativeMemDetailC层内存详情memPersistTimeC层内存详情持久化时间
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initCrashHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initCrashHandler(this
.context
.getApplicationContext(),
Path(this
.context
.cacheDir),
CrashCallbacks(collectCrashInfo: {=> JsonValue.fromStr("{}")}, reportCrashInfo: {data => AppLog.error("xxx: " + data.toString())}),
config: CrashConfig(memMonitor: CMemMonitorConfig({soName:String =>false}), lastNHilogNumber: 1000, systemLogNumber: 1000))
** 注意: **
对ArkTS/仓颉层引发的崩溃的监控依赖系统提供的ErrorManager机制。
当存在其他ErrorManager回调,并且在崩溃监控对应的回调之前执行时,可能会干扰崩溃监控的正常行为,导致收集的数据错漏等情况。
** 注意: **
如果应用编译开启了
O2级别优化,在部分场景,崩溃调用栈会出现漏栈、行号不准的问题。示例如下:func pri(n: Int64): Unit { if (n < 0) { return; } if (n == 90) { throw Exception("e"); } pri(n - 1); } main(): Unit { pri(1000); }由于内联优化和基础块合并优化的影响,抛出异常点的行号信息为0,并且调用栈长度会少于程序实际递归次数。 ** 注意: ** ArkTS 内存监控通过
hidebug.setAppResourceLimit设置应用内存资源阈值,用于在应用发生内存泄漏并达到阈值条件时触发系统资源泄漏日志。 该能力存在以下使用约束:
- 需在设备“开发者选项”中开启“系统资源泄漏日志”开关,且开关状态变更后需重启设备后生效。
- 系统对同一应用的资源泄漏事件存在频控限制,同一应用在 24 小时内最多上报一次。
- 若需要在短时间内重复验证资源泄漏事件上报,需要重启设备后重新触发测试。
监控Freeze
hm_metricx_cj 提供
public func initFreezeHandler(
applicationContext: ApplicationContext,
collectFreezeInfo: () -> JsonValue,
reportFreezeInfo: (freezeInfo: FreezeInfo) -> Unit,
persistentDir: Path
): Unit
接口对freeze事件进行监控。
initFreezeHandler 需要的入参说明如下:
applicationContext: ApplicationContext指定应用上下文。collectFreezeInfo: () -> JsonValue用于在APP发生freeze事件时,收集若干自定义的业务/系统信息(比如页面操作栈等),以JsonValue形式返回。reportFreezeInfo: (freezeInfo: FreezeInfo) -> Unit用于在APP发生freeze事件时,将收集完成的freeze信息进行上报,入参为FreezeInfo类型对象。persistentDir: Path指定中间日志文件的持久化目录。
FreezeInfo 包含以下信息:
timestampfreeze发生的时间戳pidfreeze进程名exceptionfreeze发生原因hilogHilog日志tidfreeze线程IDtnamefreeze线程名exrtaInfo收集的自定义的业务/系统信息freezeLogPath系统生成的faultlog文件路径cpuThread线程CPU使用率cpu进程CPU使用率stacktracefreeze调用栈rawFile系统生成的faultlog文件的原始内容historyRawFiles所有历史系统生成的freeze日志文件的内容
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initFreezeHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initFreezeHandler(this.context.getApplicationContext(), {=> JsonValue.fromStr("{}")}, {data =>}, Path(this.context.cacheDir))
}
}
** 注意: **
和监控Crash类似,如果应用编译开启了
O2级别优化,在部分场景,freeze调用栈会出现漏栈、行号不准的问题。
监控系统强杀
hm_metricx_cj 提供
1. 系统强杀
public func initExitInfoHandler(
lastExitMessage: String,
lastExitReason: Int32,
reportExitInfoHandler: (ExitInfo) -> Unit,
reportAppStateHandler: (AppStateInfo) -> Unit
): Unit
接口对系统强杀监控进行类型分类。
initExitInfoHandler 需要的入参说明如下:
-
`launchParam:应用本次启动时系统传入的启动参数
-
exitReason上次应用退出的原因,分类如下:ability_not_respondingAbility未响应app_freeze应用无响应cpp_crashNative层发出异常信号导致应用退出js_errorJS层Error导致应用退出unknown上次应用退出原因未被应用框架记录normal正常退出,如用户主动关闭应用performance_control系统能耗管控导致应用退出,如设备低内存resource_control资源管控导致应用退出,如过量使用CPU/IO/内存资源upgrade应用升级导致应用退出
-
exitMessage上次应用退出的详细信息
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initThermalHandler:
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initExitInfoHandler(
this.context,
launchParam,
{ data: ExitInfo =>
AppLog.error("[MetricX][ExitInfo] ${data.toString()}")
},
{ data: AppStateInfo =>
AppLog.error("[MetricX][AppState] ${data.toString()}")
},
Path(this.context.cacheDir)
)
match (launchParam.launchReason) {
case AbilityConstant
.LaunchReason
.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
}
}
2. 用户滑杀
public func initSwipeKillHandler(
context: UIAbilityContext,
launchParam: LaunchParam,
reportInfo: (info: SwipeKillInfo) -> Unit,
thresholdMs!: Int64 = DEFAULT_SWIPE_KILL_THRESHOLD_MS
)
接口对用户滑杀监控。
initSwipeKillHandler 需要的入参说明如下:
- `context: UIAbilityContext - UI能力上下文
- `launchParam:应用本次启动时系统传入的启动参数
- `reportInfo: (SwipeKillInfo) -> Unit - 滑动杀死信息回调函数
timestamp事件发生的时间戳isUserSwipeKill是否为用户滑动杀死exitInfo上次退出原因(同exitReason)
- `Threshold: 判断滑动杀死的阈值(毫秒),默认5000ms
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initThermalHandler:
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initSwipeKillHandler(
this.context,
launchParam,
{ info: SwipeKillInfo =>
AppLog.warn("[MetricX] SwipeKill: User killed app and restarted quickly! timeSinceBg: ${info.toString()}")
},
thresholdMs: 5000
)
}
}
监控热量
hm_metricx_cj 提供
public func initThermalHandler(
context: UIAbilityContext,
reportThermalInfo: (info: ThermalEventInfo) -> Unit,
sampleInterval!: Int64 = DEFAULT_SAMPLE_INTERVAL_MS,
reportMinInterval!: Int64 = DEFAULT_REPORT_MIN_INTERVAL_MS,
abnormalThreshold!: Int32 = DEFAULT_ABNORMAL_LEVEL
): Unit
接口对电池热量异常事件进行监控。
initThermalHandler 需要的入参说明如下:
applicationContext: ApplicationContext指定应用上下文。creportThermalInfo: (info: ThermalEventInfo) -> Unit用于在APP发生异常发热事件时,收集若干自定义的业务/系统信息,以JsonValue形式返回。sampleInterval!: Int64 = DEFAULT_SAMPLE_INTERVAL_MS用于热量监控sample采用频率(ms)。reportMinInterval!: Int64 = DEFAULT_REPORT_MIN_INTERVAL_MS用于热量监控异常上报频率(ms)。abnormalThreshold!: Int32 = DEFAULT_ABNORMAL_LEVEL指定异常的阈值。
ThermalEventInfo 包含以下信息:
pageName热量异常时发生的当前页面level当前热量异常的系统热level值levelName当前热量异常的系统热level值对应的状态threshold所指定异常的阈值isForeground是否在前台durationMs异常持续时长
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initThermalHandler:
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initThermalHandler(
context,
{ info: ThermalEventInfo =>
AppLog.error("[MetricX][Thermal] ${info.toString()}")
},
abnormalThreshold: 2
)
match (launchParam.launchReason) {
case AbilityConstant
.LaunchReason
.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
}
}
监控FPS/滑动掉帧率
hm_metricx_cj 提供
public func initPageEventHandler(
uiContext: UIAbilityContext,
reportFpsInfo: (fpsInfo: FpsEventInfo) -> Unit
): Unit
public func initPageEventHandler(
windowStage: WindowStage,
reportFpsInfo: (fpsInfo: FpsEventInfo) -> Unit
): Unit
public func initScrollEventHandler(
uiContext: UIAbilityContext,
reportScrollInfo: (scrollInfo: ScrollHitchInfo) -> Unit
): Unit
接口对FPS/滑动掉帧率进行监控。
initPageEventHandler 需要的入参说明如下:
uiContext: UIAbilityContext指定UIAbility上下文reportFpsInfo: (fpsInfo: FpsEventInfo) -> Unit用于每次页面退出时,将统计到的FPS信息进行上报,入参为FpsEventInfo类型对象
FpsEventInfo 包含以下信息:
minFps一段时间内,每隔一秒采样,测量到的最低帧率值avgFps一段时间内,测量到的平均帧率值pageName所在页面名称
initPageEventHandler 需要的入参说明如下:
windowStage: WindowStage指定WindowStagereportFpsInfo: (fpsInfo: FpsEventInfo) -> Unit用于每次进入后台时,将统计到的FPS信息进行上报,入参为FpsEventInfo类型对象
initScrollEventHandler 需要的入参说明如下:
uiContext: UIAbilityContext指定UIAbility上下文reportScrollInfo: (scrollInfo: ScrollHitchInfo) -> Unit用于每次滑动事件停止时,将统计到的滑动掉帧率信息,以及FPS信息进行上报,入参为ScrollHitchInfo类型对象。
ScrollHitchInfo 继承 FpsEventInfo 的所有信息,并包含以下信息:
frameDropRatio滑动掉帧率jankRate卡顿率bigJankRate严重卡顿率htLessThan0延迟小于0的帧数比例ht0To00001延迟在0到0.0001秒之间的帧数比例ht00001To0001延迟在0.0001到0.001秒之间的帧数比例ht0001To001延迟在0.001到0.01秒之间的帧数比例ht001To005延迟在0.01到0.05秒之间的帧数比例ht005To01延迟在0.05到0.1秒之间的帧数比例ht01To1延迟在0.1到1秒之间的帧数比例htBiggerThan1延迟大于1秒的帧数比例targetFPS目标帧率longestLostFrame最长丢失的帧时间totalFrameCount总帧数
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initPageEventHandler 和 initScrollEventHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initScrollEventHandler({data =>})
}
}
ii.
在主模块的 main_ability.cj 的 onWindowStageCreate 回调中调用 initPageEventHandler :
class EntryAbility <: UIAbility {
public override func onWindowStageCreate(windowStage: window.WindowStage): Unit {
windowStage.loadContent("pages/index", {err, data => ()})
initPageEventHandler(windowStage, {data =>})
windowStage.getMainWindow(
{
err, data => match(data) {
case Some(x) => initPageEventHandler(this.context, {data =>})
case None => AppLog.info("initPageEventHandler error)
}
}
)
}
}
监控交互响应延迟
hm_metricx_cj 提供
1. 延迟监控
public func initLaggyHandle(applicationcontext: ApplicationContext, uiContext: UIContext,
maxTime: Int64, maxArraySize: Int64,
reportLaggyInfo: (data: JsonObject) -> Unit)
接口对交互式响应延迟提供监控能力。
initLaggyHandle 需要的入参说明如下:
-
applicationcontext指定应用上下文。 -
uiContext指定uiContext。 -
maxTime指定最大的响应时间,超过该时间视为一次卡顿事件。 -
maxArraySize指定存储最大的卡顿时间集合,当卡顿次数超过该值时,会删除最早的一次卡顿数据。 -
reportLaggyInfo上报数据的回调函数,入参为JsonObject类型对象,该对象包含以下字段:pageName当前页面名称technologyStack技术栈responseTime响应时间,单位:msdescriptionID响应组件的结构信息nodeType响应组件类型viewTouchID响应组件IDtouchX点击位置相对于应用窗口左上角的X坐标,单位:pxtouchY点击位置相对于应用窗口左上角的Y坐标,单位:pxhitX响应组件相对于应用窗口的X轴偏移,单位: pxhitY响应组件相对于应用窗口的Y轴偏移,单位: pxhitWidth响应组件大小的宽度,单位: vphitHeight响应组件大小的高度,单位: vp
使用示例:
i.
在主模块的 main_ability.cj 的 onWindowStageCreate 回调中调用 initLaggyHandler :
public func onWindowStageCreate(windowStage: window.WindowStage): Unit {
windowStage.loadContent("pages/index", {err, data => ()})
windowStage.getMainWindow(
{
err: ?BusinessException, data: ?window.Window => match (data) {
case Some(x) => initLaggyHandler(this.context.getApplicationContext(),
fromUIContextBase(x.getUIContext()), 10, 10, {data =>})
case None => AppLog.info("initLaggyHandler error")
}
})
}
2. 白屏检查
public func initWhiteScreenHandler(
context: UIAbilityContext,
windowStage: WindowStage,
uiContext: UIContext,
config: WhiteScreenConfig,
reportWhiteScreenInfo: (data: JsonObject) -> Unit
)
接口对App白屏提供监控能力。
initWhiteScreenHandler 需要的入参说明如下:
-
context指定应用上下文,用于注册Ability生命周期回调。 -
windowStage指定窗口舞台,用于获取主窗口进行截图。 -
uiContext指定uiContext。 -
config指定白屏检测配置项,其中包括:
| 字段 | 类型 | 默认值 | 含义 | 约束 |
|---|---|---|---|---|
rootComponentId |
String | None | 根组件ID,用于组件截图 | 可选 |
ttidTimeoutMs |
Int64 | 1000 | 首帧超时时间(ms),超时判定TIMEOUT白屏 | >= 0 |
frameCheckDurationMs |
Int64 | 3000 | 首帧后帧检测持续时间(ms) | >= 0 |
backgroundFirstSnapshotDelayMs |
Int64 | 800 | 后台首次截图延迟(ms) | >= 0 |
backgroundSecondSnapshotDelayMs |
Int64 | 1800 | 后台第二次截图延迟(ms) | >= 0 |
backgroundRecentPageEnterThresholdMs |
Int64 | 3000 | 后台检测页面进入阈值(ms) | >= 0 |
minFrameCountThreshold |
Int64 | 30 | 帧数阈值,低于此值触发截图分析 | >= 0 |
maxDistinctColorCount |
Int64 | 2 | 颜色复杂度阈值,颜色种类少于等于此值判白屏 | >= 0 |
whiteRgbThreshold |
Int64 | 245 | 白色RGB阈值,RGB均>=此值认为主色接近白色 | >= 0 |
snapshotScale |
Float64 | 0.1 | 截图缩放比例 | [0.0, 1.0] |
snapshotRegionTop |
Float64 | 0.08 | 截图区域顶部裁剪比例 | [0.0, 1.0] |
snapshotRegionBottom |
Float64 | 0.08 | 截图区域底部裁剪比例 | [0.0, 1.0] |
autoWriteFaultLog |
Bool | true | 是否自动写入故障日志 | - |
reportWhiteScreenInfo指定白屏事件上报回调函数,入参为JsonObject类型对象,该对象包含以下字段:pageName当前页面名称whiteScreenType白屏类型原因whiteScreenScene白屏检测场景:PAGE_OPEN(页面打开) /PAGE_BACKGROUND(前台切后台)appState白屏检测时应用状态:FOREGROUND/BACKGROUND
使用示例:
i.
在主模块的 main_ability.cj 的 onWindowStageCreate 回调中调用 initWhiteScreenHandler :
public func onWindowStageCreate(windowStage: window.WindowStage): Unit {
windowStage.loadContent("pages/index", {err, data => ()})
windowStage.getMainWindow(
{
let whiteScreenConfig = WhiteScreenConfig()
initWhiteScreenHandler(
this.context,
windowStage,
fromUIContextBase(x.getUIContext()),
whiteScreenConfig,
{ data: JsonObject =>
AppLog.error("[MetricX][WhiteScreen][TestBench] " + data.toString())
}
)
})
}
3. 首帧渲染
public func initFirstRenderTimeMonitor(
config: FirstRenderTimeConfig,
reportCallback: (FirstRenderTimeInfo) -> Unit
): Unit
接口提供App首帧渲染监控能力。
initFirstRenderTimeMonitor 需要的入参说明如下:
config指指定首帧渲染检测配置项,其中包括:enableLogging控制是否启用日志记录功能,默认值为 truereportThreshold上报的时间
reportCallback 指定首帧渲染事件上报回调函数,该对象包含以下字段:
startTime: Int64 - 开始时间endTime: Int64 - 结束时间duration: Int64 - 持续时间targetPage: String - 目标页面
使用示例:
i.
在主模块的 main_ability.cj 的 onWindowStageCreate 回调中调用 initFirstRenderTimeMonitor :
public func onWindowStageCreate(windowStage: window.WindowStage): Unit {
windowStage.loadContent("pages/index", {err, data => ()})
windowStage.getMainWindow(
{
initFirstRenderTimeMonitor(
FirstRenderTimeConfig(true, 1000),
{ info =>
AppLog.info("[FRT] ${info.toString()}")
}
)
})
}
监控内存
hm_metricx_cj 提供
// 注册内存监控
public func initMemoryHandler(
context: UIAbilityContext,
reportPageMemoryInfo: (info: PageMemoryInfo) -> Unit,
reportProcessMemoryInfo: (info: ProcessMemoryInfo) -> Unit,
memoryThreshold!: Int64 = 100*1024
): Unit
// 取消内存监控
public func destroyMemoryHandler(): Unit
// 获取页面内存信息
public func getPageMemoryInfo(): PageMemoryInfo
// 获取进程内存信息
public func getProcessMemoryInfo(): ProcessMemoryInfo
接口对应用的内存使用情况进行监控。
initMemoryHandler 需要的入参说明如下:
context: UIAbilityContext指定UIAbility上下文。reportPageMemoryInfo: (info: PageMemoryInfo) -> Unit将当前页面内存的使用情况进行上报,入参为PageMemoryInfo类型对象。reportProcessMemoryInfo: (info: ProcessMemoryInfo) -> Unit将进程内存的使用情况进行上报,入参为ProcessMemoryInfo类型对象。memoryThreshold!: Int64内存使用阈值,默认为100 * 1024 KB。当使用内存超过该阈值时,将内存使用情况上报。sampleInterval!: Int64内存采样时间,单位为秒,默认为30秒。
PageMemoryInfo 包含以下信息:
avgMemory内存使用平均值,单位为KBmaxMemory内存使用最大值,单位为KBavgCJMemory仓颉堆已被使用的平均值,单位为 byte。maxCJMemory仓颉堆已被使用的最大值,单位为 byte。sampleCount内存采样次数pageName当前页面名称
ProcessMemoryInfo 包含以下信息:
avgMemory内存使用平均值,单位为KBmaxMemory内存使用最大值,单位为KBavgCJMemory仓颉堆已被使用的平均值,单位为 byte。maxCJMemory仓颉堆已被使用的最大值,单位为 byte。sampleCount内存采样次数pid进程ID
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initMemoryHandler
ii.
在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyMemoryHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initMemoryHandler(this.context, {data =>}, {data =>})
}
public override func onDestroy(): Unit {
destroyMemoryHandler()
AppLog.info("myAbility onDestroy.")
}
}
监控CPU
hm_metricx_cj 提供
// 注册CPU监控
public func initCpuHandler(
ability: UIAbility,
reportPageCpuInfo: (info: PageCpuInfo) -> Unit,
reportProcessCpuInfo: (info: ProcessCpuInfo) -> Unit
): Unit
// 取消CPU监控
public func destroyCpuHandler(): Unit
// 获取页面CPU信息
public func getPageCpuInfo(): PageCpuInfo
// 获取进程CPU信息
public func getProcessCpuInfo(): ProcessCpuInfo
接口对应用的CPU使用情况进行监控。
initCpuHandler 需要的入参说明如下:
context: UIAbilityContext指定UIAbility上下文。reportPageCpuInfo: (info: PageCpuInfo) -> Unit将当前页面的CPU的使用情况进行上报,入参为PageCpuInfo类型对象。reportProcessCpuInfo: (info: ProcessCpuInfo) -> Unit将进程的CPU的使用情况进行上报,入参为ProcessCpuInfo类型对象。
PageCpuInfo 包含以下信息:
avgCpuCPU使用率平均值,以比例值表示(如使用率50%,则返回0.5)maxCpuCPU使用率最大值,以比例值表示sampleCountCPU采样次数pageName当前页面名称
ProcessCpuInfo 包含以下信息:
avgCpuCPU使用率平均值,以比例值表示(如使用率50%,则返回0.5)maxCpuCPU使用率最大值,以比例值表示sampleCountCPU采样次数pid进程ID 使用示例:
i.在主模块的 main_ability.cj 的 onCreate 回调中调用 initCpuHandler
ii.在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyCpuHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initCpuHandler(this.context, {data =>}, {data =>})
}
public override func onDestroy(): Unit {
destroyCpuHandler()
AppLog.info("myAbility onDestroy.")
}
}
新增CPU异常监控 : 1)3分钟线程栈异常监控
//注册CPU异常监控
public func initHighCpuMonitorHandler(
context: UIAbilityContext,
config: HighCpuMonitorConfig,
reportHighCpuInfo: (info: HighCpuReportInfo) -> Unit
): unit
// 取消CPU监控
public func destroyHighCpuMonitorHandler(): Unit
// 获取页面CPU信息
public func HighCpuMonitorConfig(): PageCpuInfo
// 获取进程CPU信息
public func reportHighCpuInfo(): ProcessCpuInfo
接口对应用的CPU使用情况进行监控。
initHighCpuMonitorHandler 需要的入参说明如下:
context: UIAbilityContext指定UIAbility上下文。config: HighCpuMonitorConfig将当前页面的CPU的使用入参为HighCpuMonitorConfig类型对象。reportHighCpuInfo: (info: HighCpuReportInfo) -> Unit回调配置,将进程的CPU的异常使用情况进行上报。
HighCpuMonitorConfig 的入参包含信息:
cpuThresholdCPU使用率平均值,以比例值表示(如使用率50%,则返回0.5),范围是0-1,如果是负数或者超过1,会调用系统设置的默认值foregroundIntervalMs前台采样频率(ms,如果1s则设置为1000),如果是负数,会调用系统设置的默认值backgroundIntervalMsleCount后台采样频率(ms,如果1s则设置为1000),如果是负数,会调用系统设置的默认值monitorDurationMS异常上报频率(ms,如果1s则设置为1000),如果是负数,会调用系统设置的默认值threadCoolDownMs安全限流设置(ms,如果1s则设置为1000),如果是负数,会调用系统设置的默认值,针对本模块内的冷却限限流,假如时间是60s,在threadCoolDownMs时间内,如果有异常汇报过同线程,这个threadCoolDownMs会开启,在这个冷却时间内,不会重复上报已有的异常信息。globalCooldownMs安全限流设置(ms,如果1s则设置为1000),如果是负数,会调用系统设置的默认值,针对全局APM的冷却限限流,假如时间是180s,在globalCooldownMs时间内,如果有异常汇报过同线程,这个globalCooldownMs会开启,在这个冷却时间内,不会重复上报已有的异常信息。highSampleRatioThreshold高采样比例阈值,在3分钟内所有采样个数内,需要保证整体采样sample异常比例超过设定阈值,且CPU使用率平均值大于cpuThreshold,最后异常事件才会上报,范围是0-1,如果是负数或者超过1,会调用系统设置的默认值topNthreads每次采用异常线程数,0 - 200,如果在范围外,会调用系统设置的默认值
HighCpuReportInfo 包含以下信息:
timestamptimestampprocessName进程pid进程IDpageName当前页面avgProcessCpuCPU平均值montorDuration监控时长highCpuThreads.length高占用线程数
HighCpuThreads 包含以下信息:
tid进程TIDthreadName异常线程名avgCpuUsage平均CPUmaxCpuUsage最大CPUsampleCount采样次数hightSampleCount/sampleCount高采样比例moduleBane模块名firstDetectedTime首次检测时间
使用示例:
i.在主模块的 main_ability.cj 的 onCreate 回调中调用 initCpuHandler
ii.在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyCpuHandler :
initHighCpuMonitorHandler(
this.context,
HighCpuMonitorConfig(
cpuThreshold: 0.05,
foregroundIntervalMs: 1000,
backgroundIntervalMs: 2000,
monitorDurationMs: 330000,
threadCooldownMs: 60000,
globalCooldownMs: 3000,
highSampleRatioThreshold: 0.85,
topNThreads: 10
),
{ reportInfo =>
AppLog.warn("===== 高 CPU 占用上报 =====")
AppLog.warn("时间:${reportInfo.timestamp}")
AppLog.warn("进程:${reportInfo.processName} (PID: ${reportInfo.pid})")
AppLog.warn("页面:${reportInfo.pageName}")
AppLog.warn("进程平均 CPU: ${reportInfo.avgProcessCpu}")
AppLog.warn("监控时长:${reportInfo.monitorDuration}毫秒")
AppLog.warn("高占用线程数:${reportInfo.highCpuThreads.size}")
for (threadInfo in reportInfo.highCpuThreads) {
AppLog.warn("--- 线程信息 ---")
AppLog.warn(" TID: ${threadInfo.tid}")
AppLog.warn(" 线程名:${threadInfo.threadName}")
AppLog.warn(" 平均 CPU: ${threadInfo.avgCpuUsage}")
AppLog.warn(" 最大 CPU: ${threadInfo.maxCpuUsage}")
AppLog.warn(" 采样次数:${threadInfo.sampleCount}")
AppLog.warn(" 高采样比例:${threadInfo.getHighSampleRatio()}")
}
}
);
新增CPU异常监控 : 2)CPU后台活动率异常监控
//注册CPU异常监控
public func initBackgroundCpuMonitorHandler(
context: UIAbilityContext,
config: BackgroundCpuMonitorConfig,
reportCallback: (info: BackgroundCpuReportInfo) -> Unit
): unit
// 取消CPU监控
public func destroyBackgroundCpuMonitorHandler(): Unit
// 手动触发后台 CPU 上报
public func triggerBackgroundCpuReport(): Unit
// 检查后台监控是否正在运行
public func isBackgroundCpuMonitoringActive(): Bool
//获取后台监控配置
public func getBackgroundCpuConfig(): Option<BackgroundCpuMonitorConfig>
接口对应用的CPU使用情况进行监控。
initBackgroundCpuMonitorHandler 需要的入参说明如下:
context: UIAbilityContext指定UIAbility上下文。config: BackgroundCpuMonitorConfig将当前页面的CPU的使用入参为BackgroundCpuMonitorConfig类型对象。reportCallback: (info: BackgroundCpuReportInfo) -> Unit回调配置,将进程的CPU的异常使用情况进行上报。
BackgroundCpuMonitorConfig 的入参包含信息:
cpuThresholdCPU使用率平均值,以比例值表示(如使用率50%,则返回0.5),范围是0-1,如果是负数或者超过1,会调用系统设置的默认值warnDurationMs: (int64) 最小异常上报时长(ms),超过此时长触发warn级别上报。errorDurationMs: (int64) 最小异常上报时长(ms),超过此时长触发error级别上报。errorDurationMs: (int64) 最小异常上报时长(ms),超过此时长触发fatal级别上报。sampleIntervalMs: (int64) 采样间隔(ms)。windowSizeMs: (int64) 滑动窗口大小(ms)。
BackgroundCpuReportInfo 包含以下信息:
timestamptimestampprocessName进程pid进程IDlevel当前异常等级pageName当前页面avgProcessCpuCPU平均值backgroundDuration监控时长windowSamples.size滑动窗口采样数
使用示例:
i.在主模块的 main_ability.cj 的 onCreate 回调中调用 initCpuHandler
ii.在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyCpuHandler :
initBackgroundCpuMonitorHandler(
this.context,
BackgroundCpuMonitorConfig(
cpuThreshold: 0.05, // CPU 利用率阈值 5%
warnDurationMs: 10000, // 10 秒触发 WARN 级别
errorDurationMs: 30000, // 30 秒触发 ERROR 级别
fatalDurationMs: 60000, // 60 秒触发 FATAL 级别
sampleIntervalMs: 1000, // 1 秒采样一次
windowSizeMs: 5000 // 5 秒滑动窗口
),
{ reportInfo =>
AppLog.warn("===== 后台 CPU 活动超长率上报 =====")
AppLog.warn("时间:${reportInfo.timestamp}")
AppLog.warn("进程:${reportInfo.processName} (PID: ${reportInfo.pid})")
AppLog.warn("异常级别:${reportInfo.level.toString()}")
AppLog.warn("后台时长:${reportInfo.backgroundDuration}毫秒")
AppLog.warn("平均 CPU: ${reportInfo.avgCpuUsage}")
AppLog.warn("最大 CPU: ${reportInfo.maxCpuUsage}")
AppLog.warn("滑动窗口采样数:${reportInfo.windowSamples.size}")
// 打印滑动窗口数据
for (sample in reportInfo.windowSamples) {
AppLog.warn("--- 窗口采样 ---")
AppLog.warn(" 时间戳:${sample.timestamp}")
AppLog.warn(" CPU 使用率:${sample.cpuUsage}")
AppLog.warn(" 后台时长:${sample.duration}毫秒")
}
}
)
监控电量
hm_metricx_cj提供
// 注册电量监控
public func initBatteryHandler(
ability: UIAbility,
reportBatteryInfo: (batteryInfo: BatteryUsageInfo) -> Unit,
reportThreadCpuUsageInfo: (allThreadCpuUsageInfo: AllThreadCpuUsageInfo) -> Unit,
limit!: Int32 = 1
): Unit
// 取消电量监控
public func destroyBatteryHandler(): Unit
接口对手机的掉电情况进行监控。
initBatteryHandler 需要的入参说明如下:
ability: UIAbility指定应用组件。reportBatteryInfo: (batteryInfo: BatteryUsageInfo) -> Unit用于在发生掉电时,将相应的信息进行上报,入参为BatteryUsageInfo类型对象。reportThreadCpuUsageInfo: (allThreadCpuUsageInfo: AllThreadCpuUsageInfo) -> Unit用于上报所有线程的CPU使用情况,当检测到CPU使用异常时,该回调函数会被触发,函数入参为AllThreadCpuUsageInfo类型对象。limit!: Int32掉电x格上报,默认为1。
BatteryUsageInfo 包含以下信息:
currentPageName当前浏览页面level当前电量temperature当前电池温度,单位为摄氏度(°C)capacity电池容量(当前暂不支持获取)scale电池的最大电量,默认为100status电池的当前状态health电池的健康状况voltage电池的当前电压,单位为毫伏特technology电池的技术类型plugged设备的连接方式charging设备是否在充电limit掉电x格上报,默认为1格brightness屏幕亮度useTimeAPP前台使用时间,单位为stime距离上次掉电的时间间隔,单位为s
AllThreadCpuUsageInfo 包含以下信息:
threadCpuUsageInfoList所有线程的CPU使用信息,类型为ArrayList<ThreadCpuUsageInfo>
ThreadCpuUsageInfo 包含以下信息:
threadId线程idthreadName线程名threadState线程状态threadJiffiesPercent线程的CPU使用率百分比threadJiffies线程的CPU使用时间totalJiffies总的CPU时间startBgTime线程进入后台的时间exceptionTime线程出现异常的时间
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initBatteryHandler
ii.
在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyBatteryHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initBatteryHandler(this, {data =>}, {data =>})
}
public override func onDestroy(): Unit {
destroyBatteryHandler()
AppLog.info("myAbility onDestroy.")
}
}
监控流量
流量监控依赖正确配置对网络统计信息的访问权限,即需要在应用的 module.json5 中添加以下内容
"requestPermissions": [
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
hm_metricx_cj 提供
// 注册占用存储空间上报函数
public func initTrafficHandler(
context: UIAbilityContext,
reportTraffic: (sampleTraffixInfo: SampleTrafficInfo) -> Unit,
reportYesterdayTraffic: (yesterdayTraffic: DayTrafficInfo) -> Unit,
sampleTime!: Int64 = 10 * 60 * 1000,
sampleThreshold!: Int64 = 50 * 1024 * 1024
): Unit
// 取消流量监控
public func destroyTrafficHandler()
接口对app占用存储空间获取并进行上报。
initTrafficHandler 需要的入参说明如下:
context:UIAbilityContext指定UIAbility上下文。reportTraffic: (sampleTraffixInfo: SampleTrafficInfo) -> Unit回调函数,用于上报流量使用情况。当流量数据达到上报阈值sampleThreshold时,回调被触发。reportYesterdayTraffic: (yesterdayTraffic: DayTrafficInfo) -> Unit回调函数,用于在应用启动时上报前一天的流量使用情况, 仅上报一次。sampleTime用于设置流量数据的采样时间间隔,单位为毫秒。sampleThreshold用于设置流量数据的上报阈值,单位为字节。
SampleTrafficInfo 包含以下信息:
systemInfo: SystemTrafficInfo系统级别流量信息pageInfoMap: HashMap<String, PageTrafficInfo>页面级别的流量信息,键为页面名称,值为对应的流量信息urlInfoArray: ArrayList<UrlTrafficInfo>URL级别的流量信息
TrafficInfo 包含以下信息
totalDailyTraffic应用日流量信息totalTraffic单次进程总流量limit触发告警的流量阈值
SystemTrafficInfo 在 TrafficInfo 基础上,添加如下信息:
timeStamp: String时间戳,表示流量数据的采集时间
PageTrafficInfo 在 TrafficInfo 基础上,添加如下信息:
pageName: String页面名称
UrlTrafficInfo 在 TrafficInfo 基础上,添加如下信息:
url: Stringurl地址
DayTrafficInfo 在 TrafficInfo 基础上,添加如下信息:
date: String日期
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initTrafficHandler :
ii.
在主模块的 main_ability.cj 的 onDestroy 回调中调用 destroyTrafficHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initTrafficHandler(this, {data =>})
}
public override func onDestroy(): Unit {
destroyTrafficHandler()
AppLog.info("myAbility onDestroy.")
}
}
监控存储
hm_metricx_cj 提供
// 注册占用存储空间上报函数
public func initStorageHandler(
reportStorageInfo: (storageInfo: StorageInfo) -> Unit,
sizeLimit!: Int64,
dirSizeLimit!: Int64,
reportTopNum!: Int64 = 5
): Unit
// 上报占用存储空间
public func reportAppStorageInfo(): Unit
接口对app占用存储空间获取并进行上报。
initStorageHandler 需要的入参说明如下:
reportStorageInfo: (storageInfo: StorageInfo) -> Unit用于获取app占用存储空间时,将app占用存储空间进行上报,入参为StorageInfo类型对象。sizeLimit存储大小阈值。超过该阈值会上报top N个异常文件和异常文件夹。dirSizeLimit文件夹大小阈值。超过该阈值的文件夹被标记为异常文件夹。reportTopNum用于设置上报的前N个文件/夹数量。
StorageInfo 包含以下信息
appSize应用安装文件大小,单位为BytecacheSize应用缓存文件大小,单位为BytedataSize应用文件存储大小(除应用安装文件和缓存文件),单位为BytetotalSize数据的大小,单位为BytetopStorageFileList文件列表,包含size最大的N个文件exceptionDirList异常文件夹列表,包含超过dirSizeLimit大小限制的文件夹
使用示例:
i.
在主模块的 main_ability.cj 的 onCreate 回调中调用 initBatteryHandler :
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initStorageHandler({data: StorageInfo =>}, sizeLimit: 100000000, dirSizeLimit: 1000, reportTopNum: 5)
}
}
ii.
需要上报app占用存储空间时,调用 reportAppStorageInfo 函数 :
reportAppStorageInfo()
监控内存泄漏
hm_metricx_cj 提供
public func initMemLeakHandler(
context: UIAbilityContext,
persistentDir: Path,
needDumpSnapshot: (pageInfo: PageInfo, typeInfos: List<String>) -> Bool,
clearHistoryComponentInfo: (typeInfos: List<String>) -> Bool,
reportMemLeak: (path: Path) -> Unit
)
接口对内存泄漏进行监控。
initMemLeakHandler 需要的入参说明如下:
context: UIAbilityContext指定UIAbility上下文。persistentDir: Path指定内存快照导出目录。needDumpSnapshot: (pageInfo: PageInfo, typeInfos: List<String>) -> Bool是否需要导出内存快照,pageInfo为PageInfo类型对象,记录页面切换的名称信息,typeInfos记录存活组件的类型信息。clearHistoryComponentInfo: (typeInfos: List<String>) -> Bool每次内存检测结束,是否清除存活的组件,typeInfos记录存活组件的类型信息。reportMemLeak: (path: Path) -> Unit内存泄漏上报函数,入参为Path类型对象,表示内存快照文件路径。
PageInfo 包含以下信息:
fromPage页面切换的源页面名称。toPage页面切换的目的页面名称。
使用示例:
i.
class EntryAbility <: UIAbility {
public override func onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Unit {
AppLog.info("Ability OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
case _ => ()
}
initMemLeakHandler(
this.context,
Path(this.context.cacheDir),
{pageInfo, typeInfos => true},
{typeInfos => false},
{dumpFilePath => AppLog.info("dumpFilePath : ${dumpFilePath.toString()}")})
}
}