Harmony(鸿蒙) 日志
Bugly Harmony(鸿蒙) 日志能力对齐Android、iOS端日志能力,主要由两部分组成:
- TDDiag:提供日志捞取、日志染色、条件采集等端上日志服务。
- TDLog:提供本地打日志能力,底层基于微信xlog方案。此模块可选接入,通过实现
LoggerAdapter
接口与TDDiag配合使用。
支持能力:
- 日志捞取(暂不支持push能力)
- 日志染色
- 日志主动上报
一、快速开始
1. 新建应用
在Bugly平台新建应用,获取Bugly AppId 和 AppKey 。
如已创建质量监控产品,直接复用质量产品AppId及AppKey即可 。
2. 集成Har包
参考Harmony(鸿蒙)SDK接入指南,接入Bugly Har包,Bugly鸿蒙接入文档。
Harmony(鸿蒙)日志能力当前与质量监控能力统一集成在 Bugly Har包( 0.3.2
及以上版本) 中,只需通过ohpm install bugly@latest
即可接入使用。
3. 混淆规则配置
业务二次混淆Har包代码,可能导致部分Napi符号或字符串变量不可见,引入运行问题,建议业务直接keep Bugly Har包。
在 hap 工程目录下 obfuscation-rules.txt
混淆规则配置文件中直接添加如下规则。
-keep
../oh_modules/bugly
4. 初始化
参考如下代码初始化Bugly Harmony SDK日志诊断能力。
import { ILogInstance, TDLog, LogLevel, TDLogMode, TDDiag, TDDiagUploadParams } from 'bugly';
public static initBuglyDiagnose(context: Context) {
// 1、TDLog初始化(可选,如无自建日志组件推荐使用)
let logBuilder = new TDLogBuilder();
logBuilder.logDir = "xxx"; // 必填,日志的输出路径,填写示例如 getContext(this).filesDir + "/bugly_tdlog"
logBuilder.namePrefix = "xxx"; // 必填,日志文件的前缀名称
logBuilder.consoleLog = true; // 可选,是否同时将日志打印到console
logBuilder.logLevel = LogLevel.LEVEL_ALL; // 可选,设置日志输出等级,详见初始化参数参考值
logBuilder.mode = TDLogMode.Async; // 可选,设置日志写入模式,分同步和异步,Release版本一定要用异步Async方式,Debug版本两个都可以,Sync可能有卡顿
logBuilder.pubKey = "xxx"; // 可选,可参考 https://github.com/Tencent/mars 使用 `gen_key.py` 生成公私钥,并联系Bugly小助手提供公私钥进行后台配置,同时在此传入公钥,即可在Bugly平台上传日志后进行解密,若后台无配置会导致线上日志解密失败
logBuilder.maxFileSize = 50 * 1024 * 1024; // 可选,设置单个日志文件的最大值,单位字节,默认50M
logBuilder.maxAliveTime = 7 * 24 * 60 * 60; // 可选,设置日志文件的保存时间,单位秒,默认7天
logBuilder.subLogDirs = subLogDirsArray; // 可选,如有设置日志子实例,需在初始化时提前设置所有子实例日志输出路径,用于Bugly平台捞取,设置类型为数组
TDLog.init(logBuilder);
// 2、TDDiag初始化
let diagBuilder = new TDDiagBuilder();
diagBuilder.appId = "xxx"; // 必填,Bugly平台提供的appId
diagBuilder.appKey = "xxxx"; // 必填,Bugly平台提供的appKey
diagBuilder.platform = TDDiagBuilder.xxx; // 必填,OA版本填 [TDDiagBuilder.PLATFORM_OA], 专业版本填 [TDDiagBuilder.PLATFORM_PRO]
diagBuilder.appVersion = "1.0.0"; // 必填,设置app版本
diagBuilder.loggerAdapter = TDLog.getTDLogAdapter(); // 必填,设置日志适配器,如使用自建日志组件,需自实现LoggerAdapter接口,并传入实例
diagBuilder.xgTrafficQuota = 500 * 1024 * 1024; // 可选,每日可使用4G流量主动上报的日志大小,取值范围[0, 500],每日主动上报总流量大小(WIFI、4G)限制500M
diagBuilder.initiativeUploadWhiteListTags = whiteTags; // 可选,主动上报白名单tags列表,使用白名单中tag进行主动上报,将不受配额及上报频率限制
diagBuilder.logUploadListener = new DemoLogUploadListener(); // 可选,设置日志主动上报的回调接口
TDDiag.init(context, diagBuilder);
// 3、设置TDDiag Guid
TDDiag.setGuid("xxx"); // 必须初始化后设置,设置设备唯一标识Guid,用于日志捞取,设置后将触发配置拉取
}
初始化参数参考类
enum LogLevel {
LEVEL_ALL = 0,
LEVEL_VERBOSE = 0,
LEVEL_DEBUG = 1,
LEVEL_INFO = 2,
LEVEL_WARNING = 3,
LEVEL_ERROR = 4,
LEVEL_FATAL = 5,
LEVEL_NONE = 6
}
enum TDLogMode {
Async = 0,
Sync = 1
}
主动上报回调接口实现参考
/**
* 主动上报回调接口实现
*/
class DemoLogUploadListener implements LogUploadListener {
onSuccess(): void {
console.info("do custom log upload callback, success!");
}
onFailure(): void {
console.info("do custom log upload callback, failure!");
}
}
- context需要传递ApplicationContext。
- builder类均需在init接口调用之前创建,且应避免重复调用init方法。
- 需要在调用init接口,完成初始化后,再调用
TDLog
或TDDiag
的其他设置接口,否则设置可能不生效。
(可选)自实现日志组件适配接口
如需自实现日志组件,仅接入使用Bugly上报及捞取能力,可实现以下类,并将初始化时 diagBuilder.loggerAdapter
设置为自实现类的实例。
interface LoggerAdapter {
/**
* 设置日志染色级别
* @param level 染色级别
*/
setColorLevel(level: LogLevel): void;
/**
* 打印TDDiag日志
* @param level 日志等级
* @param tag 日志tag
* @param msg 日志内容
* @param e error
*/
printDiagnoseLog(level: LogLevel, tag: string, msg: string, e: Error | null): void;
/**
* 获取日志加密公钥
* @returns 不加密使用空串""
*/
getPubKey(): string;
/**
* 获取日志存放路径(如有日志子实例,需包含所有日志子实例输出路径),文件格式不限,按照创建时间捞取日志文件
* @returns
*/
getLogPaths(): Array<string>;
}
初始化完成后,即可进行日志打印、主动上报、线上捞取等能力。
二、打印日志
1. 打印日志
使用如下接口进行日志打印,默认会创建日志主实例,并用主实例打印日志。
TDLog.d("tag", "xxxxxxx");
TDLog.i("tag", "xxxxxxx");
TDLog.w("tag", "xxxxxxx");
TDLog.e("tag", "xxxxxxx");
TDLog.f("tag", "xxxxxxx");
TDLog.printErrStackTrace("tag", error, "xxxx");
2.(可选)创建子实例打印日志
Bugly鸿蒙 TDLog
支持多日志实例,通常情况下仅使用主实例即可满足日志打印诉求,无需设置日志子实例。如有提供给第三方SDK打日志等场景,可使用子实例打印。
// 初始化后,创建日志子实例
const level = LogLevel.LEVEL_ALL; // 日志子实例打印等级
const mode = TDLogMode.Async; // 日志子实例写入模式
const logDir = "xxx"; // 日志子实例路径
const namePrefix = "xxx"; // 日志子实例前缀
const subIns: ILogInstance = TDLog.openSubLogInstance(level, mode, logDir, namePrefix);
// 使用子实例打印日志
subIns.d("tag", "xxxxxxx");
subIns.i("tag", "xxxxxxx");
subIns.w("tag", "xxxxxxx");
subIns.e("tag", "xxxxxxx");
subIns.f("tag", "xxxxxxx");
subIns.printErrStackTrace("tag", error, "xxxx");
日志子实例的操作接口如下。
interface ILogInstance {
/**
* 强制将日志写入文件
*/
flushLog(): void;
/**
* 获取日志等级
*/
getLogLevel(): number;
/**
* 设置日志等级
* @param level 日志等级
*/
setLogLevel(level: number): void;
/**
* 设置是否打印到控制台,不设置则默认使用主实例设置
* @param isOpen 开启状态
*/
setConsoleLogOpen(isOpen: boolean): void;
/**
* 设置单个日志文件的最大值,不设置则默认使用主实例设置
* @param maxFileSize 文件大小最大值,单位字节
*/
setMaxFileSize(maxFileSize: number): void;
/**
* 设置日志文件的保存时间,不设置则默认使用主实例设置
* @param maxAliveTime 文件最大保存时间,单位秒
*/
setMaxAliveTime(maxAliveTime: number): void;
}
3. 验证本地日志文件
打印日志成功后可见本地日志文件。(如日志不完整,可尝试调用 TDLog.flushLog()
强制刷新日志)
4. 其他日志接口
class TDLog {
/**
* 强制将日志写入文件(含日志子实例)
*/
public static flushLog();
/**
* 关闭日志实例(含日志子实例)
*/
public static closeLog();
/**
* 获取日志等级(仅日志主实例)
*/
public static getLogLevel(): number;
/**
* 设置日志等级(含日志子实例)
* @param level 日志等级
*/
public static setLogLevel(level: number);
/**
* 关闭TDLog子实例
* @param namePrefix 子实例名称前缀
*/
public static closeSubLogInstance(namePrefix: string);
/**
* 获取TDLog子实例
* @param namePrefix
* @returns
*/
public static getSubLogInstance(namePrefix: string): ILogInstance | null;
}
5. Native日志打印
如业务项目使用到Native模块,日志模块支持高效的Native层日志打印及刷新。
首先按照如下步骤在 CMakeList.txt
文件中引入Bugly Har包中的 libbuglyxlog.so
及对应的 include
文件夹,如下所示,注意需替换为项目中真实的路径。
include_directories(xxx/oh_modules/.ohpm/xxx/oh_modules/bugly/include)
add_library(buglyxlog_lib SHARED IMPORTED)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
set_target_properties(buglyxlog_lib PROPERTIES IMPORTED_LOCATION xxx/oh_modules/.ohpm/xxx/oh_modules/bugly/libs/arm64-v8a/libbuglyxlog.so)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
set_target_properties(buglyxlog_lib PROPERTIES IMPORTED_LOCATION xxx/oh_modules/.ohpm/xxx/oh_modules/bugly/libs/x86_64/libbuglyxlog.so)
else()
message(FATAL_ERROR "Unsupported architecture")
endif()
target_link_libraries(test PUBLIC buglyxlog_lib)
Native层日志打印及刷新接口:
#define OHOS_TDLOG_LEVEL_DEBUG 1
#define OHOS_TDLOG_LEVEL_INFO 2
#define OHOS_TDLOG_LEVEL_WARNING 3
#define OHOS_TDLOG_LEVEL_ERROR 4
/**
* 打印日志
* @param namePrefix 日志实例前缀,主实例直接填 nullptr,子实例填对应的前缀名
* @param level 日志级别
* @param tag 日志tag
* @param log 日志内容
*/
void TDLogPrintLog(const char* namePrefix, int level, const char* tag, const char* log);
/**
* 刷新日志
* @param namePrefix 日志实例前缀,主实例直接填 nullptr,子实例填对应的前缀名
*/
void TDLogFlushLog(const char* namePrefix);
三、主动上报
1. 上报方式
参考如下代码主动上报日志文件或自定义文件。
import { TDDiag, TDDiagUploadParams } from 'bugly';
public static uploadFiles() {
// 1、构建上报参数
let params = new TDDiagUploadParams();
params.files = logPathArr; // 需上报的日志文件或自定义文件路径,传入文件list数组
params.tag = "xxx"; // 主动上报标签
params.summary = "xxx"; // 主动上报信息摘要
// 2、调用上报接口
TDDiag.uploadLogFiles(params);
}
2. 上报限制
调用主动上报接口时,请关注接口相关限制。
- 主动上报接口存在限频,默认 每5分钟内最多进行2次上报。
- 主动上报存在每日总配额 500M 限制(文件压缩后),每日额度采用令牌桶算法逐步递增,支持在
TDDiag
初始化时使用xgTrafficQuota
参数设置4G流量的每日上报额度。 - 可在
TDDiag
初始化时配置initiativeUploadWhiteListTags
参数来 设置忽略上报限制的tag标签 ,满足白名单标签的主动上报不受 1、2 限制。 - 主动上报存在 熔断机制 ,如果连续上报失败10次后,将停用上报6小时。
- 主动上报打包上传前,会检查压缩前的文件大小,如果 压缩前超过500M则不会被打包上报 ,请控制单次上报文件大小。
- 上报日志文件支持多路径设置,路径 支持设置目录或文件。
3. 上报查看
主动上报后,可在Bugly管理端的 日志
-> 日志查询
-> 主动上报
页面查看上报的日志信息。
四、线上捞取
1. 捞取方式
Bugly 平台提供日志捞取指令的下发能力。
用户可以在Bugly管理端的 日志
-> 日志查询
-> 下发指令
页面进行指令的下发和上报结果查询。通过 新建查询
入口,新建一个日志捞取命令,捞取命令需选择捞取日志的 时间范围 和 设备唯一ID,支持为捞取增加搜索标签和附件路径。
捞取时指定的设备ID即 TDDiag.setGuid
时设置的 Guid。
待命令下发后,可等待SDK拉取配置,并上传对应的日志文件。
2. 配置拉取
下发命令后,依赖SDK本地的配置拉取逻辑来判断是否有日志需要上报。
配置拉取时机
- 调用
TDDiag.setGuid
- 后台默认返回下一次配置拉取6分钟间隔,本地每5分钟检查是否满足间隔时间,满足则拉取。
配置强制拉取
一般情况下上述时机可以确保日志指令被及时接收并上传日志 ,但特殊场景下,用户可以选择调用如下接口来主动拉取配置。
TDDiag.syncConfig(true); // 强制拉取配置,参数设置为true为强制刷新,不检查是否满足后台默认时间间隔;参数为false则仍会检查是否满足时间间隔条件
五、设备染色
Bugly 管理端提供日志染色指令下发能力,可以在线上配置本地打印的日志等级。
用户可以在Bugly管理端的 日志
-> 设备染色
-> 新建染色
页面进行日志染色指令的下发。
待指令下发,SDK拉取到配置后,会自动调用日志等级设置接口,改变当前的日志打印级别。