Harmony(鸿蒙) SDK 接入指南
Bugly Harmony SDK 简介
Bugly Harmony 版本,支持Harmony OS Next平台基础异常问题的捕获上报,包含Js异常、Cpp异常、AppFreeze、错误,异常捕获后上报到 Bugly平台。Bugly Harmony SDK 基于Harmony平台arkTs开发,可通过Har包集成方式接入,提供arkTs接口。
Bugly鸿蒙专业版暂时对业务提供免费开放支持。
一、注册 Harmony 产品
1、在 Bugly平台 上注册产品,平台选择 Harmony
。
2、按照提示填写产品相关信息,Bundle ID字段可填写鸿蒙AppScope -> app.json5中定义的 bundleName
字段。
3、注册完成后,可在左侧栏-设置
-产品信息
查看 APP ID
、APP KEY
等信息。
二、集成 Bugly SDK
自动集成(推荐)
1、配置内网鸿蒙三方库,执行以下命令。(设置默认存在该三方库,则无需配置)
ohpm config set registry https://ohpm.openharmony.cn/ohpm/
设置默认原始只有鸿蒙官方三方库,如添加了其他三方库,需通过 ohpm config list
查看设置的三方库,手动将 https://ohpm.openharmony.cn/ohpm/
追加后重新设置。
2、通过 ohpm
安装bugly库。
ohpm install bugly@0.4.1
3、安装完成后可直接在arkTs中通过 import
导入引用。
手动集成
1、通过三方仓库或其他渠道下载 Bugly.har
三方SDK包。
2、在需要集成的模块下创建 libs
目录,将 Bugly.har
放入目录。
3、在模块的 oh-package.json5
文件中添加对应 dependencies
,如下所示。
"dependencies": {
"bugly": "file:./libs/Bugly.har"
}
三、混淆规则配置
业务二次混淆Har包代码,可能导致部分Napi符号或字符串变量不可见,引入运行问题,建议业务直接keep Bugly Har包。
在 hap 工程目录下 obfuscation-rules.txt
混淆规则配置文件中直接添加如下规则。
-keep
../oh_modules/bugly
四、初始化 Bugly SDK
参考以下代码初始化 Bugly Harmony SDK,我们推荐尽早可能初始化SDK,如将初始化逻辑放在 Ability
的 onCreate
生命周期中。可参考如下代码进行初始化。
import { Bugly, BuglyBuilder, AppVersionMode, ModuleName } from "bugly";
initBugly(context: Context): void {
let builder = new BuglyBuilder();
builder.appId = 'xxxxxxx'; // 必填,Bugly产品信息中的APP ID
builder.appKey = 'xxx-xxxx-xxxx-xxxx-xxxx'; // 必填,Bugly产品信息中的APP KEY
builder.deviceId = "12345"; // 必填,设备ID,应保证设备ID对不同设备唯一
builder.platform = BuglyBuilder.PLATFORM_PRO; // 必填,设置上报平台,专业版本需设置为[BuglyBuilder.PLATFORM_PRO]
builder.appVersion = '1.0.0'; // 选填,业务的App版本
builder.appVersionMode = AppVersionMode.DEBUG; // 选填,当前App的版本类型,支持根据不同的版本类型下发配置
builder.buildNum = '0'; // 选填,业务App版本的构建号
builder.appChannel = 'website'; // 选填,业务App渠道
builder.userId = "12345"; // 选填,用户ID,如不设置则为空
builder.deviceModel = "huawei"; // 选填,机型,如不设置则为空
builder.debugMode = true; // 选填,默认开启,开启后Bugly SDK会打印更多调试日志,线上版本可关闭
builder.sdkLogMode = true; // 选填,设置debugMode或sdkLogMode均可开启Bugly sdk日志,适用于线上关闭debug模式但又希望打印bugly日志的场景
builder.initDelay = 0; // 选填,延迟初始化时间,单位ms
builder.enableJsCrashProtect = false; // 选填,是否开启Js异常崩溃保护,设置为true后发生未捕获Js异常,进程不会退出
builder.enablePerfModules = ModuleName.AllModules; // 选填,开启性能监控项,可传入单个性能模块名称或一组性能模块名称,此处初始化后,还需配置开启对应模块采样率,模块才会真正开启
Bugly.init(context, builder); // 如果需等待Bugly完全初始化完成,使用await Bugly.init(context, builder);
}
- Context需要传递ApplicationContext。
- 设备ID非常重要,Bugly使用设备ID来计算设备异常率,强烈建议应用设置正确的设备ID,以确保设备的唯一性。
- BuglyBuilder需在init方法前创建,且应避免重复调用init方法。
- 需要在调用Bugly.init接口,完成初始化后,再调用其他接口,进行定制化设置,否则设置不生效。
- 在同一进程中,应只初始化一次Bugly,仅建议在主线程中初始化,
0.4.1
及之后的SDK版本仅支持在主线程中初始化。
五、验证数据上报
崩溃监控
初始化完成后,可以模拟崩溃进行上报,如执行以下调用。
Bugly.testCrash(Bugly.JS_CRASH); // 模拟Js异常
Bugly.testCrash(Bugly.CPP_CRASH); // 模拟native异常
- 异常问题发生后,需要二次启动Hap应用,即可完成上报。
- Crash异常会上报FaultLog信息,可在
附件
tab的crashInfos.txt
文件中查看。
异常上报后,可在 崩溃->问题列表
中查看上报问题,点击进入 问题详情
,查看上报内容。
Freeze监控
与崩溃类似,可以通过Bugly提供的测试接口来模拟Freeze,调用后适当滑动屏幕,系统将判定为当前进程Freeze。
Bugly.testCrash(Bugly.APP_FREEZE); // 模拟Freeze异常
或是在UI线程中执行耗时逻辑,触发ANR。
let index = 0
while (true) {
index++
index = index % 2
}
Freeze问题触发上报后,在 Freeze->问题列表
中查看,点击进入 问题详情
,查看上报内容。
- Freeze异常上报的是Native、arkTs混合堆栈。
- Freeze异常会上报FaultLog信息及主线程消息信息,可在
附件
tab的crashInfos.txt
文件中查看,event_handler
表示主线程未处理消息,event_handler_size_3s
表示THREAD_BLOCK事件3s时任务栈中任务数,event_handler_size_6s
表示THREAD_BLOCK事件6s时任务栈中任务数,peer_binder
表示binder调用信息。
卡顿监控
卡顿指标(FPS、挂起率)
- 确保卡顿指标模块开启,需在
buglybuilder
初始化参数enablePerfModules
中添加卡顿指标模块(looper_metric
),同时在配置中设置卡顿指标的sample_ratio
设备采样率,二者缺一不可。 - 建议测试时,配置设备采样率设为1,设置方式可参考 SDK配置。
指标说明:
FPS: 帧率,在应用运行时,GPU和CPU合作可产生的图像数量,反应了UI图像刷新的频率,计量单位帧/秒(FramePerSecond,缩写FPS),通常是评估硬件性能与应用流畅度的指标。 鸿蒙FPS的计算借鉴了Android、iOS实现方式,采用归一化的方式进行统计,以60HZ为基准,突出反映应用在影响用户体验(低于60HZ)运行时的状态,即应用越流畅,归一化FPS越接近60HZ,反之越低。
挂起率: 如果应用在主线程中的单条消息执行时间过长,则可能导致UI卡顿,此时认为应用不能很好地响应用户的交互,累计执行的时间到挂起时间中。一个设备的挂起率,指这个设备在一天中,总的挂起时间除以其前台总时长,单位是秒/小时。
验证上报:
初始化卡顿指标能力并命中采样后,在 debug
模式下,可以看到如下日志,以判断卡顿指标已被开启。
03-27 20:05:31.683 14562-14562 A00000/com.ten...looper_metric com.tencent.bugly I Jank metric module start!
在有多个页面切换,并切换前后台时,可以看到卡顿指标上报日志。
04-02 15:12:34.938 61473-61473 A00000/com.tencent.bugly/Bugly com.tencent.bugly I [Upload] upload Success, upload event: looper_metric, record id: a84630f6-ffb4-4d9b-8033-8c288507d58f.
卡顿指标上报后,可在如下页面中查看对应数据统计,并支持App版本、页面场景等维度下钻分析。
- 卡顿指标以页面场景为统计维度,在应用有页面切换时记录指标数据,退至后台时上报数据。
- 应尽早初始化Bugly,才能及时开启卡顿指标的统计。如果Bugly初始化时间较晚,将在用户下一次切前后台操作后开启采集。
卡顿个例
- 确保卡顿个例模块开启,需在
buglybuilder
初始化参数enablePerfModules
中添加卡顿指标模块(looper_stack
),同时在配置中设置卡顿指标的sample_ratio
设备采样率,二者缺一不可。 - 建议测试时,配置设备采样率设为1,设置方式可参考 SDK配置。
个例说明:
- 卡顿卡顿堆栈监控能力基于系统API 5.0.0(12) HiAppEvent 主线程超时事件开发,兼容API 12及以上版本,默认超时时间150ms,抓栈次数固定10次,在进程生命周期中,仅会触发一次。详情可参考:鸿蒙主线程超时事件。
验证上报:
初始化卡顿个例监控并命中采样后,在 debug
模式下,可以看到如下日志,以判断卡顿个例监控已被开启。
03-27 20:05:31.683 14562-14562 A00000/com.ten...-looper_stack com.tencent.bugly I Jank monitor module start!
可通过在点击事件中连续触发以下代码,来构造触发卡顿事件。
let t = Date.now();
while (Date.now() - t <= 350) {}
成功触发后,可看到如下上报日志,表明卡顿个例已成功上报。
04-02 16:06:24.405 61473-61473 A00000/com.ten...-looper_stack com.tencent.bugly I [Jank] jank event received!!! domain: OS
04-02 16:06:24.406 61473-61473 A00000/com.ten...-looper_stack com.tencent.bugly I [Jank] event group name: MAIN_THREAD_JANK
04-02 16:06:24.406 61473-61473 A00000/com.ten...-looper_stack com.tencent.bugly I [Jank] jank begin time: 1743581180178, end time: 1743581180530, log paths: ["/data/storage/el2/log/watchdog/MAIN_THREAD_JANK_20250402160622_61473.txt"]
04-02 16:06:26.170 61473-61473 A00000/com.tencent.bugly/Bugly com.tencent.bugly I bugly do upload, type: 3, event: looper_stack
04-02 16:06:26.453 61473-61473 A00000/com.tencent.bugly/Bugly com.tencent.bugly I [Upload] upload Success, upload event: looper_stack, record id: cd6623ba-e5e5-474d-b70b-bf087120aa44.
卡顿个例上报后,可在如下页面中查看抓取全部堆栈聚合而成的火焰图、堆栈树数据,堆栈支持上传符号表翻译。
API说明
信息更新接口
Bugly初始化后,更新必要字段,接口如下。
/**
* 更新device id
* @param deviceId device id
*/
public static updateDeviceId(deviceId: string);
/**
* 更新user id
* @param userId user id
*/
public static async updateUserId(userId: string);
/**
* 更新device model
* @param deviceModel
*/
public static updateDeviceModel(deviceModel: string);
错误上报接口
Bugly支持通过如下两个接口上报catch Error或自定义错误。
/**
* 上报catch Error
* @param e Error
* @param extraData [可选] 随错误上报的附加信息,以userExtraByteData附件展示
*/
public static postError(e: Error, extraData?: string): void;
/**
* 上报自定义错误
* @param name 异常名
* @param message 异常msg
* @param stack 异常堆栈
* @param storeFirst [可选] 是否优先存储db不立即上报,默认为false,仅在异常现场时采集的错误可设置为true
* @param context [可选] 如果未初始化Bugly调用接口,传入context可记录错误
* @param extraData [可选] 随错误上报的附加信息,以userExtraByteData附件展示
*/
public static postCustomError(name: string, message: string, stack: string, storeFirst: boolean = false, context?: Context, extraData?: string): void;
如即时上报一条自定义错误,且添加附加信息,示例如下:
Bugly.postCustomError("testErrorName", "testErrorMsg", "at testErrorStack 1\nat testErrorStack 2", false, undefined, "This is extra data file content");
postError
接口适用于arkTs中catch异常的捕获,直接传入catch错误的Error实例,会自动从Error实例中解析出对应的异常名称及堆栈信息。postCustomError
接口适用于上报自定义异常,如采用跨端框架、游戏框架的异常。如果在正常环境下,storeFirst
参数无需设置,如果在进程可能被系统杀死环境下,建议设置storeFirst
参数为true
,当前只以同步方式保存异常到本地文件,二次启动进程时上报。postCustomError
在0.4.1
及之后的SDK版本支持跨线程上报错误,但需在主线程初始化Bugly,或设置storeFirst
参数设置为true。- 上述错误上报接口在
0.4.1
及之后的SDK版本中支持携带附加信息,如有设置extraData
附加信息参数,错误上报后,将在错误详情中以userExtraByteData
附件的形式提供下载。 - 错误上报在
0.4.1
及之后的SDK版本中支持配置控制采样率,设置方式可参考 SDK配置。
错误上报后,在如下TAB中进行展示。错误支持arkTs与native堆栈翻译,如是自定义错误上报,需保证与崩溃堆栈格式相同。
自定义数据接口
SDK 0.2.0
开始支持设置自定义数据,自定义数据需在 Crash 、Freeze 或 错误 发生前进行设置,可以进行更新和移除操作,异常上报时会携带设置的自定义数据。
/**
* 添加或更新自定义数据
* @param key 自定义key
* @param value 自定义value
*/
public static putUserData(key: string, value: string);
/**
* 移除自定义数据
* @param key 自定义key
*/
public static removeUserData(key: string);
/**
* 清空自定义数据
*/
public static clearUserData();
上报的自定义数据将在问题详情
-> 现场数据
-> 自定义字段
中进行展示,如下图所示。
自定义附件接口
SDK 0.2.0
开始支持设置业务自定义附件,自定义附件上报当前只支持 Crash 和 Freeze 。在发生异常前,通过如下接口设置自定义附件的路径。
/**
* 设置自定义文件路径
* 传入参数为string数组,受限于AppEvent参数限制,数组值长度需在1024个字符以内
* @param paths 自定义文件路径
*/
public static async setCustomFilePaths(paths: Array<string>);
发生异常重启进程后,自定义附件会进行打包上传,在附件中展示为 custom_log.gzip
。
- 自定义数据、自定义附件、自定义标签及现场信息的关联均会使用到系统
hiAppEvent.setEventParam
接口,该接口设置参数值长度需在1024个字符以内,且至多设置64个键值对。因此 自定义附件Array的所有值长度和需在1024个字符以内 ,否则可能设置失败。 - 如果业务有自行设置系统
hiAppEvent.setEventParam
接口,请务必预留一定数量的键值对供Bugly设置(5个以上),否则可能影响自定义数据、附件或现场信息关联。
自定义标签接口
SDK 0.4.1
开始支持业务自定义个例标签设置,标签随异常个例上报。个例标签需先在Bugly管理台 设置
-> 产品配置
-> 标签
中进行申请,如下所示。
接着通过如下SDK接口,在代码中设置自定义标签ID,异常个例上报时会同时上报这些标签ID。
/**
* 设置个例标签
* @param caseLabel 个例标签数组
*/
public static async setCaseLabel(caseLabel: Array<string>);
如设置如下自定义标签。
await Bugly.setCaseLabel(["22096", "22103", "22244"]);
个例标签展示如下。
重复调用自定义标签接口设置时,标签值会进行覆盖。
日志导出接口
SDK 0.2.0
开始支持导出Bugly日志打印到业务日志系统中(不设置则默认打印到系统HiLog日志系统中),在初始化前调用如下接口进行设置 。
/**
* 设置Bugly日志适配器
* @param adapter 适配器
*/
public static setLogAdapter(adapter: BuglyLogAdapter);
/**
* Bugly日志适配接口
*/
export interface BuglyLogAdapter {
// debug级别日志
debug(tag: string, arg: string): void;
// info级别日志
info(tag: string, arg: string): void;
// warn级别日志
warn(tag: string, arg: string): void;
// error级别日志
error(tag: string, arg: string): void;
// fatal级别日志
fatal(tag: string, arg: string): void;
}
SDK 0.3.7
及之后的版本新增了日志导出接口 tag
参数,如有导出Bugly日志,请进行适配调整。
FaultLog附件管理接口
Bugly注册系统异常回调后,会自动管理系统异常 FaultLog
文件,默认上报完后会进行删除,否则缓存区满会影响后续 FaultLog
文件生成。如不希望Bugly对 FaultLog
文件进行删除,而是自行管理,可通过以下接口进行设置。
/**
* 设置是否在bugly上报完fault log附件后删除
* @param shouldDelete 是否需要bugly删除
*/
public static setDeleteFaultLogFileAfterUpload(shouldDelete: boolean);
异常回调接口
SDK 0.3.3
开始支持Js Crash、Cpp Crash的异常回调,方便在发生异常时,能回调业务进行一些自定义操作。
SDK 0.3.5
也提供HiAppEvent收到异常信息时的回调,简化业务注册流程,设置接口如下。
/**
* 异常回调接口
*/
export interface ICrashListener {
/**
* 异常发生时回调
* @param crashType 异常类型,当前仅支持 JsCrash、CppCrash
* @param crashName 异常名称,具体异常名称
* @param crashMsg 异常信息,CppCrash不支持
* @param crashStack 异常堆栈,CppCrash不支持
*/
onCrash(crashType: string, crashName: string, crashMsg: string, crashStack: string): void;
/**
* HiAppEvent收到异常信息时回调,支持Crash和Freeze
* @param crashType 异常类型
* @param crashName 异常名称
* @param crashMsg 异常信息
* @param crashStack 异常堆栈
*/
onHiAppEventReceive(crashType: string, crashName: string, crashMsg: string, crashStack: string): void;
}
设置异常回调接口示例如下。
// 在Bugly初始化前定义接口实现
class DemoCrashListener implements ICrashListener {
onCrash(crashType: string, crashName: string, crashMsg: string, crashStack: string): void {
console.info('receive callback in demo.');
console.info(`Crash Type: ${crashType}`);
console.info(`Crash Name: ${crashName}`);
console.info(`Crash Message: ${crashMsg}`);
console.info(`Crash Stack: ${crashStack}`);
}
onHiAppEventReceive(crashType: string, crashName: string, crashMsg: string, crashStack: string): void {
console.info('[demo] receive hiAppEvent crash in demo.');
console.info(`[demo] Crash Type: ${crashType}`);
console.info(`[demo] Crash Name: ${crashName}`);
console.info(`[demo] Crash Message: ${crashMsg}`);
console.info(`Crash Stack: ${crashStack}`);
}
}
// Bugly初始化逻辑
let builder = new BuglyBuilder();
...
// 初始化时将接口示例传递给builder.crashListener参数
builder.crashListener = new DemoCrashListener();
...
await Bugly.init(context, builder);
- 暂不支持App Freeze异常回调。
- Cpp Crash回调暂不支持提供堆栈信息。
- 请勿在回调中进行复杂操作,异常现场回调暂时无法保障稳定性,可能引入未知风险,请谨慎开启。
动态开关
SDK支持质量和性能异常监控模块动态开关,可通过以下接口在业务需要的场景中动态开启或关闭异常监控上报。
/**
* 质量异常监听动态开关
* @param isFreeze true为Freeze监控,false为Crash监控(包括Js Crash和Cpp Crash)
* @param isAble 打开或关闭
*/
public static setCrashMonitorAble(isFreeze: boolean, isAble: boolean): void;
/**
* 性能模块动态开关
* @param modules 性能模块项或列表
* @param isAble 打开或关闭
*/
public static setPerfMonitorsAble(modules: string | Array<string>, isAble: boolean): void;
FAQ
1.为什么本地崩溃没有上报?如何进行排查?
首先确认Bugly本地已被正确初始化,在初始化时将Bugly的debug模式 builder.debugMode设置为true,查看 hiLog
日志打印如下,则表明Bugly已被正确初始化。
04-18 00:30:20.192 11522-11522 A00000/Bugly pid-11522 I --------------------------------------------------------------------------------------------
04-18 00:30:20.192 11522-11522 A00000/Bugly pid-11522 I [init] Bugly debug模式开启 -- Bugly running in debug model.
04-18 00:30:20.192 11522-11522 A00000/Bugly pid-11522 I [init] Bugly debug模式将输出详细SDK Log -- More detailed log of Bugly SDK will be output in debug model.
04-18 00:30:20.192 11522-11522 A00000/Bugly pid-11522 I --------------------------------------------------------------------------------------------
04-18 00:30:20.214 11522-11522 A00000/Bugly pid-11522 I [init] init Bugly success.
其次确认异常是否能被Bugly正常上报,在触发异常后,IDE的 FaultLog
中可以查看到对应的错误信息。
重启应用,预计在10-15s左右能看见Bugly的上报日志,如下。
04-18 03:20:21.616 6260-6260 A00000/Bugly com.tencent.bugly I upload Success, upload type: NativeCrash, record id: 62056e9c-6954-4c1c-aaf9-7d1479915d49.
2.为什么有的信息没有数据展示?
当前Bugly SDK版本基于Harmony OS Next 5.0版本开发,API Level 12,部分信息系统未提供获取API。
Bugly Harmony SDK持续建设完善中,如有疑问或诉求,可咨询Bugly小助手。
3.如何翻译鸿蒙Native堆栈?如何翻译arkTs混淆堆栈?
详情请参考 鸿蒙符号表。
如有疑问或诉求,可咨询Bugly小助手。