

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明
source link: https://blog.51cto.com/harmonyos/4938607
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者:吴文璐
1 DFX简介
DFX(Design for X)子系统是为了提升软件质量设计的工具集,目前包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性。
目前标准系统已实现以下功能:
- HiLog:流水日志。
- HiSysEvent:系统事件记录接口。
- HiView:插件平台。
- FaultLoggerd:应用故障订阅和收集。
- HiAppEvent: js应用事件记录接口。
1.1 OpenHarmony架构图
注:本文只介绍DFX各组件的使用,后续会有文章单独分析各组件的源码。
2 Hilog
HiLog是日志系统,提供给系统框架、服务、以及应用打印日志,记录用户操作、系统运行状态等。
用户态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"
代码示例(以下代码从系统源码中摘录)
#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
Uri::Uri(const string& uriString)
@@ -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) 暂不生效
注:落盘日志文件保存路径为"/data/log/hilog/"。
3 HiSysEvent
hisysevent组件定义了HiSysEvent埋点接口供应用框架、系统服务使用,用于向hiview上报系统事件信息。通过在关键路径埋点记录系统在运行过程中的重要信息,辅助开发者定位问题。
3.1 接口说明
/**
* @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定义了事件类型
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头文件:
#include "hisysevent.h"
- 示例:(以下代码摘自源码)
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.176 369 537 D 02d10/HiView-EventServer: Start: receive data from client <private>
行 10431: 12-06 15:41:03.176 369 537 D 02d10/HiView-SysEventSource: Parser: parser raw message size=301, {"domain_":"ACE","name_":"JS_ERROR","type_":1,"time_":1638805263175,"pid_":821,"tid_":839,"PACKAGE_NAME":"","REASON":"Js Crash","SUMMARY":"Lifetime: 0.000000s
行 10432: 12-06 15:41:03.176 369 537 D 02d10/HiView-SysEventSource: Js-Engine: Quick JS
行 10433: 12-06 15:41:03.176 369 537 D 02d10/HiView-SysEventSource: Stacktrace: TypeError: cannot read property 'getAppPageStartConfig' of undefined
行 10434: 12-06 15:41:03.176 369 537 D 02d10/HiView-SysEventSource: at onPageShow (pages/EntryView.js)
行 10435: 12-06 15:41:03.176 369 537 D 02d10/HiView-SysEventSource: at onPageShow (pages/EntryView.js)
行 10472: 12-06 15:41:03.180 369 537 I 02d10/HiView-SysEventSource: Parser: parser result domain_=ACE eventName_=JS_ERROR
行 10473: 12-06 15:41:03.180 369 537 D 02d10/HiView-EventSource: PublishPipelineEvent: EventSource PublishPipelineEvent
行 10474: 12-06 15:41:03.180 369 547 I 02d10/HiView-SysEventService: Convert2SysEvent: domain is ACE, eventName is JS_ERROR.
行 10485: 12-06 15:41:03.180 369 547 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.232 369 547 I 02d10/HiView-DOCDB: open ejdb success
行 10838: 12-06 15:41:03.232 369 547 I 02d10/HiView-DOCDB: open doc store
行 11141: 12-06 15:41:03.249 369 547 D 02d10/HiView-DOCDB: put data to doc store success
行 11142: 12-06 15:41:03.250 369 547 D 02d10/HiView-SysEventDbMgr: SaveToStore: save sys event 1, JS_ERROR
行 11227: 12-06 15:41:03.253 369 547 I 02d10/Faultlogger: AddFaultLogIfNeed: Invalid module name
行 11229: 12-06 15:41:03.253 369 547 I 02d10/HiView-SysEventSource: Recycle: recycle resource
4 HiView
Hiview是一个跨平台的终端设备维测服务集。目前开源部分仅包含插件管理平台和系统事件源。
架构图如下:
Hiview由框架和插件组成,主要包含以下几部分:
- 操作系统适配层(adapter),对使用的系统服务的接口进行适配。
- Hiview基础定义(hiview base),包括插件基类、管道的定义,事件、事件队列定义以及一些工具类。
- Hiview的核心模块(hiview core),包括插件配置,插件管理以及事件源。
- Hiview服务(hiview services),目前仅包括hiview运行信息dump功能。
- Hiview插件(plugins),为独立功能的业务模块。
Hiview维测服务是由事件驱动的,其核心为分布在系统各处的HiSysEvent桩点。
格式化的事件通过HiSysEvent API上报至hiview进行处理,请参考第三节HiSysEvent的架构图。
- 1.应用框架、系统服务使用HiSysEvent组件上报系统事件。
- 2.Hiview中SysEventSource获取消息,解析并组装成管道事件分发给插件处理。
注:hiview目前并未对外提供接口。
5 FaultLoggerd
faultloggerd是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中
#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 HiAppEvent
HiAppEvent为JS应用提供事件打点接口,用于帮助应用记录在运行过程中发生的故障信息、统计信息、安全信息、用户行为信息,以支撑开发者分析应用的运行情况。
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表示事件校验失败,不执行事件异步打点操作。
6.1.2 打点配置接口
- function configure(config: ConfigOption): boolean;应用事件打点配置方法,可以对打点功能进行自定义配置。
- 参数config:应用事件打点配置项。
- 返回值:boolean,true表示配置成功,false表示配置失败。
- ConfigOption应用打点配置选项
| 配置名 | 类型|必填 |说明|
| ----- | ----- |----- | ----- |
| disable | boolean |否|应用打点功能开关,true表示关闭打点功能,false表示不关闭打点功能|
| maxStorage | string |否|打点数据本地存储文件所在目录的配额大小,默认限额为“10M”。所在目录大小超出限额后会对目录进行清理操作,会按从旧到新的顺序逐个删除打点数据文件,直到目录大小不超出限额时停止。|
6.2 接口使用
- 引入模块:
- 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=${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}`); });
- 应用打点配置
- 配置应用事件打点功能开关
hiAppEvent.configure({ disable: true });
- 配置事件文件目录存储限额大小
hiAppEvent.configure({ maxStorage: '15M' });
本文对标准系统目前已支持的DFX功能模块进行了介绍。demo请下载附件。
更多原创内容请关注: 深开鸿技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,共建鸿蒙生态,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
附件链接:
dfxdemo.zip
https://harmonyos.51cto.com/resource/1647
HiAppEventDemo.zip
https://harmonyos.51cto.com/resource/1646
https://harmonyos.51cto.com/#bkwz
Recommend
-
9
想了解更多内容,请访问:51CTO和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto...
-
9
OpenHarmony移植:XTS子系统之应用兼容性测试套件 2022年03月15日 03:05 · 阅读 80 本文分...
-
9
OpenHarmony—Graphic子系统之开机动画-51CTO.COM OpenHarmony—Graphic子系统之开机动画 作者:曹璀 2022-03-18 16:07:04 Graphic子系统 提供了图形接口能力和窗口管理接口能力, 支持应用程序框...
-
6
【OpenHarmony移植案例与原理】XTS子系统之应用兼容性测试用例开发 2022年03月23日 03:21 · 阅读 111
-
10
想了解更多内容,请访问:
-
8
想了解更多关于开源的内容,请访问:51CTO 开源基础软件社区https://ost.51cto.com
-
9
作者:李威 Wi-Fi是WLAN具体采用的技术,也是目前WLAN的主流技术。Wi-Fi采用的技术是IEEE80211系列协议,IEEE (Institute of Electrical and Electronics Engineers)是美国电气和电子工程师协会的简称。 STA模式:Station,类似于...
-
8
本文正在参加星光计划3.0–夏日挑战赛 作者:巴延兴 1. WiFi简介 1.1 WiFi介绍 WiFi是一种无线通信技术,可以将个人电脑、手持...
-
6
OpenHarmony源码解析之多模输入子系统(一) 作者:吴文璐 2023-04-06 09:14:11 本篇文章基于社区weekly_20230207的代码,对多模输入客户端注册监听流程和多模服务端事件派发流程作了简单介绍。相信大家通过本文,对...
-
5
想了解更多关于开源的内容,请访问:...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK