Skip to main content

Harmony(鸿蒙) 日志

Bugly Harmony(鸿蒙) 日志能力对齐Android、iOS端日志能力,主要由两部分组成:

  1. TDDiag:提供日志捞取、日志染色、条件采集等端上日志服务。
  2. TDLog:提供本地打日志能力,底层基于微信xlog方案。此模块可选接入,通过实现 LoggerAdapter 接口与TDDiag配合使用。

支持能力:

  1. 日志捞取(暂不支持push能力)
  2. 日志染色
  3. 日志主动上报

一、快速开始

1. 新建应用

在Bugly平台新建应用,获取Bugly AppIdAppKey

产品ID与Key

提醒

如已创建质量监控产品,直接复用质量产品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!");
}
}
注意
  1. context需要传递ApplicationContext。
  2. builder类均需在init接口调用之前创建,且应避免重复调用init方法。
  3. 需要在调用init接口,完成初始化后,再调用 TDLogTDDiag 的其他设置接口,否则设置可能不生效。

(可选)自实现日志组件适配接口

如需自实现日志组件,仅接入使用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. 上报限制

调用主动上报接口时,请关注接口相关限制。

注意
  1. 主动上报接口存在限频,默认 每5分钟内最多进行2次上报
  2. 主动上报存在每日总配额 500M 限制(文件压缩后),每日额度采用令牌桶算法逐步递增,支持在 TDDiag 初始化时使用 xgTrafficQuota 参数设置4G流量的每日上报额度。
  3. 可在 TDDiag 初始化时配置 initiativeUploadWhiteListTags 参数来 设置忽略上报限制的tag标签 ,满足白名单标签的主动上报不受 1、2 限制。
  4. 主动上报存在 熔断机制 ,如果连续上报失败10次后,将停用上报6小时。
  5. 主动上报打包上传前,会检查压缩前的文件大小,如果 压缩前超过500M则不会被打包上报 ,请控制单次上报文件大小。
  6. 上报日志文件支持多路径设置,路径 支持设置目录或文件

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拉取到配置后,会自动调用日志等级设置接口,改变当前的日志打印级别。