OpenHarmony源碼解析之DFX子系統-標準系統接口使用說明
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發送命令將日志落盤,設置指定
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命令行工具使用說明
注:落盤日志文件保存路徑為"/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
function write(string eventName, EventType type, object keyValues,
AsyncCallback
輸入參數說明:
- 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'
- });
7 總結
本文對標準系統目前已支持的DFX功能模塊進行了介紹。demo請下載附件。
https://harmonyos.51cto.com/resource/1646
https://harmonyos.51cto.com/resource/1647