Harmony(鸿蒙)
一、Harmony SDK 简介
Bugly Harmony 版本,支持Harmony OS Next平台基础异常问题的捕获上报,包含Js异常、Cpp异常、AppFreeze、错误,异常捕获后上报到 Bugly平台。Bugly Harmony SDK 基于Harmony平台arkTs开发,可通过Har包集成方式接入,提供arkTs接口。
Bugly鸿蒙专业版暂时对业务提供免费开放支持。
二、 接入 Harmony SDK
步骤一、注册产品
1、在 Bugly平台 上注册产品,平台选择 Harmony
。
2、按照提示填写产品相关信息,Bundle ID字段可填写鸿蒙AppScope -> app.json5中定义的 bundleName
字段。
3、注册完成后,可在左侧栏-设置
-产品信息
查看 APP ID
、APP KEY
等信息。
步骤二、集成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@latest
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
步骤四、初始化SDK
参考以下代码初始化 Bugly Harmony SDK,我们推荐尽早可能初始化SDK,如将初始化逻辑放在 Ability
的 onCreate
生命周期中。可参考如下代码进行初始化。
import { Bugly, BuglyBuilder } 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.buildNum = '0'; // 选填,业务App版本的构建号
builder.appChannel = 'website'; // 选填,业务App渠道
builder.userId = "12345"; // 选填,用户ID,如不设置则为空
builder.deviceModel = "huawei"; // 选填,机型,如不设置则为空
builder.debugMode = true; // 选填,默认开启,开启后Bugly SDK会打印更多调试日志,线上版本可关闭
builder.initDelay = 0; // 选填,延迟初始化时间,单位ms
builder.enableJsCrashProtect = false; // 选填,是否开启Js异常崩溃保护,设置为true后发生未捕获Js异常,进程不会退出
Bugly.init(context, builder); // 如果需等待Bugly完全初始化完成,使用await Bugly.init(context, builder);
}
- Context需要传递ApplicationContext。
- 设备ID非常重要,Bugly使用设备ID来计算设备异常率,强烈建议应用设置正确的设备ID,以确保设备的唯一性。
- BuglyBuilder需在init方法前创建,且应避免重复调用init方法。
- 需要在调用Bugly.init接口,完成初始化后,再调用其他接口,进行定制化设置,否则设置不生效。
步骤五、验证数据上报
崩溃监控
初始化完成后,可以模拟崩溃进行上报,如执行以下调用。
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调用信息。
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);
错误上报接口
SDK 0.1.0
版本开始支持错误上报,可通过如下两个接口上报错误或自定义异常。
/**
* 上报catch错误
* @param e 错误error
*/
public static postError(e: Error);
/**
* 上报自定义异常
* @param name 异常名
* @param message 异常msg
* @param stack 异常堆栈
* @param storeFirst 是否优先存储,设置后会优先存储到文件,进程重启时上报,需要在异常现场情况下采集的错误设置为true,默认为false
* @param context [可选] 如果未初始化Bugly调用接口,storeFirst设置为true时,传入context也可记录错误(但会缺失部分现场信息)
*/
public static postCustomError(name: string, message: string, stack: string, storeFirst: boolean = false, context?: Context);
postError
接口适用于arkTs中catch异常的捕获,直接传入catch错误的Error实例,会自动从Error实例中解析出对应的异常名称及堆栈信息。postCustomError
接口适用于上报自定义异常,如采用跨端Kotlin框架、游戏框架的异常。如果在正常环境下,storeFirst
参数无需设置,如果在进程可能被系统杀死环境下,建议设置storeFirst
参数为true
,当前只以同步方式保存异常到本地文件,二次启动进程时上报。
错误上报后,在如下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.2.0
开始支持导出Bugly日志打印到业务日志系统中(不设置则默认打印到系统HiLog日志系统中),在初始化前调用如下接口进行设置 。
/**
* 设置Bugly日志适配器
* @param adapter 适配器
*/
public static setLogAdapter(adapter: BuglyLogAdapter);
/**
* Bugly日志适配接口
*/
export interface BuglyLogAdapter {
// debug级别日志
debug(arg: string): void;
// info级别日志
info(arg: string): void;
// warn级别日志
warn(arg: string): void;
// error级别日志
error(arg: string): void;
// fatal级别日志
fatal(arg: string): void;
}
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的异常回调,方便在发生异常时,能回调业务进行一些自定义操作,设置接口如下。
/**
* 异常回调接口
*/
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;
}
设置异常回调接口示例如下。
// 在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}`);
}
}
// Bugly初始化逻辑
let builder = new BuglyBuilder();
...
// 初始化时将接口示例传递给builder.crashListener参数
builder.crashListener = new DemoCrashListener();
...
await Bugly.init(context, builder);
- 暂不支持App Freeze异常回调。
- Cpp Crash回调暂不支持提供堆栈信息。
- 请勿在回调中进行复杂操作,异常现场回调暂时无法保障稳定性,可能引入未知风险,请谨慎开启。
三、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小助手。