一身转战三千里,一剑曾当百万师。这篇文章主要讲述OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明相关的知识,希望能为你提供帮助。
作者:吴文璐
1 DFX简介DFX(Design for X)子系统是为了提升软件质量设计的工具集,目前包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性。
目前标准系统已实现以下功能:
- HiLog:流水日志。
- HiSysEvent:系统事件记录接口。
- HiView:插件平台。
- FaultLoggerd:应用故障订阅和收集。
- HiAppEvent: js应用事件记录接口。
文章图片
注:本文只介绍DFX各组件的使用,后续会有文章单独分析各组件的源码。
2 HilogHiLog是日志系统,提供给系统框架、服务、以及应用打印日志,记录用户操作、系统运行状态等。
用户态Process通过日志接口将日志内容写入hilogd buffer中,用户态的hilog工具支持将日志输出到控制台(console)进行查看,同时也支持通过hilog工具给hilogd发送命令将日志落盘,设置指定< type> 日志类型缓冲区的大小等。
HiLog架构图如下:
文章图片
注:目前代码暂未看到有支持读取kernel日志。
代码结构:
/base/hiviewdfx/hilog
├── frameworks# 框架代码
│└── native# HiLog native实现代码
├── interfaces# 接口
│└── native# 对外C/C++接口
│└── innerkits# 对内部子系统暴露的头文件
│└── kits# 对应用暴露的头文件
├── services
│└── hilogd# 日志常驻服务实现
│└── hilogtool# 日志工具实现
从使用者的角度,只需要关心hilog日志接口和hilog命令行工具的使用方法。
2.1 hilog接口使用说明
2.1.1 主要API说明
文章图片
2.1.2 使用方法
- 在模块BUILD.gn文件中添加依赖
external_deps = [ "hilog_native:libhilog" ]
- include头文件" hilog/log.h"
- 接口调用
```C++
#include < vector>
+#include " hilog/log.h"
#include " string_ex.h"
#include " uri.h"
using std::string;
using std::regex;
+using OHOS::HiviewDFX::HiLog;
namespace OHOS
namespace
@@ -39,6 +41,7 @@ namespace
const size_t POS_INC_MORE = 2;
const size_t POS_INC_AGAIN = 3;
const regex SCHEME_REGEX(" [a-zA-Z][a-zA-Z|\\d|+|-|.]*$" );
- const HiviewDFX::HiLogLabel LABEL = LOG_CORE, 0xD001800, "
URI"
;
; // namespace
@@ -48,6 +51,7 @@ Uri::Uri(const string& uriString)
port_ = NOT_CALCULATED;
if (uriString.empty())
- HiLog::Error(LABEL, "
Input empty!"
);
return;
### 2.2 hilog命令行工具使用说明| 短选项 | 长选项 | 参数 |说明 |备注| | ----- | ----- | ----| ---- |---- | | 缺省 | 缺省 | |阻塞读日志,不退出|| | -h | --help| |帮助命令|| | -g | ||查询buffer的大小,配合-t指定某一类型|| | -G| --buffer-size|\\< size> |设置指定\\< type> 日志类型缓冲区的大小,配合-t指定某一类型使用,默认app和core, 可使用B/K/M/G为单位|| | -r | ||清除buffer日志,配合-t指定某一类型使用,默认app和core|| | -p |--privacy |\\< on/off> |支持系统调试时日志隐私开关控制|暂不生效| || |on|打开隐私开关,显示\\< private> || || |off|关闭隐私开关,显示明文 || | -s |--statistics ||查询buffer的大小,配合-t指定某一类型|| | -S | ||清除统计信息,需配合-t或-D使用|| | -Q | |\\< ctrl-type> |流控开关控制|暂不生效| || |pidon|进程流控开关打开|| || |pidoff|进程流控开关关闭|| || |domainon|domain流控开关打开|| || |domainoff|domain流控开关关闭|| |-L|--level |\\< level> |指定级别的日志,示例:-L D/I/W/E/F|| |-t|--type|\\< type> |指定类型的日志,示例:-t app core init|| | -D | --domain|\\< domain> |指定domain,不超过5个|| |-T|--Tag |\\< tag> |指定tag,不超过10个|| |-a|--head |\\< n> |只显示前\\< n> 行日志|| |-z| --tail|\\< n> |只显示后\\< n> 行日志|| |-P|--pid |\\< pid> |指定pid,不超过5个|| |-e|--regex |\\< expr> |只打印日志消息与\\< expr> 匹配的行,其中\\< expr> 是一个正则表达式|| |-f| --filename|\\< filename> |设置落盘的文件名|配合-w落盘任务控制使用| |-l| --length|\\< length> |设置单个落盘文件的大小,需要大于等于64K|配合-w落盘任务控制使用| |-n|--number |\\< number> |设置最大落盘文件个数|配合-w落盘任务控制使用| |-j|--jobid |\\< jobid> |设置落盘任务的ID,用于开始或终止落盘任务|配合-w落盘任务控制使用| |-w| --write|\\< control> ||| || |query|落盘任务查询|| || |start|落盘任务开始,命令行参数为文件名、单文件大小、落盘算法、文件数目.|| || |stop|落盘任务停止|| |-m|--stream |\\< algorithm> |落盘压缩算法|配合-w落盘任务控制使用| || |none|无压缩方式落盘|| || |zlib|zlib压缩算法落盘,落盘文件为.gz|| || |zstd|zstd压缩算法落盘,落盘文件为.zst|| |-v| --format|\\< format> ||| || |time|显示本地时间|| || |color|不同级别显示不同颜色,参数缺省级别颜色模式处理(按黑白方式)|| || |epoch|显示相对1970时间|| || |monotonic|显示相对启动时间|| || |usec|显示微秒精度时间|| || |nsec|显示纳秒精度时间|| || |year|将年份添加到显示时间|| || |zone|将本地时区添加到显示时间|| |-b|--baselevel |\\< loglevel> |设置可打印日志的最低等级:D(DEBUG)/I(INFO)/W(WARN)/E(ERROR)/F(FATAL)|暂不生效|
3 HiSysEventhisysevent组件定义了HiSysEvent埋点接口供应用框架、系统服务使用,用于向hiview上报系统事件信息。通过在关键路径埋点记录系统在运行过程中的重要信息,辅助开发者定位问题。
文章图片
3.1 接口说明
```C++
/**
- @brief 写系统事件
- @param domain事件的domain
- @param eventName 事件名
- @param type事件类型
- @param keyValues 可变参数,键值对
- @return 0 成功,其他失败
*/
template< typename... Types> static int Write(const std::string & domain, const std::string & eventName,
EventType type, Types... keyValues)枚举类型EventType定义了事件类型 ```C++ enum EventType FAULT= 1,// system fault event STATISTIC = 2,// system statistic event SECURITY= 3,// system security event BEHAVIOR= 4// system behavior event ;
HiSysEvent内部类Domain中定义了一些字符串常量,用于表示不同的domain
3.2 接口使用
- 在BUILD.gn中增加依赖:
external_deps = [ "hisysevent_native:libhisysevent" ]
- 在类定义头文件或者类实现源文件中,包含HiSysEvent头文件:
```C++
#include " hisysevent.h"
- 示例:(以下代码摘自源码)
```C++
void EventReport::SendEvent(const EventInfo& eventInfo)
auto packageName = AceApplicationInfo::GetInstance().GetPackageName();
if (packageName.size() > MAX_PACKAGE_NAME_LENGTH)
StrTrim(packageName);
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventInfo.eventType,
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
EVENT_KEY_ERROR_TYPE, eventInfo.errorType,
EVENT_KEY_PACKAGE_NAME, packageName);
hiview在收到消息后会打印日志,并把事件保存到 /data/log/LogService/sys_event_db/hisysevent.db 数据库中。 日志如下:
行 10430: 12-06 15:41:03.176369537 D 02d10/HiView-EventServer: Start: receive data from client < private>
行 10431: 12-06 15:41:03.176369537 D 02d10/HiView-SysEventSource: Parser: parser raw message size=301, " domain" :" ACE" ," name" :" JSERROR" ," type" :1," time" :1638805263175," pid" :821," tid_" :839," PACKAGENAME" :" " ," REASON" :" Js Crash" ," SUMMARY" :" Lifetime: 0.000000s
行 10432: 12-06 15:41:03.176369537 D 02d10/HiView-SysEventSource: Js-Engine: Quick JS
行 10433: 12-06 15:41:03.176369537 D 02d10/HiView-SysEventSource: Stacktrace: TypeError: cannot read property getAppPageStartConfig of undefined
行 10434: 12-06 15:41:03.176369537 D 02d10/HiView-SysEventSource:at onPageShow (pages/EntryView.js)
行 10435: 12-06 15:41:03.176369537 D 02d10/HiView-SysEventSource:at onPageShow (pages/EntryView.js)
行 10472: 12-06 15:41:03.180369537 I 02d10/HiView-SysEventSource: Parser: parser result domain=ACE eventName_=JS_ERROR
行 10473: 12-06 15:41:03.180369537 D 02d10/HiView-EventSource: PublishPipelineEvent: EventSource PublishPipelineEvent
行 10474: 12-06 15:41:03.180369547 I 02d10/HiView-SysEventService: Convert2SysEvent: domain is ACE, eventName is JS_ERROR.
行 10485: 12-06 15:41:03.180369547 D 02d10/HiView-SysEventDao: Insert: insert db file /data/log/LogService/sys_event_db/hisysevent.db with JS_ERROR
行 10837: 12-06 15:41:03.232369547 I 02d10/HiView-DOCDB: open ejdb success
行 10838: 12-06 15:41:03.232369547 I 02d10/HiView-DOCDB: open doc store
行 11141: 12-06 15:41:03.249369547 D 02d10/HiView-DOCDB: put data to doc store success
行 11142: 12-06 15:41:03.250369547 D 02d10/HiView-SysEventDbMgr: SaveToStore: save sys event 1, JS_ERROR
行 11227: 12-06 15:41:03.253369547 I 02d10/Faultlogger: AddFaultLogIfNeed: Invalid module name
行 11229: 12-06 15:41:03.253369547 I 02d10/HiView-SysEventSource: Recycle: recycle resource
- 在BUILD.gn中增加依赖:
架构图如下:
文章图片
Hiview由框架和插件组成,主要包含以下几部分:
- 操作系统适配层(adapter),对使用的系统服务的接口进行适配。
- Hiview基础定义(hiview base),包括插件基类、管道的定义,事件、事件队列定义以及一些工具类。
- Hiview的核心模块(hiview core),包括插件配置,插件管理以及事件源。
- Hiview服务(hiview services),目前仅包括hiview运行信息dump功能。
- Hiview插件(plugins),为独立功能的业务模块。
格式化的事件通过HiSysEvent API上报至hiview进行处理,请参考第三节HiSysEvent的架构图。
- 1.应用框架、系统服务使用HiSysEvent组件上报系统事件。
- 2.Hiview中SysEventSource获取消息,解析并组装成管道事件分发给插件处理。
5 FaultLoggerdfaultloggerd是OpenHarmony中的C/C++运行时崩溃临时日志的生成及管理模块。主要流程如下:
进程A调用接口订阅故障收集功能。
进程A的异常信号处理器检测到异常信号后Fork出子进程运行processdump程序。
processdump程序Ptrace到父进程上,读取异常线程相关信息,包括寄存器以及调用栈。
processdump程序在读取异常信息后将其写入到/data/log/faultlog/temp目录下中做临时存储。
接口使用方法:
- 在模块的BUILD.gn文件中添加依赖
deps = ["//base/hiviewdfx/faultloggerd/interfaces/innerkits/signal_handler:dfx_signalhandler"]
- 包含" dfx_signal_handler.h" 头文件
- 调用DFX_InstallSignalHandler()方法订阅故障收集功能。
示例:(以下代码摘自源码)
base/telephony/ril_adapter/hril_hdf/hril_hdf.c中
```C++
#include " hril_hdf.h"
#include < pthread.h>
#include " dfx_signal_handler.h" //................[1]头文件
#include " telephony_log_c.h"
static int32_t RilAdapterInit(struct HdfDeviceObject device)
if (device == NULL)
return HDF_ERR_INVALID_OBJECT;
DFX_InstallSignalHandler(); //................[2]订阅故障收集功能
struct HdfSBuf sbuf = HdfSBufTypedObtain(SBUF_IPC);
if (sbuf == NULL)
TELEPHONY_LOGE(" HdfSampleDriverBind, failed to obtain ipc sbuf" );
return HDF_ERR_INVALID_OBJECT;
if (!HdfSbufWriteString(sbuf, " string" ))
TELEPHONY_LOGE(" HdfSampleDriverBind, failed to write string to ipc sbuf" );
HdfSBufRecycle(sbuf);
return HDF_FAILURE;
if (sbuf != NULL)
HdfSBufRecycle(sbuf);
TELEPHONY_LOGD(" sbuf IPC obtain test success!" );
LoadVendor();
return HDF_SUCCESS;
注:程序崩溃后会在/data/log/faultlog/temp路径下生成临时文件。系统开发者可以通过日志定位崩溃问题。
文章图片
6.1 接口说明
js接口定义文件:interface/sdk-js/api/phone/@ohos.hiAppEvent.d.ts
6.1.1 打点接口
-
JS 事件类型枚举——EventType 类型 描述 FAULT 故障类型事件 STATISTIC 统计类型事件 SECURITY 安全类型事件 BEHAVIOR 行为类型事件 - function write(eventName: string, eventType: EventType, keyValues: object): Promise\\< void> ; 应用事件异步打点方法,使用promise方式作为异步回调。
- function write(string eventName, EventType type, object keyValues,
AsyncCallback\\< void> callback): void应用事件异步打点方法,使用callback方式作为异步回调。 - 输入参数说明:
- eventName:事件名称。
- eventType:事件类型。
- keyValues:事件参数键值对,为Json对象类型。
- callback:回调函数,可以在回调函数中处理接口返回值。返回值为0表示事件参数校验成功,事件正常异步写入事件文件;大于0表示事件存在异常参数,事件在忽略异常参数后再异步写入事件文件;小于0表示事件校验失败,不执行事件异步打点操作。
- function configure(config: ConfigOption): boolean;
应用事件打点配置方法,可以对打点功能进行自定义配置。
- 参数config:应用事件打点配置项。
- 返回值:boolean,true表示配置成功,false表示配置失败。
-
ConfigOption应用打点配置选项 配置名 类型 必填 说明 disable boolean 否 应用打点功能开关,true表示关闭打点功能,false表示不关闭打点功能 maxStorage string 否 打点数据本地存储文件所在目录的配额大小,默认限额为“10M”。所在目录大小超出限额后会对目录进行清理操作,会按从旧到新的顺序逐个删除打点数据文件,直到目录大小不超出限额时停止。
- 引入模块:
- import hiAppEvent from @ohos.hiAppEvent
- 应用事件打点:
- callback方式
hiAppEvent.write("testevent", hiAppEvent.EventType.BEHAVIOR, "key":"value", (err, value) => console.log(`HiAppEvent testevent callback`); if (err) // 事件写入异常:事件存在异常参数或者事件校验失败不执行写入 console.error(`HiAppEvent json-callback-error code=$err.code`); else console.log(`HiAppEvent json-callback-success value=https://www.songbingjia.com/android/$value`));
- Promise方式
hiAppEvent.write("test_event", hiAppEvent.EventType.FAULT, "int_data":100, "str_data":"strValue") .then((value) => // 事件写入正常 console.log(`success to write event: $value`); ).catch((err) => // 事件写入异常:事件存在异常参数或者事件校验失败不执行写入 console.error(`failed to write event because $err.code`); );
- callback方式
- 应用打点配置
- 配置应用事件打点功能开关
hiAppEvent.configure( disable: true );
- 配置事件文件目录存储限额大小
hiAppEvent.configure( maxStorage: 15M );
- 配置应用事件打点功能开关
更多原创内容请关注:深开鸿技术团队入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,共建鸿蒙生态,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
附件链接:
dfxdemo.zip
https://harmonyos.51cto.com/resource/1647
HiAppEventDemo.zip
https://harmonyos.51cto.com/resource/1646
想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz
::: hljs-center
文章图片
:::
推荐阅读
- #yyds干货盘点# 详解JavaScript中的闭包
- Shell脚本画图形
- #yyds干货盘点#CCNA学习记录4
- Shell脚本练习三
- Nginx 四层代理之动静分离与负载均衡
- 第五课
- one 一只小红帽的linux学习笔记,从入门到放弃,再到入门
- 第四课
- #yyds干货盘点#HCIE-RS面试--STP故障及处置