HiLog 模块
1. 模块概述
源码:https://gitee.com/openharmony/hiviewdfx_hilog
1.1 功能与目标
主要功能:
HiLog是OpenHarmony操作系统的核心日志系统,为系统框架、服务和应用程序提供统一的日志打印、记录和管理功能。
核心目标:
- 提供高效、可靠的日志记录机制
- 支持多种日志类型(APP、CORE、INIT、KMSG)
- 实现日志的分级管理(DEBUG/INFO/WARN/ERROR/FATAL)
- 提供日志流控机制,防止日志打印过载
- 支持日志落盘和压缩存储
- 提供隐私保护机制
使用场景:
- 应用程序运行状态记录
- 系统框架调试信息输出
- 用户操作行为追踪
- 系统异常和错误记录
- 性能分析和问题定位
1.2 系统位置
HiLog模块位于OpenHarmony DFX(Design For X)子系统中,是系统基础设施的核心组件。
角色定位:
- 核心模块:为整个系统提供日志基础设施
- 服务提供者:通过hilogd常驻服务提供日志收集和管理
- 工具提供者:通过hilog命令行工具提供日志查询和控制
与其他模块的关系:
- 依赖模块:bounds_checking_function、c_utils、ffrt、init、napi、zlib、runtime_core
- 被依赖模块:几乎所有OpenHarmony子系统和应用
1.3 设计思路与模式
设计思路
-
客户端-服务端架构:采用C/S架构,客户端(应用进程)通过日志API发送日志,服务端(hilogd)负责收集、存储和管理日志。
-
环形缓冲区设计:使用Ring Buffer存储日志,实现高效的日志写入和读取。
-
Socket通信机制:使用Unix Domain Socket实现进程间通信,确保日志传输的可靠性。
-
分层架构:
- 接口层:提供C/C++/JS/Rust多语言接口
- 框架层:实现日志格式化和传输逻辑
- 服务层:hilogd服务端实现日志管理
设计模式
| 设计模式 | 应用场景 | 说明 |
|---|---|---|
| 单例模式 | LogKmsg | 内核日志收集器使用单例确保唯一实例 |
| 工厂模式 | LogCompress | 根据压缩类型创建不同的压缩器实例 |
| 观察者模式 | HilogBuffer | 通过回调通知新日志数据到达 |
| 策略模式 | LogCompress | 支持不同压缩算法(None/Zlib/Zstd) |
| 模板方法模式 | Socket | 定义Socket通信的基本流程 |
1.4 系统框图
OpenHarmony System 用户态进程 libhilog.so hilogd (常驻服务) hilog (命令行工具) HiLog API HiLog API HiLog API kmsg Unix Domain Socket Socket Application
Process C API
(log_c.h) Framework
Process C++ API
(log_cpp.h) Service
Process Kernel LogKmsg
(内核日志) Format
(vsnprintf) Socket Client LogCollector
(日志收集) HilogBuffer
(环形缓冲区) FlowControl
(流控) LogStats
(统计信息) LogPersister
(日志落盘) LogCompress
(压缩) ServiceController
(服务控制) Log Query
(日志查询) Log Display
(日志显示) Log Control
(日志控制) /data/log/hilog/
(日志落盘文件存储目录)
2. 模块结构
2.1 源文件与头文件
2.1.1 接口层 (interfaces/)
| 文件路径 | 功能描述 |
|---|---|
interfaces/native/innerkits/include/hilog/log.h |
主头文件,包含C和C++接口 |
interfaces/native/innerkits/include/hilog/log_c.h |
C语言日志接口定义 |
interfaces/native/innerkits/include/hilog/log_cpp.h |
C++日志接口定义 |
interfaces/native/innerkits/include/hilog_base/log_base.h |
基础日志接口 |
interfaces/native/innerkits/include/hilog_trace.h |
日志追踪接口 |
interfaces/rust/src/lib.rs |
Rust语言绑定 |
interfaces/js/kits/napi/ |
JavaScript NAPI接口 |
2.1.2 框架层 (frameworks/)
| 文件路径 | 功能描述 |
|---|---|
frameworks/libhilog/hilog.cpp |
HiLog C++类实现 |
frameworks/libhilog/hilog_printf.cpp |
日志格式化打印实现 |
frameworks/libhilog/base/hilog_base.c |
基础日志功能实现 |
frameworks/libhilog/include/hilog_common.h |
公共定义和常量 |
frameworks/libhilog/include/hilog_cmd.h |
命令和协议定义 |
frameworks/libhilog/vsnprintf/vsnprintf_s_p.c |
安全格式化函数 |
frameworks/libhilog/param/properties.cpp |
属性配置管理 |
frameworks/libhilog/socket/*.cpp |
Socket通信实现 |
frameworks/libhilog/utils/*.cpp |
工具函数 |
2.1.3 服务层 (services/)
hilogd服务:
| 文件路径 | 功能描述 |
|---|---|
services/hilogd/main.cpp |
服务入口 |
services/hilogd/service_controller.cpp |
服务控制器 |
services/hilogd/log_collector.cpp |
日志收集器 |
services/hilogd/log_buffer.cpp |
环形缓冲区实现 |
services/hilogd/log_persister.cpp |
日志持久化 |
services/hilogd/log_compress.cpp |
日志压缩 |
services/hilogd/flow_control.cpp |
流量控制 |
services/hilogd/log_stats.cpp |
统计信息 |
services/hilogd/log_kmsg.cpp |
内核日志收集 |
services/hilogd/cmd_executor.cpp |
命令执行器 |
hilog工具:
| 文件路径 | 功能描述 |
|---|---|
services/hilogtool/main.cpp |
工具入口和命令处理 |
services/hilogtool/log_display.cpp |
日志显示格式化 |
2.2 类、结构体、函数与方法
2.2.1 核心枚举类型
cpp
// 日志类型 (log_c.h)
typedef enum {
LOG_TYPE_MIN = 0,
LOG_APP = 0, // 应用日志
LOG_INIT = 1, // 启动阶段日志
LOG_CORE = 3, // 核心服务/框架日志
LOG_KMSG = 4, // 内核日志
LOG_ONLY_PRERELEASE = 5, // 仅预发布版本
LOG_TYPE_MAX
} LogType;
// 日志级别 (log_c.h)
typedef enum {
LOG_LEVEL_MIN = 0,
LOG_DEBUG = 3, // 调试信息
LOG_INFO = 4, // 一般信息
LOG_WARN = 5, // 警告
LOG_ERROR = 6, // 错误
LOG_FATAL = 7, // 致命错误
LOG_LEVEL_MAX,
} LogLevel;
// 控制命令 (hilog_cmd.h)
enum class IoctlCmd {
INVALID = -1,
OUTPUT_RQST = 1, // 日志输出请求
PERSIST_START_RQST, // 开始持久化
PERSIST_STOP_RQST, // 停止持久化
BUFFERSIZE_GET_RQST, // 获取缓冲区大小
BUFFERSIZE_SET_RQST, // 设置缓冲区大小
STATS_QUERY_RQST, // 查询统计信息
// ... 更多命令
};
2.2.2 核心结构体
cpp
// 日志标签 (log_cpp.h)
using HiLogLabel = struct {
LogType type; // 日志类型
unsigned int domain; // 域ID
const char *tag; // 标签
};
// 日志消息头 (hilog_cmd.h)
struct MsgHeader {
uint8_t ver; // 版本
uint8_t cmd; // 命令
int16_t err; // 错误码
uint16_t len; // 长度
} __attribute__((__packed__));
// 日志数据 (log_data.h)
struct HilogData {
uint16_t len; // 数据长度
uint16_t version : 3;
uint16_t type : 3; // 日志类型
uint16_t level : 4; // 日志级别
uint16_t tagLen : 6; // 标签长度
uint32_t tv_sec; // 时间戳(秒)
uint32_t tv_nsec; // 时间戳(纳秒)
uint32_t mono_sec; // 单调时间
uint32_t pid; // 进程ID
uint32_t tid; // 线程ID
uint32_t domain; // 域ID
char* tag; // 标签指针
char* content; // 内容指针
};
// 日志过滤器 (log_filter.h)
struct LogFilter {
uint16_t types; // 类型过滤
uint16_t levels; // 级别过滤
bool blackDomain; // 域黑名单模式
uint8_t domainCount; // 域数量
uint32_t domains[MAX_DOMAINS]; // 域列表
bool blackTag; // 标签黑名单模式
uint8_t tagCount; // 标签数量
char tags[MAX_TAGS][MAX_TAG_LEN]; // 标签列表
bool blackPid; // PID黑名单模式
int pidCount; // PID数量
uint32_t pids[MAX_PIDS]; // PID列表
char regex[MAX_REGEX_STR_LEN]; // 正则表达式
};
2.2.3 核心类
HiLog类 (C++接口)
cpp
namespace OHOS::HiviewDFX {
class HiLog final {
public:
static int Debug(const HiLogLabel &label, const char *fmt, ...);
static int Info(const HiLogLabel &label, const char *fmt, ...);
static int Warn(const HiLogLabel &label, const char *fmt, ...);
static int Error(const HiLogLabel &label, const char *fmt, ...);
static int Fatal(const HiLogLabel &label, const char *fmt, ...);
};
}
HilogBuffer类 (环形缓冲区)
cpp
class HilogBuffer {
public:
using LogMsgContainer = std::list<HilogData>;
using ReaderId = uintptr_t;
HilogBuffer(bool isSupportSkipLog);
~HilogBuffer();
size_t Insert(const HilogMsg& msg, bool& isFull);
std::optional<HilogData> Query(const LogFilter& filter,
const ReaderId& id, int tailCount = 0);
ReaderId CreateBufReader(std::function<void()> onNewDataCallback);
void RemoveBufReader(const ReaderId& id);
int32_t Delete(uint16_t logType);
int64_t GetBuffLen(uint16_t logType);
int32_t SetBuffLen(uint16_t logType, uint64_t buffSize);
private:
size_t sizeByType[LOG_TYPE_MAX];
LogMsgContainer hilogDataList;
std::shared_mutex hilogBufferMutex;
std::map<ReaderId, std::shared_ptr<BufferReader>> m_logReaders;
};
LogCollector类 (日志收集器)
cpp
class LogCollector {
public:
explicit LogCollector(HilogBuffer& buffer);
void InsertDropInfo(const HilogMsg &msg, int droppedCount);
size_t InsertLogToBuffer(const HilogMsg& msg);
void onDataRecv(const ucred& cred, std::vector<char>& data, int dataLen);
void SetLogFlowControl(bool on);
void SetDebuggable(bool on);
private:
HilogBuffer& m_hilogBuffer;
bool countEnable;
bool flowControl;
bool debug;
};
LogPersister类 (日志持久化)
cpp
class LogPersister : public std::enable_shared_from_this<LogPersister> {
public:
static std::shared_ptr<LogPersister> CreateLogPersister(HilogBuffer &buffer);
~LogPersister();
static int Kill(uint32_t id);
static int Query(std::list<LogPersistQueryResult> &results);
static int Refresh(uint32_t id);
static void Clear();
int Init(const PersistRecoveryInfo& msg, bool restore);
int Deinit();
void Start();
void Stop();
private:
std::unique_ptr<LogCompress> m_compressor;
std::unique_ptr<LogPersisterRotator> m_fileRotator;
std::thread m_persisterThread;
HilogBuffer &m_hilogBuffer;
};
ServiceController类 (服务控制器)
cpp
class ServiceController {
public:
static constexpr int MAX_DATA_LEN = 2048;
ServiceController(std::unique_ptr<Socket> communicationSocket,
LogCollector& collector,
HilogBuffer& hilogBuffer,
HilogBuffer& kmsgBuffer);
~ServiceController();
void CommunicationLoop(std::atomic<bool>& stopLoop, const CmdList& list);
private:
void HandleOutputRqst(const OutputRqst &rqst);
void HandlePersistStartRqst(const PersistStartRqst &rqst);
void HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst);
void HandleStatsQueryRqst(const StatsQueryRqst& rqst);
// ... 更多处理函数
std::unique_ptr<Socket> m_communicationSocket;
LogCollector& m_logCollector;
HilogBuffer& m_hilogBuffer;
HilogBuffer& m_kmsgBuffer;
};
LogCompress类 (日志压缩 - 策略模式)
cpp
class LogCompress {
public:
LogCompress() = default;
virtual ~LogCompress() = default;
virtual int Compress(const LogPersisterBuffer &inBuffer,
LogPersisterBuffer &compressBuffer) = 0;
static std::string CompressType2Str(uint16_t compressType);
static uint16_t Str2CompressType(const std::string& str);
};
class NoneCompress : public LogCompress {
int Compress(...) override;
};
class ZlibCompress : public LogCompress {
int Compress(...) override;
};
class ZstdCompress : public LogCompress {
int Compress(...) override;
};
Socket类 (网络通信)
cpp
class Socket {
public:
explicit Socket(int socketType);
~Socket();
bool CloseHandler();
int Create();
int Write(const char *data, unsigned int len);
int Read(char *buffer, unsigned int len);
protected:
int socketHandler;
uint32_t socketType;
struct ucred socketCred;
};
class SocketClient : public Socket {
public:
SocketClient(std::string serverPath, uint32_t socketType);
int Connect();
private:
sockaddr_un serverAddr;
};
class SocketServer {
public:
SocketServer(const std::string& socketName, uint32_t socketType);
int Init();
int Listen(unsigned int backlog);
int Accept();
};
2.2.4 核心函数
C语言接口函数
cpp
// 日志打印
int HiLogPrint(LogType type, LogLevel level, unsigned int domain,
const char *tag, const char *fmt, ...);
// 日志级别检查
bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level);
// 设置日志回调
void LOG_SetCallback(LogCallback callback);
// 设置最低日志级别
void HiLogSetAppMinLogLevel(LogLevel level);
// 获取最后一条致命日志
const char* GetLastFatalMessage(void);
宏定义接口
cpp
// C语言宏
#define HILOG_DEBUG(type, ...) ((void)HILOG_IMPL((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, __VA_ARGS__))
#define HILOG_INFO(type, ...) ((void)HILOG_IMPL((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, __VA_ARGS__))
#define HILOG_WARN(type, ...) ((void)HILOG_IMPL((type), LOG_WARN, LOG_DOMAIN, LOG_TAG, __VA_ARGS__))
#define HILOG_ERROR(type, ...) ((void)HILOG_IMPL((type), LOG_ERROR, LOG_DOMAIN, LOG_TAG, __VA_ARGS__))
#define HILOG_FATAL(type, ...) ((void)HILOG_IMPL((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, __VA_ARGS__))
// C++宏
#define HiLogDebug(label, fmt, ...) HILOG_IMPL(label.type, LOG_DEBUG, label.domain, label.tag, fmt, ##__VA_ARGS__)
#define HiLogInfo(label, fmt, ...) HILOG_IMPL(label.type, LOG_INFO, label.domain, label.tag, fmt, ##__VA_ARGS__)
#define HiLogWarn(label, fmt, ...) HILOG_IMPL(label.type, LOG_WARN, label.domain, label.tag, fmt, ##__VA_ARGS__)
#define HiLogError(label, fmt, ...) HILOG_IMPL(label.type, LOG_ERROR, label.domain, label.tag, fmt, ##__VA_ARGS__)
#define HiLogFatal(label, fmt, ...) HILOG_IMPL(label.type, LOG_FATAL, label.domain, label.tag, fmt, ##__VA_ARGS__)
2.3 类图
uses <<final>> HiLog +Debug(label, fmt, ...) : int +Info(label, fmt, ...) : int +Warn(label, fmt, ...) : int +Error(label, fmt, ...) : int +Fatal(label, fmt, ...) : int HiLogLabel +type : LogType +domain : unsigned int +tag : const char* ServiceController -m_communicationSocket : unique_ptr<Socket> -m_logCollector : LogCollector& -m_hilogBuffer : HilogBuffer& -m_kmsgBuffer : HilogBuffer& +CommunicationLoop(stopLoop, list) : void +HandleOutputRqst(rqst) : void +HandlePersistStartRqst(rqst) : void LogCollector -m_hilogBuffer : HilogBuffer& -countEnable : bool -flowControl : bool -debug : bool +InsertLogToBuffer(msg) : size_t +onDataRecv(cred, data, dataLen) : void +SetLogFlowControl(on) : void HilogBuffer -hilogDataList : LogMsgContainer -sizeByType : size_t[] -m_logReaders : map +Insert(msg, isFull) : size_t +Query(filter, id, tailCount) : optional<HilogData> +CreateBufReader(callback) : ReaderId +RemoveBufReader(id) : void HilogData +len : uint16_t +type : uint16_t +level : uint16_t +tagLen : uint16_t +tv_sec : uint32_t +tv_nsec : uint32_t +pid : uint32_t +tid : uint32_t +domain : uint32_t +tag : char* +content : char* LogPersister -m_compressor : unique_ptr<LogCompress> -m_fileRotator : unique_ptr<LogPersisterRotator> -m_hilogBuffer : HilogBuffer& +CreateLogPersister(buffer) : shared_ptr<LogPersister> +Init(msg, restore) : int +Start() : void +Stop() : void <<abstract>> LogCompress +Compress(inBuffer, compressBuffer) : int +CompressType2Str(compressType) : string +Str2CompressType(str) : uint16_t NoneCompress +Compress(inBuffer, compressBuffer) : int ZlibCompress +Compress(inBuffer, compressBuffer) : int ZstdCompress +Compress(inBuffer, compressBuffer) : int Socket #socketHandler : int #socketType : uint32_t #socketCred : ucred +Create() : int +Write(data, len) : int +Read(buffer, len) : int +CloseHandler() : bool SocketClient -serverAddr : sockaddr_un +Connect() : int SocketServer -socketHandler : int -serverAddr : sockaddr_un +Init() : int +Listen(backlog) : int +Accept() : int
2.4 模块内部依赖框图
services/ (服务层) frameworks/ (框架层) interfaces/ (接口层) hilogd/ libhilog socket/ include/ hilogtool/ main.cpp log_display.cpp main.cpp log_collector.cpp log_buffer.cpp log_persister.cpp log_compress.cpp flow_control.cpp log_stats.cpp log_kmsg.cpp service_controller.cpp cmd_executor.cpp hilog.cpp hilog_printf.cpp vsnprintf_s_p.c properties.cpp hilog_inner.h hilog_common.h hilog_cmd.h hilog_base.h socket.cpp socket_client.cpp hilog_input_socket_client.cpp log.h log_c.h log_cpp.h
3. 模块间交互
3.1 交互描述
3.1.1 与应用进程的交互
- 通信方式:Unix Domain Socket (SOCK_DGRAM)
- Socket名称 :
hilogInput - 数据格式:HilogMsg结构体
- 交互流程:应用调用HiLog API → 格式化日志 → 通过Socket发送到hilogd
3.1.2 与hilog工具的交互
- 输出Socket :
hilogOutput(用于日志查询) - 控制Socket :
hilogControl(用于配置和管理) - 通信协议:基于MsgHeader的请求-响应模式
3.1.3 与内核的交互
- 交互方式 :读取
/dev/kmsg设备文件 - 数据处理:LogKmsg类解析内核日志格式并转换为HilogData
3.1.4 外部依赖
| 依赖组件 | 用途 |
|---|---|
| bounds_checking_function | 安全字符串处理函数 |
| c_utils | 基础工具函数 |
| ffrt | 并发任务调度框架 |
| init | 系统初始化和属性服务 |
| napi | Node.js Native API (JS接口) |
| zlib | 日志压缩 |
| runtime_core | 运行时核心 |
3.1.5 多线程处理
hilogd服务使用多线程架构:
| 线程 | 功能 |
|---|---|
| 主线程 | 处理日志输出请求 |
| 控制线程 | 处理配置和管理命令 |
| 日志收集线程 | 接收应用日志 |
| 持久化线程 | 日志落盘任务 |
| Kmsg线程 | 内核日志收集 |
3.2 外部依赖框图
文件系统 内核空间 HiLog Module 用户空间应用 libhilog.so libhilog.so napi hilog_rust libhilog.so Unix Domain Socket Socket /data/log/hilog/
(日志落盘目录)
- hilog.000.20170805-170154.gz
- hilog_kmsg.000.20170805-170430.gz /dev/kmsg
(内核日志设备) hilogd External Dependencies zlib
(压缩) ffrt
(并发) c_utils
(工具) init (系统属性服务) - persist.sys.hilog.stats
- hilog.loggable.global
- hilog.private.on bounds_checking_function
- strncpy_s, memcpy_s, sprintf_s ... hilog
(命令行工具) C API C++ API JS API Rust API Socket Client Native App JS App Rust App Framework
4. 状态机转换图
4.1 状态机模型
HiLog模块包含多个状态机,主要涉及:
- hilogd服务状态机
- 日志持久化任务状态机
- 流控状态机
4.2 状态机树图
HiLog System hilogd Service State Machine LogPersister Task State Machine Flow Control State Machine Buffer State Machine Uninitialized (未初始化) Initializing (初始化中) Running (运行中) Stopping (停止中) Collecting (收集日志) Processing (处理命令) Persisting (持久化) Idle (空闲) Initializing (初始化中) Running (运行中) Refreshing (刷新中) Stopped (已停止) Receiving (接收日志) Compressing (压缩) Writing (写入文件) Normal (正常) Warning (警告) Throttling (限流中) Empty (空) Available (可用) Full (满) Overflow (溢出)
4.3 状态切换规则
4.3.1 hilogd服务状态机
| 当前状态 | 事件/条件 | 目标状态 | 动作 |
|---|---|---|---|
| Uninitialized | 系统启动 | Initializing | 初始化资源 |
| Initializing | 初始化完成 | Running | 启动服务循环 |
| Initializing | 初始化失败 | Uninitialized | 清理资源 |
| Running | 收到SIGINT | Stopping | 停止服务 |
| Running | 收到日志 | Running | 处理日志 |
| Stopping | 资源释放完成 | Uninitialized | 退出进程 |
4.3.2 日志持久化任务状态机
| 当前状态 | 事件/条件 | 目标状态 | 动作 |
|---|---|---|---|
| Idle | Start命令 | Initializing | 创建文件和压缩器 |
| Initializing | 初始化成功 | Running | 启动接收线程 |
| Initializing | 初始化失败 | Idle | 清理资源 |
| Running | 新日志到达 | Running | 写入日志 |
| Running | 缓冲区满 | Running | 压缩并写入文件 |
| Running | Refresh命令 | Refreshing | 刷新缓冲区 |
| Running | Stop命令 | Stopped | 停止线程 |
| Refreshing | 刷新完成 | Running | 继续接收 |
| Stopped | Start命令 | Initializing | 重新初始化 |
4.3.3 流控状态机
| 当前状态 | 事件/条件 | 目标状态 | 动作 |
|---|---|---|---|
| Normal | 日志量 < 阈值 | Normal | 正常处理 |
| Normal | 日志量 >= 警告阈值 | Warning | 记录警告 |
| Warning | 日志量 >= 限流阈值 | Throttling | 开始丢弃日志 |
| Warning | 日志量 < 警告阈值 | Normal | 恢复正常 |
| Throttling | 日志量 < 限流阈值 | Warning | 减少丢弃 |
| Throttling | 超时周期结束 | Normal | 重置计数 |
4.4 状态机转换图
4.4.1 hilogd服务状态机
系统启动 初始化失败 资源释放完成 初始化成功 SIGINT信号 Uninitialized Initializing Running 收到命令 命令处理完成 触发落盘 落盘完成 Collecting Processing Persisting Stopping
4.4.2 日志持久化任务状态机
Start命令 初始化失败 Start命令 初始化成功 Refresh命令 刷新完成 Stop命令 Idle Initializing Running 缓冲区满 压缩完成 写入完成 Receiving Compressing Writing Refreshing Stopped
4.4.3 流控状态机
日志量 < 阈值 日志量 >= 警告阈值 日志量 < 警告阈值 日志量 >= 限流阈值 日志量 < 限流阈值 超时周期结束 继续丢弃日志 Normal Warning Throttling
5. 接口设计
5.1 公共接口
5.1.1 C语言接口
HiLogPrint - 日志打印
cpp
/**
* @brief 打印日志
* @param type 日志类型 (LOG_APP/LOG_CORE/LOG_INIT等)
* @param level 日志级别 (LOG_DEBUG/LOG_INFO/LOG_WARN/LOG_ERROR/LOG_FATAL)
* @param domain 域ID (APP: 0-0xFFFF, CORE: 0xD000000-0xD0FFFFF)
* @param tag 日志标签
* @param fmt 格式化字符串
* @return 成功返回写入字节数,失败返回-1
*/
int HiLogPrint(LogType type, LogLevel level, unsigned int domain,
const char *tag, const char *fmt, ...);
HiLogIsLoggable - 检查日志级别
cpp
/**
* @brief 检查指定域和标签的日志是否可打印
* @param domain 域ID
* @param tag 日志标签
* @param level 日志级别
* @return true: 可打印, false: 不可打印
*/
bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level);
LOG_SetCallback - 设置日志回调
cpp
/**
* @brief 设置用户自定义日志处理回调
* @param callback 回调函数指针,NULL表示取消回调
* @since 11
*/
void LOG_SetCallback(LogCallback callback);
// 回调函数类型定义
typedef void (*LogCallback)(const LogType type, const LogLevel level,
const unsigned int domain, const char *tag,
const char *msg);
HiLogSetAppMinLogLevel - 设置最低日志级别
cpp
/**
* @brief 设置应用进程的最低日志级别
* @param level 日志级别
* @since 15
*/
void HiLogSetAppMinLogLevel(LogLevel level);
GetLastFatalMessage - 获取最后一条致命日志
cpp
/**
* @brief 获取最后一条FATAL级别日志
* @return 日志内容字符串
*/
const char* GetLastFatalMessage(void);
5.1.2 C++接口
HiLog类静态方法
cpp
namespace OHOS::HiviewDFX {
class HiLog final {
public:
/**
* @brief 打印DEBUG级别日志
* @param label 日志标签结构体
* @param fmt 格式化字符串
* @return 成功返回写入字节数,失败返回-1
*/
static int Debug(const HiLogLabel &label, const char *fmt, ...);
/**
* @brief 打印INFO级别日志
*/
static int Info(const HiLogLabel &label, const char *fmt, ...);
/**
* @brief 打印WARN级别日志
*/
static int Warn(const HiLogLabel &label, const char *fmt, ...);
/**
* @brief 打印ERROR级别日志
*/
static int Error(const HiLogLabel &label, const char *fmt, ...);
/**
* @brief 打印FATAL级别日志
*/
static int Fatal(const HiLogLabel &label, const char *fmt, ...);
};
}
5.1.3 宏接口
C语言宏
cpp
// 使用前需定义 LOG_DOMAIN 和 LOG_TAG
#define LOG_DOMAIN 0x0001
#define LOG_TAG "MyModule"
// 日志打印宏
HILOG_DEBUG(LOG_CORE, "Debug message: %{public}d", value);
HILOG_INFO(LOG_CORE, "Info message: %{public}s", str);
HILOG_WARN(LOG_CORE, "Warning message");
HILOG_ERROR(LOG_CORE, "Error message: %{private}s", privateData);
HILOG_FATAL(LOG_CORE, "Fatal error!");
C++宏
cpp
// 定义日志标签
constexpr HiLogLabel LABEL = {LOG_CORE, 0xD001234, "MyModule"};
// 日志打印宏
HiLogDebug(LABEL, "Debug: %{public}d", value);
HiLogInfo(LABEL, "Info: %{public}s", str);
HiLogWarn(LABEL, "Warning");
HiLogError(LABEL, "Error: %{private}s", data);
HiLogFatal(LABEL, "Fatal!");
5.2 数据交换接口
5.2.1 Socket通信协议
消息头格式
cpp
struct MsgHeader {
uint8_t ver; // 协议版本,当前为0
uint8_t cmd; // 命令类型 (IoctlCmd枚举值)
int16_t err; // 错误码
uint16_t len; // 数据长度
} __attribute__((__packed__));
日志输出请求/响应
cpp
// 请求
struct OutputRqst {
uint16_t headLines; // 显示头部行数
uint16_t types; // 日志类型过滤
uint16_t levels; // 日志级别过滤
bool blackDomain; // 域黑名单模式
uint8_t domainCount; // 域数量
uint32_t domains[MAX_DOMAINS]; // 域列表
bool blackTag; // 标签黑名单模式
uint8_t tagCount; // 标签数量
char tags[MAX_TAGS][MAX_TAG_LEN]; // 标签列表
bool blackPid; // PID黑名单模式
int pidCount; // PID数量
uint32_t pids[MAX_PIDS]; // PID列表
char regex[MAX_REGEX_STR_LEN]; // 正则表达式
bool noBlock; // 非阻塞模式
uint16_t tailLines; // 显示尾部行数
} __attribute__((__packed__));
// 响应
struct OutputRsp {
uint16_t len; // 数据长度
uint8_t level; // 日志级别
uint8_t type; // 日志类型
uint32_t pid; // 进程ID
uint32_t tid; // 线程ID
uint32_t domain; // 域ID
uint32_t tv_sec; // 时间戳(秒)
uint32_t tv_nsec; // 时间戳(纳秒)
uint32_t mono_sec; // 单调时间
uint8_t tagLen; // 标签长度
bool end; // 是否结束
char data[]; // 标签和内容
} __attribute__((__packed__));
持久化任务请求/响应
cpp
// 开始持久化请求
struct PersistStartRqst {
OutputRqst outputFilter; // 日志过滤条件
uint32_t jobId; // 任务ID
uint32_t fileSize; // 单文件大小
uint16_t fileNum; // 文件数量
char fileName[MAX_FILE_NAME_LEN]; // 文件名
char stream[MAX_STREAM_NAME_LEN]; // 压缩算法
} __attribute__((__packed__));
// 停止持久化请求
struct PersistStopRqst {
uint32_t jobId; // 任务ID (0表示停止所有)
} __attribute__((__packed__));
5.3 接口调用时序图
5.3.1 日志打印时序图
App Process libhilog.so Socket Client hilogd Service HilogBuffer HiLogPrint() Format Log Send formatted log Unix Domain Socket Insert() Notify Reader Success ACK Return return bytes App Process libhilog.so Socket Client hilogd Service HilogBuffer
5.3.2 日志查询时序图
hilog Tool LogIoctl Socket Client hilogd Service HilogBuffer QueryLog() OutputRqst Connect() Send Request Query() HilogData OutputRsp OutputRsp Display Log Query() HilogData OutputRsp OutputRsp Display Log loop [Until end=true] hilog Tool LogIoctl Socket Client hilogd Service HilogBuffer
5.3.3 持久化任务启动时序图
hilog Tool LogIoctl hilogd Service LogPersister LogCompress -w start PersistStartRqst CreateLogPersister() InitCompression() Compressor Init() Start() Start Thread PersistStartRsp Job Started hilog Tool LogIoctl hilogd Service LogPersister LogCompress
5.3.4 hilogd服务启动时序图
main() HilogBuffer LogCollector InputServer CmdExecutor Create Buffer Create Collector Create InputServer Init() RunServingThread() Create CmdExecutor (Control) Start Thread Create CmdExecutor (Output) MainLoop() Loop main() HilogBuffer LogCollector InputServer CmdExecutor
附录
A. 常量定义
| 常量名 | 值 | 说明 |
|---|---|---|
| MAX_LOG_LEN | 4096 | 单条日志最大长度 |
| MAX_TAG_LEN | 32 | 标签最大长度 |
| MAX_DOMAINS | 5 | 最大域过滤数量 |
| MAX_TAGS | 10 | 最大标签过滤数量 |
| MAX_PIDS | 5 | 最大PID过滤数量 |
| MIN_BUFFER_SIZE | 64KB | 缓冲区最小大小 |
| MAX_BUFFER_SIZE | 16MB | 缓冲区最大大小 |
| MIN_LOG_FILE_SIZE | 64KB | 日志文件最小大小 |
| MAX_LOG_FILE_SIZE | 512MB | 日志文件最大大小 |
| MIN_LOG_FILE_NUM | 2 | 最小日志文件数量 |
| MAX_LOG_FILE_NUM | 1000 | 最大日志文件数量 |
| DOMAIN_OS_MIN | 0xD000000 | 系统域ID最小值 |
| DOMAIN_OS_MAX | 0xD0FFFFF | 系统域ID最大值 |
| DOMAIN_APP_MIN | 0x0 | 应用域ID最小值 |
| DOMAIN_APP_MAX | 0xFFFF | 应用域ID最大值 |
B. 错误码定义
| 错误码 | 值 | 说明 |
|---|---|---|
| RET_SUCCESS | 0 | 成功 |
| RET_FAIL | -1 | 失败 |
| ERR_LOG_LEVEL_INVALID | -2 | 无效的日志级别 |
| ERR_LOG_TYPE_INVALID | -3 | 无效的日志类型 |
| ERR_INVALID_RQST_CMD | -4 | 无效的请求命令 |
| ERR_DOMAIN_INVALID | -19 | 无效的域ID |
| ERR_MSG_LEN_INVALID | -21 | 无效的消息长度 |
| ERR_BUFF_SIZE_INVALID | -30 | 无效的缓冲区大小 |
| ERR_SOCKET_CLIENT_INIT_FAIL | -46 | Socket客户端初始化失败 |
C. hilog命令行参数
| 参数 | 说明 |
|---|---|
| -h, --help | 显示帮助信息 |
| -x, --exit | 非阻塞读取日志 |
| -a, --head=<n> | 显示前n行日志 |
| -z, --tail=<n> | 显示后n行日志 |
| -t, --type=<type> | 指定日志类型 |
| -L, --level=<level> | 指定日志级别 |
| -D, --domain=<domain> | 指定域ID |
| -T, --tag=<tag> | 指定标签 |
| -P, --pid=<pid> | 指定进程ID |
| -e, --regex=<expr> | 正则表达式过滤 |
| -r | 清除缓冲区日志 |
| -g | 查询缓冲区大小 |
| -G, --buffer-size=<size> | 设置缓冲区大小 |
| -s, --statistics | 查询统计信息 |
| -S | 清除统计信息 |
| -w, --write=<control> | 落盘任务控制 |
| -b, --baselevel=<level> | 设置日志级别 |
| -p, --privacy=<on/off> | 隐私开关控制 |
| -k, --kmsg=<on/off> | 内核日志开关 |
| -Q <control-type> | 流控开关控制 |