12

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明

 3 years ago
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.
neoserver,ios ssh client

作者:吴文璐

1 DFX简介

DFX(Design for X)子系统是为了提升软件质量设计的工具集,目前包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性。
目前标准系统已实现以下功能:

  • HiLog:流水日志。
  • HiSysEvent:系统事件记录接口。
  • HiView:插件平台。
  • FaultLoggerd:应用故障订阅和收集。
  • HiAppEvent: js应用事件记录接口。

1.1 OpenHarmony架构图

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_DFX子系统
注:本文只介绍DFX各组件的使用,后续会有文章单独分析各组件的源码。

2 Hilog

HiLog是日志系统,提供给系统框架、服务、以及应用打印日志,记录用户操作、系统运行状态等。
用户态Process通过日志接口将日志内容写入hilogd buffer中,用户态的hilog工具支持将日志输出到控制台(console)进行查看,同时也支持通过hilog工具给hilogd发送命令将日志落盘,设置指定<type>日志类型缓冲区的大小等。

HiLog架构图如下:
OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_源码解析_02
注:目前代码暂未看到有支持读取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说明

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_开鸿HarmonyOS_03

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上报系统事件信息。通过在关键路径埋点记录系统在运行过程中的重要信息,辅助开发者定位问题。
OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_开鸿HarmonyOS_04

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是一个跨平台的终端设备维测服务集。目前开源部分仅包含插件管理平台和系统事件源。
架构图如下:
OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_Hiview_05
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应用提供事件打点接口,用于帮助应用记录在运行过程中发生的故障信息、统计信息、安全信息、用户行为信息,以支撑开发者分析应用的运行情况。
OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_Hiview_06

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

 想了解更多关于鸿蒙的内容,请访问:

 51CTO和华为官方合作共建的鸿蒙技术社区

 https://harmonyos.51cto.com/#bkwz

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明_Hiview_07


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK