diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..81e03366da1f2d100a1b209acd1c6c5150bd1d8a --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +target +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ccd77977019170bba8232cc0cb1012a0c23e7204 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[workspace] +members = [ + "interfaces/rust", +] diff --git a/README_zh.md b/README_zh.md index 7e305df0ea964d00a81b8b76576a8e134e60d631..00091bfea736ee9c833eea5ade7561316b7e23dc 100644 --- a/README_zh.md +++ b/README_zh.md @@ -20,7 +20,7 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 ![](figures/zh-cn_image_0000001115534242.png) -用户态Process通过日志接口将日志内容写入hilogd buffer中,用户态的hilog工具支持将输出到控制台(console)进行查看,同时也支持通过hilog工具给hilogd发送命令将日志落盘。 +用户态Process通过日志接口将日志内容写入hilogd buffer中,用户态的hilog工具支持将日志输出到控制台(console)进行查看,同时也支持通过hilog工具给hilogd发送命令将日志落盘。 下述主要任务的详细内容: diff --git a/bundle.json b/bundle.json index c465107f25265018f53c9fc54cd55d2de2daef1e..af6b26811afed3538e2da2ccf2c6f506976b402e 100644 --- a/bundle.json +++ b/bundle.json @@ -18,20 +18,74 @@ "adapted_system_type": [ "standard" ], - "rom": "188KB", - "ram": "2000KB", + "rom": "648KB", + "ram": "16336KB", "deps": { "components": [ "init", - "utils_base" + "napi", + "c_utils" ], "third_party": [ "bounds_checking_function", "zlib" ] }, + "features": [ + "hilog_native_feature_ohcore" + ], "build": { - "sub_component": [] + "sub_component": [ + "//base/hiviewdfx/hilog/services/hilogtool:hilog", + "//base/hiviewdfx/hilog/services/hilogd:hilogd", + "//base/hiviewdfx/hilog/interfaces/js:hilog_napi", + "//base/hiviewdfx/hilog/frameworks/hilog_ndk:hilog_ndk", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_base", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//base/hiviewdfx/hilog/interfaces/rust:hilog_rust" + ], + "inner_kits": [ + { + "name": "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "header": { + "header_files": [ + "hilog/log.h", + "hilog/log_c.h", + "hilog/log_cpp.h", + "hilog_trace.h" + ], + "header_base": "//base/hiviewdfx/hilog/interfaces/native/innerkits/include" + } + }, + { + "name": "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_base", + "header": { + "header_files": [ + "hilog_base/log_base.h" + ], + "header_base": "//base/hiviewdfx/hilog/interfaces/native/innerkits/include" + } + }, + { + "name": "//base/hiviewdfx/hilog/interfaces/rust:hilog_rust", + "header": { + "header_files": [], + "header_base": [] + } + }, + { + "name": "//base/hiviewdfx/hilog/frameworks/hilog_ndk:hilog_ndk", + "header": { + "header_files": [], + "header_base": [] + } + } + ], + "test": [ + "//base/hiviewdfx/hilog/test:hilog_unittest", + "//base/hiviewdfx/hilog/test:hilog_moduletest", + "//base/hiviewdfx/hilog/test:fuzztest" + ] } } } \ No newline at end of file diff --git a/frameworks/hilog_ndk/BUILD.gn b/frameworks/hilog_ndk/BUILD.gn index 08c35f8746c3b8194f5c44b77296a4286707c5e0..c767d417b737630b3492a046e1dc84a0f487a7cd 100644 --- a/frameworks/hilog_ndk/BUILD.gn +++ b/frameworks/hilog_ndk/BUILD.gn @@ -14,6 +14,11 @@ import("//build/ohos.gni") ohos_shared_library("hilog_ndk") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", "//base/hiviewdfx/hilog/frameworks/include/", @@ -21,13 +26,13 @@ ohos_shared_library("hilog_ndk") { sources = [ "hilog_ndk.c" ] - external_deps = [ "hilog_native:libhilog" ] + deps = [ "../../interfaces/native/innerkits:libhilog" ] install_images = [ system_base_dir, "updater", ] - relative_install_dir = "ndk" - part_name = "hilog_native" + innerapi_tags = [ "ndk" ] + part_name = "hilog" subsystem_name = "hiviewdfx" } diff --git a/frameworks/hilog_ndk/hilog_ndk.c b/frameworks/hilog_ndk/hilog_ndk.c index 79466f37b8474b471a4bc221788b174296f90409..792cca33b1bb36f77ef5ba3dd7f83ead87d7224c 100644 --- a/frameworks/hilog_ndk/hilog_ndk.c +++ b/frameworks/hilog_ndk/hilog_ndk.c @@ -32,3 +32,8 @@ bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level) { return HiLogIsLoggable(domain, tag, level); } + +void OH_LOG_SetCallback(LogCallback callback) +{ + return LOG_SetCallback(callback); +} diff --git a/frameworks/libhilog/BUILD.gn b/frameworks/libhilog/BUILD.gn index fe1a6623f28b1293597e14f5cd228e2a27a2cf48..14076ba2e2e1ae0b02e587d7fe517d671d978f9c 100644 --- a/frameworks/libhilog/BUILD.gn +++ b/frameworks/libhilog/BUILD.gn @@ -79,13 +79,15 @@ template("libhilog_source") { sources += vsnprintf_sources defines = [] + cflags_cc = [ "-Wno-deprecated-declarations" ] if (platform == "windows") { - cflags_cc = [ "-std=c++17" ] + cflags_cc += [ "-std=c++17" ] defines += [ "__WINDOWS__" ] } else if (platform == "mac") { + cflags_cc += [ "-std=c++17" ] defines += [ "__MAC__" ] } else if (platform == "linux") { - cflags_cc = [ "-std=c++17" ] + cflags_cc += [ "-std=c++17" ] defines += [ "__LINUX__" ] } else { defines = [ "__RECV_MSG_WITH_UCRED_" ] @@ -93,6 +95,8 @@ template("libhilog_source") { defines += [ "HILOG_USE_MUSL" ] } } + + cflags = [ "-Wno-deprecated-declarations" ] public_configs = [ ":libhilog_config" ] configs = [ ":libhilog_config" ] @@ -102,7 +106,7 @@ template("libhilog_source") { external_deps = [ "init:libbegetutil" ] } - part_name = "hilog_native" + part_name = "hilog" subsystem_name = "hiviewdfx" } } @@ -129,6 +133,7 @@ ohos_source_set("libhilog_base_source") { sources = [ "$libhilog_base_root/hilog_base.cpp" ] sources += vsnprintf_sources + cflags = [ "-Wno-deprecated-declarations" ] defines = [ "__RECV_MSG_WITH_UCRED_", "HILOG_PROHIBIT_ALLOCATION", @@ -136,6 +141,6 @@ ohos_source_set("libhilog_base_source") { public_configs = [ ":libhilog_base_config" ] configs = [ ":libhilog_base_config" ] - part_name = "hilog_native" + part_name = "hilog" subsystem_name = "hiviewdfx" } diff --git a/frameworks/libhilog/base/hilog_base.cpp b/frameworks/libhilog/base/hilog_base.cpp index be974f150ae7e911b63273877345d7c86063dbe3..1d14d5d8e6f4f433e88292dd5c689350b819f504 100644 --- a/frameworks/libhilog/base/hilog_base.cpp +++ b/frameworks/libhilog/base/hilog_base.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,10 @@ namespace { constexpr int SOCKET_TYPE = SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC; constexpr int INVALID_SOCKET = -1; -constexpr sockaddr_un SOCKET_ADDR = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME}; +constexpr size_t HILOG_VEC_MAX_SIZE = 4; +constexpr size_t HILOG_VEC_SIZE_OHCORE = 4; +constexpr size_t HILOG_VEC_SIZE_OH = 3; +constexpr int32_t MAX_DOMAIN_TAGSIZE = 64; struct SocketHandler { std::atomic_int socketFd {INVALID_SOCKET}; @@ -45,12 +49,82 @@ struct SocketHandler { } }; +typedef struct LogTime { + uint32_t tvSec; + uint32_t tvNsec; +} __attribute__((__packed__)) LogTime; + +typedef struct __attribute__((__packed__)) { + uint8_t id; + uint16_t tid; + uint16_t ohPid; + LogTime realtime; +} LogHeader; + +struct HiLogMsgInfo { + HilogMsg *header_; + const char *tag_; + uint16_t tagLen_; + const char *fmt_; + uint16_t fmtLen_; + HiLogMsgInfo(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) + { + header_ = header; + tag_ = tag; + tagLen_ = tagLen; + fmt_ = fmt; + fmtLen_ = fmtLen; + } +}; + +typedef enum { + TYPE_OH = 0, + TYPE_OHCORE = 1, +} HiLogProtocolType; + +sockaddr_un g_sockAddr = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME}; +HiLogProtocolType g_protocolType = TYPE_OH; + +struct Initializer { + Initializer() + { + constexpr char configFile[] = "/system/etc/hilog_config"; + if (access(configFile, F_OK) != 0) { + return; + } + std::ifstream file; + file.open(configFile); + if (file.fail()) { + std::cerr << "open hilog_config config file failed" << std::endl; + return; + } + + std::string sock; + std::string protocol; + file >> sock >> protocol; + if (auto posColon = sock.find(":"); posColon != sock.npos) { + std::string sockPath = sock.substr(posColon + 1); + size_t pos = 0; + while (pos < sockPath.size() && pos < (sizeof(g_sockAddr.sun_path) - 1)) { + g_sockAddr.sun_path[pos] = sockPath[pos]; + pos++; + } + g_sockAddr.sun_path[pos] = '\0'; + } + if (auto posColon = protocol.find(":"); posColon != protocol.npos) { + g_protocolType = protocol.substr(posColon + 1) == "ohcore" ? TYPE_OHCORE : TYPE_OH; + } + file.close(); + } +}; +Initializer g_initializer; + static int GenerateFD() { - int tmpFd = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCKET_TYPE, 0)); + int tmpFd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); int res = tmpFd; if (tmpFd == 0) { - res = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCKET_TYPE, 0)); + res = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); close(tmpFd); } return res; @@ -65,7 +139,7 @@ static int CheckSocket(SocketHandler& socketHandler) int fd = GenerateFD(); if (fd < 0) { - std::cerr << "Can't get hilog socket! Errno: " << errno << "\n"; + std::cerr << "Can't get hilog socket! Errno: " << errno << std::endl; return fd; } @@ -90,15 +164,62 @@ static int CheckConnection(SocketHandler& socketHandler) } auto result = TEMP_FAILURE_RETRY(connect(socketHandler.socketFd.load(), - reinterpret_cast(&SOCKET_ADDR), sizeof(SOCKET_ADDR))); + reinterpret_cast(&g_sockAddr), sizeof(g_sockAddr))); if (result < 0) { - std::cerr << "Can't connect to hilog server. Errno: " << errno << "\n"; return result; } socketHandler.isConnected.store(true); return 0; } +static size_t BuildHilogMessageForOhCore(struct HiLogMsgInfo* logMsgInfo, LogHeader& logHeader, uint16_t& logLevel, + char tagBuf[], struct iovec *vec) +{ + struct timespec ts = {0}; + (void)clock_gettime(CLOCK_REALTIME, &ts); + logHeader.realtime.tvSec = static_cast(ts.tv_sec); + logHeader.realtime.tvNsec = static_cast(ts.tv_nsec); + logHeader.tid = static_cast(gettid()); + logHeader.ohPid = static_cast(getpid()); + logLevel = logMsgInfo->header_->level; + constexpr uint32_t domainFilter = 0x000FFFFF; + if (vsnprintfp_s(tagBuf, MAX_DOMAIN_TAGSIZE, MAX_DOMAIN_TAGSIZE - 1, false, "%05X/%s", + (logMsgInfo->header_->domain & domainFilter), logMsgInfo->tag_) < 0) { + return 0; + } + + vec[0].iov_base = reinterpret_cast(&logHeader); // 0 : index of hos log header + vec[0].iov_len = sizeof(logHeader); // 0 : index of hos log header + vec[1].iov_base = reinterpret_cast(&logLevel); // 1 : index of log level + vec[1].iov_len = 1; // 1 : index of log level + vec[2].iov_base = reinterpret_cast(const_cast(tagBuf)); // 2 : index of log tag + vec[2].iov_len = strlen(tagBuf) + 1; // 2 : index of log tag + vec[3].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 3 : index of log format + vec[3].iov_len = logMsgInfo->fmtLen_; // 3 : index of log format + return HILOG_VEC_SIZE_OHCORE; +} + +static size_t BuildHilogMessageForOh(struct HiLogMsgInfo* logMsgInfo, struct iovec *vec) +{ + struct timespec ts = {0}; + (void)clock_gettime(CLOCK_REALTIME, &ts); + struct timespec tsMono = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &tsMono); + logMsgInfo->header_->tv_sec = static_cast(ts.tv_sec); + logMsgInfo->header_->tv_nsec = static_cast(ts.tv_nsec); + logMsgInfo->header_->mono_sec = static_cast(tsMono.tv_sec); + logMsgInfo->header_->len = sizeof(HilogMsg) + logMsgInfo->tagLen_ + logMsgInfo->fmtLen_; + logMsgInfo->header_->tag_len = logMsgInfo->tagLen_; + + vec[0].iov_base = logMsgInfo->header_; // 0 : index of hos log header + vec[0].iov_len = sizeof(HilogMsg); // 0 : index of hos log header + vec[1].iov_base = reinterpret_cast(const_cast(logMsgInfo->tag_)); // 1 : index of log tag + vec[1].iov_len = logMsgInfo->tagLen_; // 1 : index of log tag + vec[2].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 2 : index of log content + vec[2].iov_len = logMsgInfo->fmtLen_; // 2 : index of log content + return HILOG_VEC_SIZE_OH; +} + static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) { SocketHandler socketHandler; @@ -111,25 +232,19 @@ static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const return ret; } - struct timespec ts = {0}; - (void)clock_gettime(CLOCK_REALTIME, &ts); - struct timespec tsMono = {0}; - (void)clock_gettime(CLOCK_MONOTONIC, &tsMono); - header->tv_sec = static_cast(ts.tv_sec); - header->tv_nsec = static_cast(ts.tv_nsec); - header->mono_sec = static_cast(tsMono.tv_sec); - header->len = sizeof(HilogMsg) + tagLen + fmtLen; - header->tag_len = tagLen; - - std::array vec; - vec[0].iov_base = header; // 0 : index of hos log header - vec[0].iov_len = sizeof(HilogMsg); // 0 : index of hos log header - vec[1].iov_base = reinterpret_cast(const_cast(tag)); // 1 : index of log tag - vec[1].iov_len = tagLen; // 1 : index of log tag - vec[2].iov_base = reinterpret_cast(const_cast(fmt)); // 2 : index of log content - vec[2].iov_len = fmtLen; // 2 : index of log content - ret = TEMP_FAILURE_RETRY(::writev(socketHandler.socketFd.load(), vec.data(), vec.size())); - return ret; + struct iovec vec[HILOG_VEC_MAX_SIZE]; + struct HiLogMsgInfo msgInfo(header, tag, tagLen, fmt, fmtLen); + LogHeader logHeader; + uint16_t logLevel = 0; + char tagBuf[MAX_DOMAIN_TAGSIZE] = {0}; + auto vecSize = (g_protocolType == TYPE_OHCORE) ? + BuildHilogMessageForOhCore(&msgInfo, logHeader, logLevel, tagBuf, vec) : + BuildHilogMessageForOh(&msgInfo, vec); + if (vecSize == 0) { + std::cerr << "BuildHilogMessage failed ret = " << vecSize << std::endl; + return RET_FAIL; + } + return TEMP_FAILURE_RETRY(::writev(socketHandler.socketFd.load(), vec, vecSize)); } static int HiLogBasePrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, diff --git a/frameworks/libhilog/hilog_printf.cpp b/frameworks/libhilog/hilog_printf.cpp index 31ac2d9aed30ee1da3ecce57caa186b5d2f8a134..cc79daa1cf51bb237c2754ad8c67124f053e68f5 100644 --- a/frameworks/libhilog/hilog_printf.cpp +++ b/frameworks/libhilog/hilog_printf.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #ifdef __LINUX__ #include @@ -27,6 +30,7 @@ #ifndef __WINDOWS__ #include +#include #else #include #include @@ -51,6 +55,7 @@ using namespace std; using namespace OHOS::HiviewDFX; static RegisterFunc g_registerFunc = nullptr; +static LogCallback g_logCallback = nullptr; static atomic_int g_hiLogGetIdCallCount = 0; // protected by static lock guard static char g_hiLogLastFatalMessage[MAX_LOG_LEN] = { 0 }; // MAX_lOG_LEN : 1024 @@ -84,6 +89,11 @@ void HiLogUnregisterGetIdFun(RegisterFunc registerFunc) return; } +void LOG_SetCallback(LogCallback callback) +{ + g_logCallback = callback; +} + static uint16_t GetFinalLevel(unsigned int domain, const std::string& tag) { // Priority: TagLevel > DomainLevel > GlobalLevel @@ -97,6 +107,14 @@ static uint16_t GetFinalLevel(unsigned int domain, const std::string& tag) if (domainLevel != LOG_LEVEL_MIN) { return domainLevel; } + // domain within the range of [DOMAIN_APP_MIN, DOMAIN_APP_MAX] is a js log, + // if this js log comes from debuggable hap, set the default level. + if ((domain >= DOMAIN_APP_MIN) && (domain <= DOMAIN_APP_MAX)) { + static bool isDebuggableHap = IsDebuggableHap(); + if (isDebuggableHap) { + return LOG_LEVEL_MIN; + } + } return GetGlobalLevel(); #else return LOG_LEVEL_MIN; @@ -135,6 +153,19 @@ static int HiLogFlowCtrlProcess(int len, const struct timespec &ts) } return 0; } + +static bool IsNeedProcFlowCtr(const LogType type) +{ + if (type != LOG_APP) { + return false; + } + //debuggable hap don't perform process flow control + static bool isDebuggableHap = IsDebuggableHap(); + if (IsProcessSwitchOn() && !isDebuggableHap) { + return true; + } + return false; +} #else static int PrintLog(HilogMsg& header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) { @@ -162,12 +193,43 @@ static int PrintLog(HilogMsg& header, const char *tag, uint16_t tagLen, const ch } #endif +static int LogToKmsg(const LogLevel level, const char *tag, const char* info) +{ + static int fd = open("/dev/kmsg", O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + printf("open /dev/kmsg failed, fd=%d. \n", fd); + return -1; + } + char logInfo[MAX_LOG_LEN] = {0}; + if (snprintf_s(logInfo, sizeof(logInfo), sizeof(logInfo) - 1, "<%d>%s: %s\n", level, tag, info) == -1) { + logInfo[sizeof(logInfo) - 2] = '\n'; // 2 add \n to tail + logInfo[sizeof(logInfo) - 1] = '\0'; + } +#ifdef __LINUX__ + return TEMP_FAILURE_RETRY(write(fd, logInfo, strlen(logInfo))); +#else + return write(fd, logInfo, strlen(logInfo)); +#endif +} + int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, const char *fmt, va_list ap) { - if ((tag == nullptr) || !HiLogIsLoggable(domain, tag, level)) { + if ((type != LOG_APP) && ((domain < DOMAIN_OS_MIN) || (domain > DOMAIN_OS_MAX))) { + return -1; + } + if (!HiLogIsLoggable(domain, tag, level)) { return -1; } + if (type == LOG_KMSG) { + char tmpFmt[MAX_LOG_LEN] = {0}; + // format va_list info to char* + if (vsnprintfp_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, true, fmt, ap) == -1) { + tmpFmt[sizeof(tmpFmt) - 2] = '\n'; // 2 add \n to tail + tmpFmt[sizeof(tmpFmt) - 1] = '\0'; + } + return LogToKmsg(level, tag, tmpFmt); + } HilogMsg header = {0}; struct timespec ts = {0}; @@ -226,7 +288,10 @@ int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif - ret = vsnprintfp_s(logBuf, MAX_LOG_LEN - traceBufLen, MAX_LOG_LEN - traceBufLen - 1, priv, fmt, ap); + vsnprintfp_s(logBuf, MAX_LOG_LEN - traceBufLen, MAX_LOG_LEN - traceBufLen - 1, priv, fmt, ap); + if (g_logCallback != nullptr) { + g_logCallback(type, level, domain, tag, logBuf); + } #ifdef __clang__ #pragma clang diagnostic pop #elif __GNUC__ @@ -264,7 +329,7 @@ int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int #if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ )) /* flow control */ - if (type == LOG_APP && !debug && IsProcessSwitchOn()) { + if (!debug && IsNeedProcFlowCtr(type)) { ret = HiLogFlowCtrlProcess(tagLen + logLen - traceBufLen, ts_mono); if (ret < 0) { return ret; @@ -275,7 +340,7 @@ int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int char dropLogBuf[MAX_LOG_LEN] = {0}; if (snprintf_s(dropLogBuf, MAX_LOG_LEN, MAX_LOG_LEN - 1, "==LOGS OVER PROC QUOTA, %d DROPPED==", ret) > 0) { - ret = HilogWriteLogMessage(&header, P_LIMIT_TAG, strlen(P_LIMIT_TAG) + 1, dropLogBuf, + HilogWriteLogMessage(&header, P_LIMIT_TAG, strlen(P_LIMIT_TAG) + 1, dropLogBuf, strnlen(dropLogBuf, MAX_LOG_LEN - 1) + 1); } header.level = level; @@ -299,7 +364,7 @@ int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *ta bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level) { - if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == nullptr) { + if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || (tag == nullptr) || (domain >= DOMAIN_OS_MAX)) { return false; } if (level < GetFinalLevel(domain, tag)) { diff --git a/frameworks/libhilog/include/hilog_common.h b/frameworks/libhilog/include/hilog_common.h index 367638ca892368e48dd535d1b79e118955860ed8..7d6945f0821b711b3d9a3918b19f6310ced76c63 100644 --- a/frameworks/libhilog/include/hilog_common.h +++ b/frameworks/libhilog/include/hilog_common.h @@ -28,7 +28,7 @@ #define OUTPUT_SOCKET_NAME "hilogOutput" #define CONTROL_SOCKET_NAME "hilogControl" #define HILOG_FILE_DIR "/data/log/hilog/" -#define MAX_LOG_LEN 1024 /* maximum length of a log, include '\0' */ +#define MAX_LOG_LEN 4096 /* maximum length of a log, include '\0' */ #define MAX_TAG_LEN 32 /* log tag size, include '\0' */ #define MAX_REGEX_STR_LEN (128) #define MAX_FILE_NAME_LEN (64) @@ -48,6 +48,7 @@ constexpr uint32_t DOMAIN_APP_MIN = 0x0; constexpr uint32_t DOMAIN_APP_MAX = 0xFFFF; constexpr uint32_t JOB_ID_MIN = 10; constexpr uint32_t JOB_ID_MAX = UINT_MAX; +constexpr uint32_t WAITING_DATA_MS = 5000; /* * header of log message from libhilog to hilogd diff --git a/frameworks/libhilog/param/include/properties.h b/frameworks/libhilog/param/include/properties.h index d64781b5f592daf6daa6f7cd08faf02db0fcaa83..fecf644233732654f7acb2bbcf31c4cca0978acb 100644 --- a/frameworks/libhilog/param/include/properties.h +++ b/frameworks/libhilog/param/include/properties.h @@ -20,10 +20,20 @@ namespace OHOS { namespace HiviewDFX { -bool IsPrivateSwitchOn(); + bool IsOnceDebugOn(); bool IsPersistDebugOn(); +#ifdef __cplusplus +extern "C" { +#endif + bool IsDebugOn(); +bool IsPrivateSwitchOn(); + +#ifdef __cplusplus +} +#endif +bool IsDebuggableHap(); uint16_t GetGlobalLevel(); uint16_t GetDomainLevel(uint32_t domain); uint16_t GetTagLevel(const std::string& tag); diff --git a/frameworks/libhilog/param/properties.cpp b/frameworks/libhilog/param/properties.cpp index faf6ce416dafd7d9aaaedb2ae8b5f6fc716cf496..8b7a5ecbd8b54f254994232e6e11cce30a9e4e89 100644 --- a/frameworks/libhilog/param/properties.cpp +++ b/frameworks/libhilog/param/properties.cpp @@ -77,6 +77,7 @@ static pthread_mutex_t g_domainLevelLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_tagLevelLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_domainFlowLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_processFlowLock = PTHREAD_MUTEX_INITIALIZER; +static constexpr const char* HAP_DEBUGGABLE = "HAP_DEBUGGABLE"; using PropRes = struct { string name; @@ -315,6 +316,15 @@ bool IsDebugOn() return IsOnceDebugOn() || IsPersistDebugOn(); } +bool IsDebuggableHap() +{ + const char *path = getenv(HAP_DEBUGGABLE); + if ((path == nullptr) || (strcmp(path, "true") != 0)) { + return false; + } + return true; +} + uint16_t GetGlobalLevel() { static auto *logLevelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, PropType::PROP_GLOBAL_LOG_LEVEL); @@ -338,7 +348,7 @@ uint16_t GetDomainLevel(uint32_t domain) PropType::PROP_DOMAIN_LOG_LEVEL, Uint2HexStr(domain)); auto result = domainMap->insert({ domain, levelCache }); if (!result.second) { - std::cerr << "Can't insert new LogLevelCache for domain: " << domain << "\n"; + delete levelCache; return LOG_LEVEL_MIN; } it = result.first; @@ -365,7 +375,7 @@ uint16_t GetTagLevel(const string& tag) PropType::PROP_TAG_LOG_LEVEL, tag); auto result = tagMap->insert({ tag, levelCache }); if (!result.second) { - std::cerr << "Can't insert new LogLevelCache for tag: " << tag << "\n"; + delete levelCache; return LOG_LEVEL_MIN; } it = result.first; @@ -455,7 +465,7 @@ bool IsTagStatsEnable() int GetProcessQuota(const string& proc) { - static constexpr int default_quota = 10240; + static constexpr int default_quota = 51200; char value[HILOG_PROP_VALUE_MAX] = {0}; string prop = GetPropertyName(PropType::PROP_PROC_QUOTA) + proc; @@ -468,7 +478,7 @@ int GetProcessQuota(const string& proc) int GetDomainQuota(uint32_t domain) { - static constexpr int default_quota = 10240; + static constexpr int default_quota = 51200; char value[HILOG_PROP_VALUE_MAX] = {0}; string prop = GetPropertyName(PropType::PROP_DOMAIN_QUOTA) + Uint2HexStr(domain); diff --git a/frameworks/libhilog/socket/hilog_input_socket_server.cpp b/frameworks/libhilog/socket/hilog_input_socket_server.cpp index 9b90db09ad4cdcf9452e1b7d96a457495836d7eb..75f0a108e5e41a958e9db0302303cefe606afb74 100644 --- a/frameworks/libhilog/socket/hilog_input_socket_server.cpp +++ b/frameworks/libhilog/socket/hilog_input_socket_server.cpp @@ -64,7 +64,7 @@ void HilogInputSocketServer::ServingThread() #ifndef __RECV_MSG_WITH_UCRED_ while ((ret = RecvPacket(data)) >= 0) { if (ret > 0) { - m_packetHandler(data); + m_packetHandler(data, ret); } if (m_stopServer.load()) { break; @@ -74,7 +74,7 @@ void HilogInputSocketServer::ServingThread() ucred cred; while ((ret = RecvPacket(data, &cred)) >= 0) { if (ret > 0) { - m_packetHandler(cred, data); + m_packetHandler(cred, data, ret); } if (m_stopServer.load()) { break; diff --git a/frameworks/libhilog/socket/include/hilog_input_socket_server.h b/frameworks/libhilog/socket/include/hilog_input_socket_server.h index b7c278197dd99f67cf03d199f2af1dd609044308..c410e7c8e42facece9a9f8d21dda684de4d88986 100644 --- a/frameworks/libhilog/socket/include/hilog_input_socket_server.h +++ b/frameworks/libhilog/socket/include/hilog_input_socket_server.h @@ -29,9 +29,9 @@ class HilogInputSocketServer : public DgramSocketServer { public: #ifndef __RECV_MSG_WITH_UCRED_ - using HandlingFunc = std::function& data)>; + using HandlingFunc = std::function& data, int dataLen)>; #else - using HandlingFunc = std::function& data)>; + using HandlingFunc = std::function& data, int dataLen)>; #endif enum class ServerThreadState { JUST_STARTED, diff --git a/frameworks/libhilog/socket/socket_server.cpp b/frameworks/libhilog/socket/socket_server.cpp index e7b790f8fef513f916abe49948636fb9099c0242..04c744b079553d19391748df5a1e94e9fb08a1e6 100644 --- a/frameworks/libhilog/socket/socket_server.cpp +++ b/frameworks/libhilog/socket/socket_server.cpp @@ -77,18 +77,18 @@ int SocketServer::Recv(void *buffer, unsigned int bufferLen, int flags) int SocketServer::RecvMsg(struct msghdr *hdr, int flags) { - return recvmsg(socketHandler, hdr, flags); + return TEMP_FAILURE_RETRY(recvmsg(socketHandler, hdr, flags)); } int SocketServer::Listen(unsigned int backlog) { - return listen(socketHandler, backlog); + return TEMP_FAILURE_RETRY(listen(socketHandler, backlog)); } int SocketServer::Poll(short inEvent, short& outEvent, const std::chrono::milliseconds& timeout) { pollfd info {socketHandler, inEvent, outEvent}; - int result = poll(&info, 1, timeout.count()); + int result = TEMP_FAILURE_RETRY(poll(&info, 1, timeout.count())); outEvent = info.revents; return result; } diff --git a/frameworks/libhilog/utils/include/log_utils.h b/frameworks/libhilog/utils/include/log_utils.h index 5493d1bbcf99134d578be5fdcdaa1e1fd7b27f62..464fe848bd9c2ce305e3015a21d6fc61f820c9b5 100644 --- a/frameworks/libhilog/utils/include/log_utils.h +++ b/frameworks/libhilog/utils/include/log_utils.h @@ -104,6 +104,7 @@ std::string GetNameByPid(uint32_t pid); uint32_t GetPPidByPid(uint32_t pid); uint64_t GenerateHash(const char *p, size_t size); void PrintErrorno(int err); +int WaitingToDo(int max, const std::string& path, std::function func); } // namespace HiviewDFX } // namespace OHOS #endif // LOG_UTILS_H \ No newline at end of file diff --git a/frameworks/libhilog/utils/log_print.cpp b/frameworks/libhilog/utils/log_print.cpp index 6d47a9ae3c225ceea271f73b9d091f5cd0f76d5e..77fc66af8934bc9ddd13f760b49945e385708aa0 100644 --- a/frameworks/libhilog/utils/log_print.cpp +++ b/frameworks/libhilog/utils/log_print.cpp @@ -121,18 +121,24 @@ static void PrintLogPrefix(const LogContent& content, const LogFormat& format, s out << "Invalid time accuracy format" << endl; return; } - out << setfill(' '); - // 2. print pid/tid - out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid; - // 3. print level - out << " " << LogLevel2ShortStr(content.level) << " "; - // 4. print log type - out << GetLogTypePrefix(content.type); - // 5. print domain - out << setfill('0'); - out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec; - // 5. print tag & log - out << "/" << content.tag << ": "; + // The kmsg logs are taken from /proc/kmsg, cannot obtain pid, tid or domain information + // The kmsg log printing format: 08-06 16:51:04.945 <6> [4294.967295] hungtask_base whitelist[0]-init-1 + if (content.type != LOG_KMSG) { + out << setfill(' '); + // 2. print pid/tid + out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid; + // 3. print level + out << " " << LogLevel2ShortStr(content.level) << " "; + // 4. print log type + out << GetLogTypePrefix(content.type); + // 5. print domain + out << setfill('0'); + out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec; + // 5. print tag & log + out << "/" << content.tag << ": "; + } else { + out << " " << content.tag << " "; + } } void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out) diff --git a/frameworks/libhilog/utils/log_utils.cpp b/frameworks/libhilog/utils/log_utils.cpp index c30f1c10a7573bc93cd360842c42c6da89e36f04..7cef84762a7c394a226fcad3ee76f3b107fe5af5 100644 --- a/frameworks/libhilog/utils/log_utils.cpp +++ b/frameworks/libhilog/utils/log_utils.cpp @@ -14,13 +14,16 @@ */ #include #include +#include #include #include #include +#include #include +#include #include #include - +#include #include "hilog_common.h" #include "hilog_cmd.h" #include "log_utils.h" @@ -42,6 +45,7 @@ namespace { namespace OHOS { namespace HiviewDFX { using namespace std; +using namespace std::chrono; // Buffer Size&Char Map static const KVMap g_SizeMap({ @@ -496,5 +500,23 @@ void PrintErrorno(int err) #endif std::cerr << "Errno: " << err << ", " << buf << std::endl; } + +int WaitingToDo(int max, const string& path, function func) +{ + chrono::steady_clock::time_point start = chrono::steady_clock::now(); + chrono::milliseconds wait(max); + while (true) { + if (func(path) != RET_FAIL) { + cout << "waiting for " << path << " successfully!" << endl; + return RET_SUCCESS; + } + + std::this_thread::sleep_for(10ms); + if ((chrono::steady_clock::now() - start) > wait) { + cerr << "waiting for " << path << " failed!" << endl; + return RET_FAIL; + } + } +} } // namespace HiviewDFX } // namespace OHOS diff --git a/frameworks/libhilog/vsnprintf/include/vsnprintf_s_p.h b/frameworks/libhilog/vsnprintf/include/vsnprintf_s_p.h index b8f1cfdae041e9d1d3802e3f9c6f81872b20d966..70d96fe50f4c17372d25c41736ac9611fae8fedb 100644 --- a/frameworks/libhilog/vsnprintf/include/vsnprintf_s_p.h +++ b/frameworks/libhilog/vsnprintf/include/vsnprintf_s_p.h @@ -35,4 +35,7 @@ HILOG_LOCAL_API int vsnprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const char *format, va_list arglist); +HILOG_LOCAL_API +int vsnprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const char *format, ...); + #endif /* __VSNPRINTFP_S_H__ */ diff --git a/frameworks/libhilog/vsnprintf/vsnprintf_s_p.cpp b/frameworks/libhilog/vsnprintf/vsnprintf_s_p.cpp index 466bb002c68307ad6eb44ec9c11f42704f78031e..591fb44e6b67bfa1b1b73dfc718ce0bf68155ea0 100644 --- a/frameworks/libhilog/vsnprintf/vsnprintf_s_p.cpp +++ b/frameworks/libhilog/vsnprintf/vsnprintf_s_p.cpp @@ -28,6 +28,10 @@ #error "max string is 2G" #endif +#if defined(_WIN64) || defined(WIN64) || defined(__LP64__) || defined(_LP64) +#define SECUREC_ON_64BITS +#endif + #if defined(_DEBUG) || defined(DEBUG) #if defined(SECUREC_ERROR_HANDLER_BY_ASSERT) #define SECUREC_ERROR_INVALID_PARAMTER(msg) assert( msg "invalid argument" == NULL) @@ -258,6 +262,16 @@ int vsnprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const c return retVal; } +HILOG_LOCAL_API +int vsnprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + int ret = vsnprintfp_s(strDest, destMax, count, priv, format, ap); + va_end(ap); + return ret; +} + #ifdef SECUREC_FOR_WCHAR #undef SECUREC_FOR_WCHAR #endif diff --git a/hilog.gni b/hilog.gni index 50b85be0ba33115b0c06f413c5bcd0169bc68257..74e715cee289663289806b0e836ecc5b63804f29 100644 --- a/hilog.gni +++ b/hilog.gni @@ -16,4 +16,10 @@ platforms = [ "windows", "mac", "linux", + "android", + "ios", ] + +declare_args() { + hilog_native_feature_ohcore = false +} diff --git a/interfaces/bundle.json b/interfaces/bundle.json deleted file mode 100644 index c196c8e2f06aa8d93fe77cd20ccd084b7f67f90b..0000000000000000000000000000000000000000 --- a/interfaces/bundle.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@ohos/hilog_native", - "description": "Native log interface provided for system", - "version": "3.1", - "license": "Apache License 2.0", - "publishAs": "code-segment", - "segment": { - "destPath": "base/hiviewdfx/hilog" - }, - "dirs": {}, - "scripts": {}, - "component": { - "name": "hilog_native", - "subsystem": "hiviewdfx", - "syscap": [ - "SystemCapability.HiviewDFX.HiLog" - ], - "adapted_system_type": [ - "standard" - ], - "rom": "188KB", - "ram": "2000KB", - "deps": { - "components": [ - "c_utils", - "init", - "napi" - ], - "third_party": [ - "bounds_checking_function", - "zlib" - ] - }, - "build": { - "sub_component": [ - "//base/hiviewdfx/hilog/frameworks/hilog_ndk:hilog_ndk", - "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", - "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_base", - "//base/hiviewdfx/hilog/interfaces/js:hilog_napi" - ], - "inner_kits": [ - { - "name": "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", - "header": { - "header_files": [ - "hilog/log.h", - "hilog/log_c.h", - "hilog/log_cpp.h", - "hilog_trace.h" - ], - "header_base": "//base/hiviewdfx/hilog/interfaces/native/innerkits/include" - } - }, - { - "name": "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_base", - "header": { - "header_files": [ - "hilog_base/log_base.h" - ], - "header_base": "//base/hiviewdfx/hilog/interfaces/native/innerkits/include" - } - } - ], - "test": [] - } - } -} diff --git a/interfaces/js/kits/napi/BUILD.gn b/interfaces/js/kits/napi/BUILD.gn index f0c15686151121181e7c3c3b06d61c9c012e14c0..483ad6ad0d070c3b47766c8a2ce55cae352d5c08 100644 --- a/interfaces/js/kits/napi/BUILD.gn +++ b/interfaces/js/kits/napi/BUILD.gn @@ -11,13 +11,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//base/hiviewdfx/hilog/hilog.gni") import("//build/ohos.gni") ohos_source_set("libhilognapi_src") { + defines = [] include_dirs = [ "//third_party/node/src", "//third_party/bounds_checking_function/include", "//base/hiviewdfx/hilog/frameworks/libhilog/param/include", + "//base/hiviewdfx/hilog/frameworks/libhilog/include", ] sources = [ "src/common/napi/n_class.cpp", @@ -31,13 +34,10 @@ ohos_source_set("libhilognapi_src") { if (is_mingw || is_mac || is_linux) { deps += [ "//foundation/arkui/napi:ace_napi" ] } else { - external_deps = [ - "hilog_native:libhilog", - "napi:ace_napi", - ] + deps += [ "../../../../interfaces/native/innerkits:libhilog" ] + external_deps = [ "napi:ace_napi" ] } - defines = [] cflags_cc = [] if (is_mingw) { deps += [ @@ -55,7 +55,7 @@ ohos_source_set("libhilognapi_src") { defines += [ "__LINUX__" ] } subsystem_name = "hiviewdfx" - part_name = "hilog_native" + part_name = "hilog" } config("libhilog_js_cfg") { @@ -64,13 +64,18 @@ config("libhilog_js_cfg") { } ohos_shared_library("libhilognapi") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } deps = [ ":libhilognapi_src" ] public_configs = [ ":libhilog_js_cfg" ] configs = [ ":libhilog_js_cfg" ] - output_name = "libhilog" + output_name = "libhilog_napi" relative_install_dir = "module" subsystem_name = "hiviewdfx" - part_name = "hilog_native" + part_name = "hilog" } diff --git a/interfaces/js/kits/napi/src/hilog/src/hilog_napi_base.cpp b/interfaces/js/kits/napi/src/hilog/src/hilog_napi_base.cpp index 87779e8d15a91cf1675af57eca31252bf4657727..259fc42188b47bfdde0720e700be273734052b38 100644 --- a/interfaces/js/kits/napi/src/hilog/src/hilog_napi_base.cpp +++ b/interfaces/js/kits/napi/src/hilog/src/hilog_napi_base.cpp @@ -14,6 +14,7 @@ */ #include "properties.h" +#include "hilog_common.h" #include "napi/native_api.h" #include "napi/native_node_api.h" @@ -55,7 +56,6 @@ void ParseLogContent(string& formatStr, vector& params, string& logCo debug = IsDebugOn(); #endif bool priv = (!debug) && IsPrivateSwitchOn(); - for (; pos < len; ++pos) { bool showPriv = true; if (count >= size) { @@ -88,7 +88,8 @@ void ParseLogContent(string& formatStr, vector& params, string& logCo ++pos; break; case 's': - if (params[count].type == napi_string || params[count].type == napi_undefined) { + if (params[count].type == napi_string || params[count].type == napi_undefined || + params[count].type == napi_boolean || params[count].type == napi_null) { ret += (priv && showPriv) ? PRIV_STR : params[count].val; } count++; @@ -130,6 +131,9 @@ napi_value HilogNapiBase::isLoggable(napi_env env, napi_callback_info info) if (!succ) { return nullptr; } + if ((domain < static_cast(DOMAIN_APP_MIN)) || (domain > static_cast(DOMAIN_APP_MAX))) { + return NVal::CreateBool(env, false).val_; + } int32_t level; tie(succ, level) = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32(); if (!succ) { @@ -180,7 +184,8 @@ napi_value HilogNapiBase::parseNapiValue(napi_env env, napi_callback_info info, if (typeStatus != napi_ok) { return nullptr; } - if (type == napi_number || type == napi_bigint || type == napi_object || type == napi_undefined) { + if (type == napi_number || type == napi_bigint || type == napi_object || + type == napi_undefined || type == napi_boolean || type == napi_null) { napi_value elmString; napi_status objectStatus = napi_coerce_to_string(env, element, &elmString); if (objectStatus != napi_ok) { @@ -196,10 +201,12 @@ napi_value HilogNapiBase::parseNapiValue(napi_env env, napi_callback_info info, return nullptr; } } else { - NAPI_ASSERT(env, false, "type mismatch"); + HiLog::Info(LABEL, "%{public}s", "type mismatch"); } res.type = type; - res.val = name.get(); + if (name != nullptr) { + res.val = name.get(); + } params.emplace_back(res); return nullptr; } @@ -260,8 +267,7 @@ napi_value HilogNapiBase::HilogImpl(napi_env env, napi_callback_info info, int l } } ParseLogContent(fmtString, params, logContent); - HiLogPrint(DEFAULT_LOG_TYPE, static_cast(level), domain, tag.get(), - logContent.c_str(), ""); + HiLogPrint(DEFAULT_LOG_TYPE, static_cast(level), domain, tag.get(), "%{public}s", logContent.c_str()); return nullptr; } } // namespace HiviewDFX diff --git a/interfaces/native/bundle.json b/interfaces/native/bundle.json deleted file mode 100644 index 414854b1612d3ea7446ec3fe062635efe6282946..0000000000000000000000000000000000000000 --- a/interfaces/native/bundle.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@ohos/hiviewdfx_hilog_native", - "description": "Native log interface provided for system", - "version": "3.1", - "license": "Apache License 2.0", - "publishAs": "code-segment", - "segment": { - "destPath": "base/hiviewdfx/hilog" - }, - "dirs": {}, - "scripts": {}, - "component": { - "name": "hiviewdfx_hilog_native", - "subsystem": "hiviewdfx", - "syscap": [ - "SystemCapability.HiviewDFX.HiLog" - ], - "adapted_system_type": [ - "standard" - ], - "rom": "188KB", - "ram": "2000KB", - "deps": { - "components": [ - "init", - "utils_base" - ], - "third_party": [ - "bounds_checking_function", - "zlib" - ] - }, - "build": { - "sub_component": [] - } - } -} \ No newline at end of file diff --git a/interfaces/native/innerkits/BUILD.gn b/interfaces/native/innerkits/BUILD.gn index a3ba8693ef0fe84da42943baafe7b318981772b6..9023a14afcc98a0a08f4ba139cb575605efbf5a9 100644 --- a/interfaces/native/innerkits/BUILD.gn +++ b/interfaces/native/innerkits/BUILD.gn @@ -18,37 +18,91 @@ config("libhilog_pub_config") { visibility = [ ":*" ] include_dirs = [ "include" ] } - -template("libhilog") { - forward_variables_from(invoker, "*") - ohos_shared_library(target_name) { +if (is_mingw || is_mac || is_linux || is_ohos) { + ohos_shared_library("libhilog") { public_configs = [ ":libhilog_pub_config" ] + if (is_ohos) { + deps = [ "../../../frameworks/libhilog:libhilog_source_ohos" ] + } else if (is_mingw) { + deps = [ "../../../frameworks/libhilog:libhilog_source_windows" ] + } else if (is_mac) { + deps = [ "../../../frameworks/libhilog:libhilog_source_mac" ] + } else if (is_linux) { + deps = [ "../../../frameworks/libhilog:libhilog_source_linux" ] + } - deps = [ - "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_source_$platform", - ] - - if (platform == "ohos") { + if (is_ohos) { output_extension = "so" + version_script = "libhilog.map" + innerapi_tags = [ + "chipsetsdk", + "platformsdk", + "sasdk", + ] + install_enable = !hilog_native_feature_ohcore + install_images = [ + "system", + "updater", + ] + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } } - install_enable = true - install_images = [ - "system", - "updater", - ] - part_name = "hilog_native" + part_name = "hilog" subsystem_name = "hiviewdfx" } } -foreach(item, platforms) { - if (item == "ohos") { - libhilog("libhilog") { - platform = item +template("libhilog") { + forward_variables_from(invoker, "*") + if (current_os == "android" || current_os == "ios") { + ohos_static_library(target_name) { + public_configs = [ ":libhilog_pub_config" ] + deps = [ "../../../platform:libhilog_platform_source_$platform" ] + + part_name = "hilog" + subsystem_name = "hiviewdfx" + } + } else { + ohos_shared_library(target_name) { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":libhilog_pub_config" ] + deps = [ "../../../frameworks/libhilog:libhilog_source_$platform" ] + if (platform == "ohos") { + output_extension = "so" + version_script = "libhilog.map" + } + + install_enable = !hilog_native_feature_ohcore + install_images = [ + "system", + "updater", + ] + + if (platform == "ohos") { + innerapi_tags = [ + "chipsetsdk", + "platformsdk", + "sasdk", + ] + } + + part_name = "hilog" + subsystem_name = "hiviewdfx" } } - if (item == "windows" || item == "mac" || item == "linux") { +} + +foreach(item, platforms) { + if (item == "windows" || item == "mac" || item == "linux" || item == "ios" || + item == "android") { libhilog("libhilog_" + item) { platform = item } @@ -57,14 +111,18 @@ foreach(item, platforms) { config("libhilog_base_pub_cfg") { visibility = [ "*:*" ] - include_dirs = [ "include" ] + include_dirs = [ + "include", + "../../../frameworks/libhilog/include", + "../../../frameworks/libhilog/vsnprintf/include", + ] } ohos_static_library("libhilog_base") { public_configs = [ ":libhilog_base_pub_cfg" ] - deps = [ "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_base_source" ] + deps = [ "../../../frameworks/libhilog:libhilog_base_source" ] subsystem_name = "hiviewdfx" - part_name = "hilog_native" + part_name = "hilog" } diff --git a/interfaces/native/innerkits/include/hilog/log_c.h b/interfaces/native/innerkits/include/hilog/log_c.h index 2649f3325932781f72ce4b37b3095abdf4eea0fd..9284e8afb37c1314e42b341f05c4a6624bc42df4 100644 --- a/interfaces/native/innerkits/include/hilog/log_c.h +++ b/interfaces/native/innerkits/include/hilog/log_c.h @@ -23,57 +23,138 @@ extern "C" { #endif -// Log domain +/** + * Log domain, indicates the log service domainID. Different LogType have different domainID ranges. + * Log type of LOG_APP: 0-0xFFFF + * Log type of LOG_CORE & LOG_INIT: 0xD000000-0xD0FFFFF + */ #ifndef LOG_DOMAIN #define LOG_DOMAIN 0 #endif -// Log tag +/** + * Log tag, indicates the log service tag, you can customize the tag as needed, usually the keyword of the module. + */ #ifndef LOG_TAG #define LOG_TAG NULL #endif -// Log type +/* Log type */ typedef enum { + /* min log type */ LOG_TYPE_MIN = 0, + /* Used by app log. */ LOG_APP = 0, + /* Used by system log: recommended for important logs during the startup phase. */ LOG_INIT = 1, - // Used by core service, framework. + /* Used by core service, framework. */ LOG_CORE = 3, + /* Used by kmsg log. */ LOG_KMSG = 4, + /* max log type */ LOG_TYPE_MAX } LogType; -// Log level +/* Log level */ typedef enum { + /* min log level */ LOG_LEVEL_MIN = 0, + /* Designates lower priority log. */ LOG_DEBUG = 3, + /* Designates useful information. */ LOG_INFO = 4, + /* Designates hazardous situations. */ LOG_WARN = 5, + /* Designates very serious errors. */ LOG_ERROR = 6, + /* Designates major fatal anomaly. */ LOG_FATAL = 7, + /* max log level */ LOG_LEVEL_MAX, } LogLevel; +/** + * @brief Get log of fatal level + */ const char* GetLastFatalMessage(void); +/** + * @brief Print hilog + * + * @return If the log is successfully printed, returns the number of bytes written, + * if failed, returns -1. + */ int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) __attribute__((__format__(os_log, 5, 6))); -#define HILOG_DEBUG(type, ...) ((void)HiLogPrint((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) +/** + * @brief Hilog C interface of different log level + * + * @param type enum:LogType + */ +#define HILOG_DEBUG(type, ...) ((void)HILOG_IMPL((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) -#define HILOG_INFO(type, ...) ((void)HiLogPrint((type), LOG_INFO, 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)HiLogPrint((type), LOG_WARN, 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)HiLogPrint((type), LOG_ERROR, 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)HiLogPrint((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) +#define HILOG_FATAL(type, ...) ((void)HILOG_IMPL((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) +/** + * @brief Hilog C interface implementation + * + * @param type enum:LogType + * @param level enum:LogLevel + * @param domain macro:LOG_DOMAIN + * @param tag macro:LOG_TAG + */ +#define HILOG_IMPL(type, level, domain, tag, ...) HiLogPrint(type, level, domain, tag, ##__VA_ARGS__) + +/** + * @brief Check whether log of a specified domain, tag and level can be printed. + * + * @param domain macro:LOG_DOMAIN + * @param tag macro:LOG_TAG + * @param level enum:LogLevel + */ bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level); +/** + * @brief Defines the function pointer type for the user-defined log processing function. + * + * @param type Indicates the log type. The type for third-party applications is defined by {@link LOG_APP}. + * @param level Indicates the log level, which can be LOG_DEBUG, LOG_INFO, LOG_WARN, + * LOG_ERROR, and LOG_FATAL. + * @param domain Indicates the service domain of logs. Its value is a hexadecimal integer ranging from 0x0 to 0xFFFF. + * @param tag Indicates the log tag, which is a string used to identify the class, file, or service behavior. + * @param msg Indicates the log message itself, which is a formatted log string. + * @since 11 + */ +typedef void (*LogCallback)(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, + const char *msg); + +/** + * @brief Set the user-defined log processing function. + * + * After calling this function, the callback function implemented by the user can receive all hilogs of the + * current process. + * Note that it will not change the default behavior of hilog logs of the current process, no matter whether this + * interface is called or not. \n + * + * @param callback Indicates the callback function implemented by the user. If you do not need to process hilog logs, + * you can transfer a null pointer. + * @since 11 + */ +void LOG_SetCallback(LogCallback callback); + #ifdef __cplusplus } #endif +#ifdef HILOG_RAWFORMAT +#include "hilog/log_inner.h" +#endif + #endif // HIVIEWDFX_HILOG_C_H diff --git a/interfaces/native/innerkits/include/hilog/log_cpp.h b/interfaces/native/innerkits/include/hilog/log_cpp.h index ff481623c8958b3283895617ce2d8b62315c611a..76c9543d026e4061a7737846b824d9fbb5f2f913 100644 --- a/interfaces/native/innerkits/include/hilog/log_cpp.h +++ b/interfaces/native/innerkits/include/hilog/log_cpp.h @@ -21,12 +21,30 @@ #ifdef __cplusplus namespace OHOS { namespace HiviewDFX { +/** + * @brief Initialize log parameters: type, domain and tag. + * domain: Indicates the log service domainID. Different LogType have different domainID ranges, + * Log type of LOG_APP: 0-0xFFFF, + * Log type of LOG_CORE & LOG_INIT: 0xD000000-0xD0FFFFF. + * tag: Indicates the log service tag, you can customize the tag as needed, usually the keyword of the module. + */ using HiLogLabel = struct { LogType type; unsigned int domain; const char *tag; }; +/** + * @brief Hilog C++ class interface of different log level. + * Debug: Designates lower priority log. + * Info: Designates useful information. + * Warn: Designates hazardous situations. + * Error: Designates very serious errors. + * Fatal: Designates major fatal anomaly. + * + * @param label HiLogLabel for the log + * @param fmt Format string for the log + */ class HiLog final { public: static int Debug(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); @@ -37,5 +55,23 @@ public: }; } // namespace HiviewDFX } // namespace OHOS + +/** + * @brief Hilog C++ macro interface of different log level. + * HiLogDebug: Designates lower priority log. + * HiLogInfo: Designates useful information. + * HiLogWarn: Designates hazardous situations. + * HiLogError: Designates very serious errors. + * HiLogFatal: Designates major fatal anomaly. + * + * @param label HiLogLabel for the log + * @param fmt Format string for the log + */ +#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__) + #endif // __cplusplus #endif // HIVIEWDFX_HILOG_CPP_H diff --git a/interfaces/native/innerkits/include/hilog_base/log_base.h b/interfaces/native/innerkits/include/hilog_base/log_base.h index 7e06e64bbe4d032179a769f2281e00e675305704..0851e920b56c0f73649ea1230c61ffa636b27dab 100644 --- a/interfaces/native/innerkits/include/hilog_base/log_base.h +++ b/interfaces/native/innerkits/include/hilog_base/log_base.h @@ -23,42 +23,69 @@ extern "C" { #endif -// Log domain +/** + * Log domain, indicates the log service domainID. Different LogType have different domainID ranges. + * Log type of LOG_APP: 0-0xFFFF + * Log type of LOG_CORE & LOG_INIT: 0xD000000-0xD0FFFFF + */ #ifndef LOG_DOMAIN #define LOG_DOMAIN 0 #endif -// Log tag +/** + * Log tag, indicates the log service tag, you can customize the tag as needed, usually the keyword of the module. + */ #ifndef LOG_TAG #define LOG_TAG NULL #endif -// Log type +/* Log type */ typedef enum { + /* min log type */ LOG_TYPE_MIN = 0, + /* Used by app log. */ LOG_APP = 0, - // Log to kmsg, only used by init phase. + /* Log to kmsg, only used by init phase. */ LOG_INIT = 1, - // Used by core service, framework. + /* Used by core service, framework. */ LOG_CORE = 3, + /* Used by kmsg log. */ LOG_KMSG = 4, + /* max log type */ LOG_TYPE_MAX } LogType; -// Log level +/* Log level */ typedef enum { + /* min log level */ LOG_LEVEL_MIN = 0, + /* Designates lower priority log. */ LOG_DEBUG = 3, + /* Designates useful information. */ LOG_INFO = 4, + /* Designates hazardous situations. */ LOG_WARN = 5, + /* Designates very serious errors. */ LOG_ERROR = 6, + /* Designates major fatal anomaly. */ LOG_FATAL = 7, + /* max log level */ LOG_LEVEL_MAX, } LogLevel; int HiLogBasePrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) __attribute__((__format__(os_log, 5, 6))); +/** + * @brief Hilog base interface of different log level. + * DEBUG: Designates lower priority log. + * INFO: Designates useful information. + * WARN: Designates hazardous situations. + * ERROR: Designates very serious errors. + * FATAL: Designates major fatal anomaly. + * + * @param type enum:LogType + */ #define HILOG_BASE_DEBUG(type, ...) ((void)HiLogBasePrint((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) #define HILOG_BASE_INFO(type, ...) ((void)HiLogBasePrint((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) @@ -69,10 +96,21 @@ int HiLogBasePrint(LogType type, LogLevel level, unsigned int domain, const char #define HILOG_BASE_FATAL(type, ...) ((void)HiLogBasePrint((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) +/** + * @brief Check whether log of a specified domain, tag and level can be printed. + * + * @param domain macro:LOG_DOMAIN + * @param tag macro:LOG_TAG + * @param level enum:LogLevel + */ bool HiLogBaseIsLoggable(unsigned int domain, const char *tag, LogLevel level); #ifdef __cplusplus } #endif +#ifdef HILOG_RAWFORMAT +#include "hilog_base/log_base_inner.h" +#endif + #endif // HIVIEWDFX_HILOG_BASE_C_H diff --git a/interfaces/native/innerkits/include/hilog_trace.h b/interfaces/native/innerkits/include/hilog_trace.h index 746eae50bbe9518f5bc26fed5a35c13c06b37759..b370c93cc70ba62912299db11441df3253db8bc7 100644 --- a/interfaces/native/innerkits/include/hilog_trace.h +++ b/interfaces/native/innerkits/include/hilog_trace.h @@ -24,7 +24,18 @@ extern "C" { typedef int (*RegisterFunc)(uint64_t*, uint32_t*, uint64_t*, uint64_t*); +/** + * @brief register hilog trace. + * + * @param RegisterFunc Function pointer to RegisterFunc + */ int HiLogRegisterGetIdFun(RegisterFunc); + +/** + * @brief unregister hilog trace. + * + * @param RegisterFunc Function pointer to RegisterFunc + */ void HiLogUnregisterGetIdFun(RegisterFunc); #ifdef __cplusplus diff --git a/interfaces/native/innerkits/libhilog.map b/interfaces/native/innerkits/libhilog.map new file mode 100644 index 0000000000000000000000000000000000000000..0312d454d1835a24dbaf0c14130cb6a10e3ce455 --- /dev/null +++ b/interfaces/native/innerkits/libhilog.map @@ -0,0 +1,105 @@ +{ + global: + extern "C" { + HiLogPrintArgs; + HiLogPrint; + HiLogIsLoggable; + IsPrivateSwitchOn; + IsDebugOn; + HiLogRegisterGetIdFun; + HiLogUnregisterGetIdFun; + HilogWriteLogMessage; + GetLastFatalMessage; + LOG_SetCallback; + }; + extern "C++" { + "OHOS::HiviewDFX::HiLog::Info(OHOS::HiviewDFX::HiLogLabel const&, char const*, ...)"; + "OHOS::HiviewDFX::HiLog::Warn(OHOS::HiviewDFX::HiLogLabel const&, char const*, ...)"; + "OHOS::HiviewDFX::HiLog::Error(OHOS::HiviewDFX::HiLogLabel const&, char const*, ...)"; + "OHOS::HiviewDFX::HiLog::Fatal(OHOS::HiviewDFX::HiLogLabel const&, char const*, ...)"; + "OHOS::HiviewDFX::HiLog::Debug(OHOS::HiviewDFX::HiLogLabel const&, char const*, ...)"; + "OHOS::HiviewDFX::SocketServer::SocketServer(std::__h::basic_string, std::__h::allocator> const&, unsigned int)"; + "OHOS::HiviewDFX::SocketServer::Init()"; + "OHOS::HiviewDFX::SeqPacketSocketServer::StartAcceptingConnection(std::__h::function>)>, std::__h::chrono::duration>, std::__h::function)"; + "OHOS::HiviewDFX::SeqPacketSocketServer::StartAcceptingConnection(std::__h::function>)>, std::__h::chrono::duration>, std::__h::function)"; + "OHOS::HiviewDFX::SocketServer::~SocketServer()"; + "OHOS::HiviewDFX::Socket::~Socket()"; + "OHOS::HiviewDFX::GetDomainQuota(unsigned int)"; + "OHOS::HiviewDFX::GetBufferSize(unsigned short, bool)"; + "OHOS::HiviewDFX::LogType2Str(unsigned short)"; + "OHOS::HiviewDFX::PrintErrorno(int)"; + "OHOS::HiviewDFX::LogPrintWithFormat(OHOS::HiviewDFX::LogContent const&, OHOS::HiviewDFX::LogFormat const&, std::__h::basic_ostream>&)"; + "OHOS::HiviewDFX::GenerateHash(char const*, unsigned int)"; + "OHOS::HiviewDFX::GenerateHash(char const*, unsigned long)"; + "OHOS::HiviewDFX::IsStatsEnable()"; + "OHOS::HiviewDFX::IsTagStatsEnable()"; + "OHOS::HiviewDFX::GetNameByPid(unsigned int)"; + "OHOS::HiviewDFX::IsDomainSwitchOn()"; + "OHOS::HiviewDFX::IsPersistDebugOn()"; + "OHOS::HiviewDFX::HilogInputSocketServer::RunServingThread()"; + "OHOS::HiviewDFX::IsKmsgSwitchOn()"; + "OHOS::HiviewDFX::HilogInputSocketServer::~HilogInputSocketServer()"; + "OHOS::HiviewDFX::Size2Str(unsigned long long)"; + "OHOS::HiviewDFX::Size2Str(unsigned long)"; + "OHOS::HiviewDFX::LogLevel2Str(unsigned short)"; + "OHOS::HiviewDFX::LogIoctl::LogIoctl(IoctlCmd, IoctlCmd)"; + "OHOS::HiviewDFX::LogIoctl::RequestOutput(OutputRqst const&, std::__h::function)"; + "OHOS::HiviewDFX::PrettyStr2LogLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::SetGlobalLevel(unsigned short)"; + "OHOS::HiviewDFX::SetDomainLevel(unsigned int, unsigned short)"; + "OHOS::HiviewDFX::Uint2HexStr(unsigned int)"; + "OHOS::HiviewDFX::SetTagLevel(std::__h::basic_string, std::__h::allocator> const&, unsigned short)"; + "OHOS::HiviewDFX::Split(std::__h::basic_string, std::__h::allocator> const&, std::__h::vector, std::__h::allocator>, std::__h::allocator, std::__h::allocator>>>&, std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::HexStr2Uint(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::ComboLogType2Str(unsigned short)"; + "OHOS::HiviewDFX::Str2Size(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::Str2ComboLogLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::SetPrivateSwitchOn(bool)"; + "OHOS::HiviewDFX::SetProcessSwitchOn(bool)"; + "OHOS::HiviewDFX::ErrorCode2Str(short)"; + "OHOS::HiviewDFX::WaitingToDo(int, std::__h::basic_string, std::__h::allocator> const&, std::__h::function, std::__h::allocator> const&)>)"; + "OHOS::HiviewDFX::Socket::Read(char*, unsigned int)"; + "OHOS::HiviewDFX::Socket::WriteV(iovec const*, unsigned int)"; + "OHOS::HiviewDFX::Socket::Write(char const*, unsigned int)"; + "OHOS::HiviewDFX::Socket::GetUid()"; + "OHOS::HiviewDFX::Socket::GetPid()"; + "OHOS::HiviewDFX::GetPPidByPid(unsigned int)"; + "OHOS::HiviewDFX::GetBitsCount(unsigned long long)"; + "OHOS::HiviewDFX::GetBitsCount(unsigned long)"; + "OHOS::HiviewDFX::GetAllLogTypes()"; + "OHOS::HiviewDFX::SetBufferSize(unsigned short, bool, unsigned int)"; + "OHOS::HiviewDFX::SetBufferSize(unsigned short, bool, unsigned long)"; + "OHOS::HiviewDFX::SetKmsgSwitchOn(bool)"; + "OHOS::HiviewDFX::SetDomainSwitchOn(bool)"; + "OHOS::HiviewDFX::LogIoctl::RequestStatsQuery(StatsQueryRqst const&, std::__h::function)"; + "OHOS::HiviewDFX::Str2ComboLogType(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::LogIoctl::SendMsgHeader(IoctlCmd, unsigned int)"; + "OHOS::HiviewDFX::LogIoctl::SendMsgHeader(IoctlCmd, unsigned long)"; + "OHOS::HiviewDFX::Socket::WriteAll(char const*, unsigned int)"; + "OHOS::HiviewDFX::LogIoctl::ReceiveMsgHeaer(MsgHeader&)"; + "OHOS::HiviewDFX::LogIoctl::GetRsp(char*, int)"; + + vtable?for?OHOS::HiviewDFX::HilogInputSocketServer; + + "OHOS::HiviewDFX::SetOnceDebugOn(bool)"; + "OHOS::HiviewDFX::SetPersistDebugOn(bool)"; + "OHOS::HiviewDFX::IsOnceDebugOn()"; + "OHOS::HiviewDFX::IsProcessSwitchOn()"; + "OHOS::HiviewDFX::ShortStr2LogLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::GetGlobalLevel()"; + "OHOS::HiviewDFX::GetDomainLevel(unsigned int)"; + "OHOS::HiviewDFX::GetTagLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::Str2LogType(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::Str2LogLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::LogLevel2ShortStr(unsigned short)"; + "OHOS::HiviewDFX::ShortStr2LogLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::ComboLogLevel2Str(unsigned short)"; + "OHOS::HiviewDFX::GetBitPos(unsigned long long)"; + "OHOS::HiviewDFX::GetBitPos(unsigned long)"; + "OHOS::HiviewDFX::Uint2DecStr(unsigned int)"; + "OHOS::HiviewDFX::DecStr2Uint(std::__h::basic_string, std::__h::allocator> const&)"; + }; + + local: + *; +}; \ No newline at end of file diff --git a/interfaces/native/kits/include/hilog/log.h b/interfaces/native/kits/include/hilog/log.h index 4f620b1531409b818eb2d6a72b60bb285ba7d5d0..26049d945ad80c33ee9d3f3d124b3951e4957d2c 100644 --- a/interfaces/native/kits/include/hilog/log.h +++ b/interfaces/native/kits/include/hilog/log.h @@ -250,4 +250,9 @@ bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level); } #endif /** @} */ + +#ifdef HILOG_RAWFORMAT +#include "hilog/log_inner.h" +#endif + #endif // HIVIEWDFX_HILOG_C_H diff --git a/interfaces/rust/BUILD.gn b/interfaces/rust/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..05c32c5965542ed1870d45e0a2d3d8acc2759da5 --- /dev/null +++ b/interfaces/rust/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_rust_shared_library("hilog_rust") { + sources = [ "src/lib.rs" ] + + deps = [ "../../interfaces/native/innerkits:libhilog" ] + + crate_name = "hilog_rust" + crate_type = "dylib" + + subsystem_name = "hiviewdfx" + part_name = "hilog" +} + +group("rust_hilog_component") { + deps = [ ":hilog_rust" ] +} diff --git a/interfaces/rust/Cargo.toml b/interfaces/rust/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..be464e2c9fb351fb38d5f2536ea2a7872343910c --- /dev/null +++ b/interfaces/rust/Cargo.toml @@ -0,0 +1,18 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[package] +name = "hilog_rust" +version = "1.0.0" +edition = "2021" +description = "Native log interface provided for system" +license = "Apache-2.0" +repository = "https://gitee.com/openharmony/hiviewdfx_hilog" diff --git a/interfaces/rust/src/lib.rs b/interfaces/rust/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d4f8793cd576ec385d97371c81b4a5f8ba7725d3 --- /dev/null +++ b/interfaces/rust/src/lib.rs @@ -0,0 +1,92 @@ +// Copyright (C) 2022 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! hilog dylib_crate for Rust. +use std::ffi::c_char; + +#[macro_use] +mod macros; + +/// log level +#[derive(Debug)] +pub enum LogLevel { + /// min log level + LogLevelMin = 0, + /// The "debug" level. + /// + /// Designates lower priority log. + Debug = 3, + /// The "info" level. + /// + /// Designates useful information. + Info = 4, + /// The "warn" level. + /// + /// Designates hazardous situations. + Warn = 5, + /// The "error" level. + /// + /// Designates very serious errors. + Error = 6, + /// The "fatal" level. + /// + /// Designates major fatal anomaly. + Fatal = 7, + /// max log level + LogLevelMax, +} + +/// log type +#[derive(Debug)] +pub enum LogType { + /// log type for app log + LogApp = 0, + /// log type for init log + LogInit = 1, + /// log type for core log + LogCore = 3, + /// log type for kernel log + LogKmsg = 4, + /// max log type + LogTypeMax, +} + +/// hilog label +#[derive(Debug)] +pub struct HiLogLabel { + /// log type + pub log_type: LogType, + /// log domain + pub domain: u32, + /// log tag + pub tag: &'static str, +} + +// hilog ffi interface +extern "C" { + /// hilog ffi interface HiLogIsLoggabel + pub fn HiLogIsLoggable(domain: u32, tag: *const c_char, level: u32) -> bool; + /// hilog ffi interface HiLogPrint + pub fn HiLogPrint( + logType: u8, + level: u8, + domain: u32, + tag: *const c_char, + fmt: *const c_char, + ... + ) -> u32; + /// hilog ffi interface IsPrivateSwitchOn + pub fn IsPrivateSwitchOn() -> bool; + /// hilog ffi interface IsDebugOn + pub fn IsDebugOn() -> bool; +} diff --git a/interfaces/rust/src/macros.rs b/interfaces/rust/src/macros.rs new file mode 100644 index 0000000000000000000000000000000000000000..cdca4f42bc09413c880bda47f625da5a6f2d9ebf --- /dev/null +++ b/interfaces/rust/src/macros.rs @@ -0,0 +1,194 @@ +// Copyright (C) 2022 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! macros crate for Rust. + +/// hilog macros + +#[macro_export] +macro_rules! hilog { + (@call $log_label:ident, $level:expr, $fmt:literal, $(,)? $($processed_args:expr),* ) => ( + let log_str = format!($fmt, $($processed_args),*); + let res = unsafe { + $crate::HiLogPrint($log_label.log_type as u8, $level as u8, $log_label.domain as u32, + CString::new($log_label.tag).expect("default tag").as_ptr() as *const c_char, + CString::new(log_str).expect("default log").as_ptr() as *const c_char) + }; + res + ); + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; ($arg:expr); $(,)? $($processed_args:expr),*) => { + if ($priv_flag) { + hilog!(@call $log_label, $level, $fmt, $($processed_args),*, ""); + } else { + hilog!(@call $log_label, $level, $fmt, $($processed_args),*, $arg); + } + }; + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; (@private($arg:expr)); $(,)? $($processed_args:expr),*) => { + if ($priv_flag) { + hilog!(@call $log_label, $level, $fmt, $($processed_args),*, ""); + } else { + hilog!(@call $log_label, $level, $fmt, $($processed_args),*, $arg); + } + }; + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; (@public($arg:expr)); $(,)? $($processed_args:expr),*) => { + hilog!(@call $log_label, $level, $fmt, $($processed_args),*, $arg); + }; + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; ($arg:expr, $($unprocessed_args:tt)*); $($processed_args:tt)*) => { + if ($priv_flag) { + hilog!(@rec $priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*); $($processed_args)*, ""); + } else { + hilog!(@rec $priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*); $($processed_args)*, $arg); + } + }; + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; (@private($arg:expr), $($unprocessed_args:tt)*); $($processed_args:tt)*) => { + if ($priv_flag) { + hilog!(@rec $priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*); $($processed_args)*, ""); + } else { + hilog!(@rec $priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*); $($processed_args)*, $arg); + } + }; + + (@rec $priv_flag:ident; $log_label:ident; $level:expr; $fmt:literal; (@public($arg:expr), $($unprocessed_args:tt)*); $($processed_args:tt)*) => { + hilog!(@rec $priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*); $($processed_args)*, $arg); + }; + + // Public API + ($log_label:ident, $level:expr, $fmt:literal, $($unprocessed_args:tt)*) => { + let priv_flag = unsafe{ $crate::IsPrivateSwitchOn() && !$crate::IsDebugOn() }; + hilog!(@rec priv_flag; $log_label; $level; $fmt; ($($unprocessed_args)*);); + }; + + ($log_label:ident, $level:expr, $fmt:literal) => { + hilog!(@call $log_label, $level, $fmt,); + }; +} + +/// printf log at the debug level. +/// +/// #Examples +/// +/// ``` +/// use hilog_rust::{debug, hilog, HiLogLabel, LogType}; +/// +/// # fn main() { +/// let log_label: HiLogLabel = HiLogLabel { +/// log_type: LogType::LogCore, +/// domain: 0xd003200, +/// tag: "testTag", +/// }; +/// debug!(LOG_LABEL, "testLog{}", "testargs"); +/// # } +/// ``` +#[macro_export] +macro_rules! debug{ + ($log_label:ident, $($arg:tt)*) => ( + hilog!($log_label, $crate::LogLevel::Debug, $($arg)*) + ); +} + +/// printf log at the info level. +/// +/// #Examples +/// +/// ``` +/// use hilog_rust::{hilog, info, HiLogLabel, LogType}; +/// +/// # fn main() { +/// let log_label: HiLogLabel = HiLogLabel { +/// log_type: LogType::LogCore, +/// domain: 0xd003200, +/// tag: "testTag", +/// }; +/// info!(LOG_LABEL, "testLog{}", "testargs"); +/// # } +/// ``` +#[macro_export] +macro_rules! info{ + ($log_label:ident, $($arg:tt)*) => ( + hilog!($log_label, $crate::LogLevel::Info, $($arg)*) + ); +} + +/// printf log at the warn level. +/// +/// #Examples +/// +/// ``` +/// use hilog_rust::{hilog, warn, HiLogLabel, LogType}; +/// +/// # fn main() { +/// let log_label: HiLogLabel = HiLogLabel { +/// log_type: LogType::LogCore, +/// domain: 0xd003200, +/// tag: "testTag", +/// }; +/// warn!(LOG_LABEL, "testLog{}", "testargs"); +/// # } +/// ``` +#[macro_export] +macro_rules! warn{ + ($log_label:ident, $($arg:tt)*) => ( + hilog!($log_label, $crate::LogLevel::Warn, $($arg)*) + ); +} + +/// printf log at the error level. +/// +/// #Examples +/// +/// ``` +/// use hilog_rust::{error, hilog, HiLogLabel, LogType}; +/// +/// # fn main() { +/// let log_label: HiLogLabel = HiLogLabel { +/// log_type: LogType::LogCore, +/// domain: 0xd003200, +/// tag: "testTag", +/// }; +/// error!(LOG_LABEL, "testLog{}", "testargs"); +/// # } +/// ``` +#[macro_export] +macro_rules! error{ + ($log_label:ident, $($arg:tt)*) => ( + hilog!($log_label, $crate::LogLevel::Error, $($arg)*) + ); +} + +/// printf log at the fatal level. +/// +/// #Examples +/// +/// ``` +/// use hilog_rust::{fatal, hilog, HiLogLabel, LogType}; +/// +/// # fn main() { +/// let log_label: HiLogLabel = HiLogLabel { +/// log_type: LogType::LogCore, +/// domain: 0xd003200, +/// tag: "testTag", +/// }; +/// fatal!(LOG_LABEL, "testLog{}", "testargs"); +/// # } +/// ``` +#[macro_export] +macro_rules! fatal{ + ($log_label:ident, $($arg:tt)*) => ( + hilog!($log_label, $crate::LogLevel::Fatal, $($arg)*) + ); +} diff --git a/platform/BUILD.gn b/platform/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e9228feef3eab7c951de6b7ad5591a2f5e39f7a1 --- /dev/null +++ b/platform/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/hiviewdfx/hilog/hilog.gni") +import("//base/hiviewdfx/hilog/platformlog.gni") +import("//build/ohos.gni") + +template("libhilog_platform_source") { + forward_variables_from(invoker, "*") + ohos_source_set(target_name) { + defines = [ "DFX_PLATFORM_LOG_TAG=\"Ace\"" ] + include_dirs = [ + "${PLATFORM_HILOG_PATH}/frameworks/libhilog/param/include", + "${PLATFORM_HILOG_PATH}/interfaces/native/innerkits/include", + ] + if (target_os == "android") { + defines += [ "ANDROID_PLATFORM" ] + libs = [ "log" ] + } else if (target_os == "ios") { + include_dirs += [ "//third_party/bounds_checking_function/include" ] + defines += [ "IOS_PLATFORM" ] + } + sources = [ + "hilog.cpp", + "hilog_printf.cpp", + "hilog_utils.cpp", + "interface/native/log.cpp", + ] + + subsystem_name = "hiviewdfx" + part_name = "hilog" + } +} + +foreach(item, platforms) { + libhilog_platform_source("libhilog_platform_source_" + item) { + } +} diff --git a/platform/hilog.cpp b/platform/hilog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04c27565ee3622cf18d59d886391dbdbe498b61d --- /dev/null +++ b/platform/hilog.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hilog/log.h" + +#include +#include + +int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, + const char *fmt, va_list ap); + +namespace OHOS { +namespace HiviewDFX { +#define HILOG_VA_ARGS_PROCESS(ret, level) \ + do { \ + va_list args; \ + va_start(args, fmt); \ + (ret) = ::HiLogPrintArgs(label.type, (level), label.domain, label.tag, fmt, args); \ + va_end(args); \ + } while (0) + +int HiLog::Debug(const HiLogLabel &label, const char *fmt, ...) +{ + int ret; + HILOG_VA_ARGS_PROCESS(ret, LOG_DEBUG); + return ret; +} + +int HiLog::Info(const HiLogLabel &label, const char *fmt, ...) +{ + int ret; + HILOG_VA_ARGS_PROCESS(ret, LOG_INFO); + return ret; +} + +int HiLog::Warn(const HiLogLabel &label, const char *fmt, ...) +{ + int ret; + HILOG_VA_ARGS_PROCESS(ret, LOG_WARN); + return ret; +} + +int HiLog::Error(const HiLogLabel &label, const char *fmt, ...) +{ + int ret; + HILOG_VA_ARGS_PROCESS(ret, LOG_ERROR); + return ret; +} + +int HiLog::Fatal(const HiLogLabel &label, const char *fmt, ...) +{ + int ret; + HILOG_VA_ARGS_PROCESS(ret, LOG_FATAL); + return ret; +} +} // namespace HiviewDFX +} // namespace OHOS diff --git a/platform/hilog_printf.cpp b/platform/hilog_printf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eab43d483f8f3e0b40d068d2e5a1083798f47f88 --- /dev/null +++ b/platform/hilog_printf.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hilog/log.h" +#include "interface/native/log.h" + +static OHOS::HiviewDFX::Hilog::Platform::LogLevel ConvertLogLevel(LogLevel level) +{ + if (level == LogLevel::LOG_DEBUG) { + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Debug; + } else if (level == LogLevel::LOG_INFO) { + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Info; + } else if (level == LogLevel::LOG_WARN) { + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Warn; + } else if (level == LogLevel::LOG_ERROR) { + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Error; + } else if (level == LogLevel::LOG_FATAL) { + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Fatal; + } + + return OHOS::HiviewDFX::Hilog::Platform::LogLevel::Debug; +} + +int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, + const char *fmt, va_list ap) +{ + OHOS::HiviewDFX::Hilog::Platform::LogPrint(ConvertLogLevel(level), fmt, ap); + return 0; +} + +int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = HiLogPrintArgs(type, level, domain, tag, fmt, ap); + va_end(ap); + return ret; +} + +bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level) +{ + if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == nullptr) { + return false; + } + + return true; +} diff --git a/platform/hilog_utils.cpp b/platform/hilog_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb70867b2b02d1193d5ebba34c5657d8ee7d3c22 --- /dev/null +++ b/platform/hilog_utils.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "properties.h" + +namespace OHOS::HiviewDFX { +bool IsDebugOn() +{ + return false; +} + +bool IsPrivateSwitchOn() +{ + return true; +} +} // namespace OHOS::HiviewDFX \ No newline at end of file diff --git a/platform/interface/native/log.cpp b/platform/interface/native/log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..470a9d3bc0c2cf1d1abd5f75a316f37686ee8777 --- /dev/null +++ b/platform/interface/native/log.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "log.h" +#if defined(ANDROID_PLATFORM) +#include +#endif + +#if defined(IOS_PLATFORM) +#include +#import +#endif + +namespace OHOS::HiviewDFX::Hilog::Platform { +[[maybe_unused]] static void StripFormatString(const std::string& prefix, std::string& str) +{ + for (auto pos = str.find(prefix, 0); pos != std::string::npos; pos = str.find(prefix, pos)) { + str.erase(pos, prefix.size()); + } +} + +void LogPrint(LogLevel level, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + LogPrint(level, fmt, args); + va_end(args); +} + +#if defined(ANDROID_PLATFORM) +constexpr int32_t LOG_LEVEL[] = { ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, + ANDROID_LOG_FATAL }; + +void LogPrint(LogLevel level, const char* fmt, va_list args) +{ + std::string newFmt(fmt); + StripFormatString("{public}", newFmt); + StripFormatString("{private}", newFmt); + __android_log_vprint(LOG_LEVEL[static_cast(level)], DFX_PLATFORM_LOG_TAG, newFmt.c_str(), args); +} +#endif + +#if defined(IOS_PLATFORM) +constexpr uint32_t MAX_BUFFER_SIZE = 4096; +constexpr os_log_type_t LOG_TYPE[] = {OS_LOG_TYPE_DEBUG, OS_LOG_TYPE_INFO, OS_LOG_TYPE_DEFAULT, OS_LOG_TYPE_ERROR, + OS_LOG_TYPE_FAULT}; +constexpr const char* LOG_TYPE_NAME[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + +void LogPrint(LogLevel level, const char* fmt, va_list args) +{ + std::string newFmt(fmt); + StripFormatString("{public}", newFmt); + StripFormatString("{private}", newFmt); + char buf[MAX_BUFFER_SIZE] = { '\0' }; + int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, newFmt.c_str(), args); + if (ret < 0) { + return; + } + os_log_type_t logType = LOG_TYPE[static_cast(level)]; + const char* levelName = LOG_TYPE_NAME[static_cast(level)]; + os_log_t log = os_log_create(DFX_PLATFORM_LOG_TAG, levelName); + os_log(log, "[%{public}s] %{public}s", levelName, buf); +} +#endif +} // namespace OHOS::HiviewDFX::Hilog::Platform \ No newline at end of file diff --git a/platform/interface/native/log.h b/platform/interface/native/log.h new file mode 100644 index 0000000000000000000000000000000000000000..b59d07c96f88d8b1193444873a6c6fbd9e742da8 --- /dev/null +++ b/platform/interface/native/log.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PLATFORM_INTERFACE_NATIVE_LOG_H +#define PLATFORM_INTERFACE_NATIVE_LOG_H + +#include +#include + +#define __FILENAME__ strrchr(__FILE__, '/') + 1 + +namespace OHOS::HiviewDFX::Hilog::Platform { + +enum class LogLevel : uint32_t { + Debug = 0, + Info, + Warn, + Error, + Fatal, +}; + +void LogPrint(LogLevel level, const char* fmt, ...); +void LogPrint(LogLevel level, const char* fmt, va_list args); + +#define LOG_PRINT(Level, fmt, ...) \ + OHOS::HiviewDFX::Hilog::Platform::LogPrint(OHOS::HiviewDFX::Hilog::Platform::LogLevel::Level, \ + "[%-20s(%s)] " fmt, __FILENAME__, __FUNCTION__, ##__VA_ARGS__) + +#define LOGF(fmt, ...) LOG_PRINT(Fatal, fmt, ##__VA_ARGS__) +#define LOGE(fmt, ...) LOG_PRINT(Error, fmt, ##__VA_ARGS__) +#define LOGW(fmt, ...) LOG_PRINT(Warn, fmt, ##__VA_ARGS__) +#define LOGI(fmt, ...) LOG_PRINT(Info, fmt, ##__VA_ARGS__) +#define LOGD(fmt, ...) LOG_PRINT(Debug, fmt, ##__VA_ARGS__) +} // namespace OHOS::HiviewDFX::Hilog::Platform + +#endif // PLATFORM_INTERFACE_NATIVE_LOG_H diff --git a/platformlog.gni b/platformlog.gni new file mode 100644 index 0000000000000000000000000000000000000000..d4e272f0b58666f1487b2f8adef12fc3b72aa699 --- /dev/null +++ b/platformlog.gni @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PLATFORM_HILOG_PATH = "//base/hiviewdfx/hilog" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000000000000000000000000000000000000..d9c0940b56afca50033a41b970096bef9d9179c6 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,17 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +edition = "2021" +wrap_comments = true +imports_granularity = "Module" +group_imports = "StdExternalCrate" +format_code_in_doc_comments = true +normalize_comments = true diff --git a/services/bundle.json b/services/bundle.json deleted file mode 100644 index 2a3e161f8c5279e479613d1b1786245a1456a3a6..0000000000000000000000000000000000000000 --- a/services/bundle.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@ohos/hilog_service", - "description": "Log service provided for the system framework, services, and applications", - "version": "3.1", - "license": "Apache License 2.0", - "publishAs": "code-segment", - "segment": { - "destPath": "base/hiviewdfx/hilog" - }, - "dirs": {}, - "scripts": {}, - "component": { - "name": "hilog_service", - "subsystem": "hiviewdfx", - "syscap": [ - "SystemCapability.HiviewDFX.HiLog" - ], - "adapted_system_type": [ - "standard" - ], - "rom": "460KB", - "ram": "14336KB", - "deps": { - "components": [ - "init", - "utils_base" - ], - "third_party": [ - "bounds_checking_function", - "zlib" - ] - }, - "build": { - "sub_component": [ - "//base/hiviewdfx/hilog/services/hilogtool:hilog", - "//base/hiviewdfx/hilog/services/hilogd:hilogd" - ], - "inner_kits": [], - "test": [ "//base/hiviewdfx/hilog/test:HiLogNDKTest" ] - } - } -} \ No newline at end of file diff --git a/services/hilogd/BUILD.gn b/services/hilogd/BUILD.gn index 379d704b2f70cd1c8e23b18303b8d36c5270db0c..d3a333e02f3c67abba9371ab2fd9e1bbfe7a8daf 100644 --- a/services/hilogd/BUILD.gn +++ b/services/hilogd/BUILD.gn @@ -42,19 +42,19 @@ ohos_executable("hilogd") { defines = [ "__RECV_MSG_WITH_UCRED_" ] deps = [ "//third_party/bounds_checking_function:libsec_shared", - "//third_party/zlib:libz", + "//third_party/zlib:shared_libz", ] - deps += [ "etc:hilogd_etc" ] - - external_deps = [ - "hilog_native:libhilog", - "init:libbegetutil", + deps += [ + "../../interfaces/native/innerkits:libhilog", + "etc:hilogd_etc", ] + + external_deps = [ "init:libbegetutil" ] install_images = [ "system", "updater", ] install_enable = true - part_name = "hilog_service" + part_name = "hilog" subsystem_name = "hiviewdfx" } diff --git a/services/hilogd/cmd_executor.cpp b/services/hilogd/cmd_executor.cpp index 4af273925caba0e6cf320668e1675d498b329d73..9ab6fde8beeea212c979127115d9e6238c23ed1d 100644 --- a/services/hilogd/cmd_executor.cpp +++ b/services/hilogd/cmd_executor.cpp @@ -91,7 +91,7 @@ void CmdExecutor::ClientEventLoop(std::unique_ptr handler) } prctl(PR_SET_NAME, m_name.c_str()); - ServiceController serviceCtrl(std::move(handler), m_logCollector, m_hilogBuffer); + ServiceController serviceCtrl(std::move(handler), m_logCollector, m_hilogBuffer, m_kmsgBuffer); serviceCtrl.CommunicationLoop((*clientInfoIt)->m_stopThread, m_cmdList); std::lock_guard ul(m_finishedClientAccess); diff --git a/services/hilogd/etc/BUILD.gn b/services/hilogd/etc/BUILD.gn index a0bd3afa07554f0875104b845315e7943f2453c9..41ca6cac62bf552fce1f3a69c02d41666c367d1e 100644 --- a/services/hilogd/etc/BUILD.gn +++ b/services/hilogd/etc/BUILD.gn @@ -24,20 +24,20 @@ group("hilogd_etc") { ohos_prebuilt_etc("hilogd.cfg") { source = "hilogd.cfg" relative_install_dir = "init" - part_name = "hilog_service" + part_name = "hilog" subsystem_name = "hiviewdfx" } ohos_prebuilt_etc("hilog.para") { source = "hilog.para" relative_install_dir = "param" - part_name = "hilog_service" + part_name = "hilog" subsystem_name = "hiviewdfx" } ohos_prebuilt_etc("hilog.para.dac") { source = "hilog.para.dac" relative_install_dir = "param" - part_name = "hilog_service" + part_name = "hilog" subsystem_name = "hiviewdfx" } diff --git a/services/hilogd/etc/hilogd.cfg b/services/hilogd/etc/hilogd.cfg index 615f5197844d15d4f33b3fcb2e07792757144067..e3079d7d9c52109e029008d5a800a26f5368091a 100644 --- a/services/hilogd/etc/hilogd.cfg +++ b/services/hilogd/etc/hilogd.cfg @@ -1,14 +1,10 @@ { "jobs" : [{ - "name" : "pre-init", - "cmds" : [ - "start hilogd" - ] - },{ - "name" : "post-fs-data", + "name" : "init", "cmds" : [ "mkdir /data/log/ 0775 system log", - "mkdir /data/log/hilog/ 0755 logd log" + "mkdir /data/log/hilog/ 0755 logd log", + "start hilogd" ] }, { "name" : "services:hilogd", @@ -58,6 +54,7 @@ "option" : [ ] }], + "caps" : [ "SYSLOG" ], "start-mode" : "condition", "secon" : "u:r:hilogd:s0" } diff --git a/services/hilogd/include/cmd_executor.h b/services/hilogd/include/cmd_executor.h index d6d6d6cf1c85ad4e761985fbfe1a912be2328352..e0add440407a555396270c72c0158faae9bce9a3 100644 --- a/services/hilogd/include/cmd_executor.h +++ b/services/hilogd/include/cmd_executor.h @@ -35,8 +35,9 @@ struct ClientThread { class CmdExecutor { public: - explicit CmdExecutor(LogCollector& collector, HilogBuffer& buffer, const CmdList& list, const std::string& name) - : m_logCollector(collector), m_hilogBuffer(buffer), m_cmdList(list), m_name(name) {} + explicit CmdExecutor(LogCollector& collector, HilogBuffer& hilogBuffer, HilogBuffer& kmsgBuffer, + const CmdList& list, const std::string& name) : m_logCollector(collector), m_hilogBuffer(hilogBuffer), + m_kmsgBuffer(kmsgBuffer), m_cmdList(list), m_name(name) {} ~CmdExecutor(); void MainLoop(const std::string& sockName); private: @@ -46,6 +47,7 @@ private: LogCollector& m_logCollector; HilogBuffer& m_hilogBuffer; + HilogBuffer& m_kmsgBuffer; CmdList m_cmdList; std::string m_name; std::list> m_clients; diff --git a/services/hilogd/include/log_buffer.h b/services/hilogd/include/log_buffer.h index 00a1004642bfd8cbdc88e0965601841198fa0699..93595c714e2a3db31bf1930e1049560498922b0d 100644 --- a/services/hilogd/include/log_buffer.h +++ b/services/hilogd/include/log_buffer.h @@ -36,10 +36,10 @@ public: using LogMsgContainer = std::list; using ReaderId = uintptr_t; - HilogBuffer(); + HilogBuffer(bool isSupportSkipLog); ~HilogBuffer(); - size_t Insert(const HilogMsg& msg); + size_t Insert(const HilogMsg& msg, bool& isFull); std::optional Query(const LogFilter& filter, const ReaderId& id, int tailCount = 0); ReaderId CreateBufReader(std::function onNewDataCallback); @@ -67,6 +67,7 @@ private: BUFF_OVERFLOW, CMD_CLEAR }; + bool IsItemUsed(LogMsgContainer::iterator itemPos); void OnDeleteItem(LogMsgContainer::iterator itemPos, DeleteReason reason); void OnPushBackedItem(LogMsgContainer& msgList); void OnNewItem(LogMsgContainer& msgList); @@ -74,11 +75,11 @@ private: size_t sizeByType[LOG_TYPE_MAX]; LogMsgContainer hilogDataList; - LogMsgContainer hilogKlogList; std::shared_mutex hilogBufferMutex; std::map> m_logReaders; std::shared_mutex m_logReaderMtx; LogStats stats; + bool m_isSupportSkipLog; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_collector.h b/services/hilogd/include/log_collector.h index 0cbfa6a25e123cada68d71079cdd48086f16105a..53e764139eda7ab36888176334b3404c6d833467 100644 --- a/services/hilogd/include/log_collector.h +++ b/services/hilogd/include/log_collector.h @@ -34,9 +34,9 @@ public: void InsertDropInfo(const HilogMsg &msg, int droppedCount); size_t InsertLogToBuffer(const HilogMsg& msg); #ifndef __RECV_MSG_WITH_UCRED_ - void onDataRecv(std::vector& data); + void onDataRecv(std::vector& data, int dataLen); #else - void onDataRecv(const ucred& cred, std::vector& data); + void onDataRecv(const ucred& cred, std::vector& data, int dataLen); #endif void SetLogFlowControl(bool on); void SetDebuggable(bool on); diff --git a/services/hilogd/include/log_persister_rotator.h b/services/hilogd/include/log_persister_rotator.h index 147e795eb70d5067b6978a13fddaeaca9e4e2f9b..3070f8cf92b5bd549480b0410b381ebbe56d5e20 100644 --- a/services/hilogd/include/log_persister_rotator.h +++ b/services/hilogd/include/log_persister_rotator.h @@ -66,6 +66,7 @@ private: uint32_t m_maxLogFileNum = 0; std::string m_logsPath; std::string m_fileNameSuffix; + std::string m_currentLogFileName; uint32_t m_currentLogFileIdx = 0; std::fstream m_currentLogOutput; diff --git a/services/hilogd/include/service_controller.h b/services/hilogd/include/service_controller.h index 7af1ff3b420277dd4f580eb6b07cdf917df5b4c4..5f258e40209805e74dc79ff2d6d129fca4d51e49 100644 --- a/services/hilogd/include/service_controller.h +++ b/services/hilogd/include/service_controller.h @@ -42,7 +42,8 @@ public: static constexpr int MAX_DATA_LEN = 2048; using PacketBuf = std::array; - ServiceController(std::unique_ptr communicationSocket, LogCollector& collector, HilogBuffer& buffer); + ServiceController(std::unique_ptr communicationSocket, LogCollector& collector, HilogBuffer& hilogBuffer, + HilogBuffer& kmsgBuffer); ~ServiceController(); void CommunicationLoop(std::atomic& stopLoop, const CmdList& list); @@ -90,8 +91,9 @@ private: std::unique_ptr m_communicationSocket; LogCollector& m_logCollector; HilogBuffer& m_hilogBuffer; - HilogBuffer::ReaderId m_bufReader; - + HilogBuffer& m_kmsgBuffer; + HilogBuffer::ReaderId m_hilogBufferReader; + HilogBuffer::ReaderId m_kmsgBufferReader; std::condition_variable m_notifyNewDataCv; std::mutex m_notifyNewDataMtx; }; @@ -110,7 +112,7 @@ void ServiceController::RequestHandler(const MsgHeader& hdr, std::function res; - if (std::regex_search(str.begin(), str.end(), res, express)) { - *level = strtoul(res[1].str().c_str(), nullptr, DEC); - *timestamp = strtoumax(res[3].str().c_str(), nullptr, DEC); - str.erase(res.position(), res.length()); - } -} - -// Parse pid if exists -static uint32_t ParsePid(std::string& str) -{ - static const std::string pattern = "\\[pid=(\\d+)\\]"; - static const std::regex express(pattern); - std::match_results res; - if (std::regex_search(str.begin(), str.end(), res, express)) { - uint32_t ret = strtoumax(res[1].str().c_str(), nullptr, DEC); - str.erase(res.position(), res.length()); - return ret; - } - return 0; -} - -static std::string ParseTag(std::string& str) -{ - static const std::string pattern = "\\[.*?\\]"; - static const std::regex express(pattern); - std::match_results res; - if (std::regex_search(str.begin(), str.end(), res, express)) { - std::string ret = res[0].str(); - str.erase(res.position(), res.length()); - return ret; - } - return {}; -} - // Log levels are different in syslog.h and hilog log_c.h static uint16_t KmsgLevelMap(uint16_t prio) { @@ -120,48 +79,11 @@ static uint16_t KmsgLevelMap(uint16_t prio) return level; } -static constexpr timespec TimepointToTimespec(time_point tp) -{ - auto secs = time_point_cast(tp); - auto nsecs = time_point_cast(tp) - time_point_cast(secs); - return timespec{secs.time_since_epoch().count(), nsecs.count()}; -} - -// Kmsg has microseconds from system boot. Now get the time of system boot. -KmsgParser::BootTp KmsgParser::BootTime() -{ - struct timespec t_uptime; - clock_gettime(CLOCK_BOOTTIME, &t_uptime); - auto uptime = seconds{t_uptime.tv_sec} + nanoseconds{t_uptime.tv_nsec}; - auto current = system_clock::now(); - auto boottime = current - uptime; - return boottime; -} std::optional KmsgParser::ParseKmsg(const std::vector& kmsgBuffer) { std::string kmsgStr(kmsgBuffer.data()); - std::vector mtag(MAX_TAG_LEN, '\0'); - uint16_t mLevel = 0; - uint64_t timestamp = 0; - ParseHeader(kmsgStr, &mLevel, ×tamp); - // Parses pid if exists. Pid in kmsg content is like: [pid=xxx,...] - uint32_t mpid = ParsePid(kmsgStr); - // If there are some other content wrapped in square brackets "[]", parse it as tag - // Otherwise, use default tag "kmsg" - size_t tagLen = 0; - std::string tagStr = ParseTag(kmsgStr); - if (!tagStr.empty()) { - tagLen = tagStr.size(); - if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, tagStr.c_str(), tagStr.size()) != 0) { - return {}; - } - } else { - constexpr auto defaultTag = "kmsg"sv; - tagLen = defaultTag.size(); - if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, defaultTag.data(), defaultTag.size()) != 0) { - return {}; - } - } + std::string tagStr = ""; + size_t tagLen = tagStr.size(); // Now build HilogMsg and insert it into buffer auto len = kmsgStr.size() + 1; auto msgLen = sizeof(HilogMsg) + tagLen + len + 1; @@ -170,15 +92,12 @@ std::optional KmsgParser::ParseKmsg(const std::vector& km msg.len = msgLen; msg.tag_len = tagLen + 1; msg.type = LOG_KMSG; - msg.domain = 0xD002600; - msg.level = KmsgLevelMap(mLevel); - time_point logtime = BootTime() + microseconds{timestamp}; - struct timespec logts = TimepointToTimespec(logtime); - msg.tv_sec = static_cast(logts.tv_sec); - msg.tv_nsec = static_cast(logts.tv_nsec); - msg.pid = mpid; - msg.tid = mpid; - if (strncpy_s(msg.tag, tagLen + 1, mtag.data(), tagLen) != 0) { + msg.level = KmsgLevelMap(LOG_INFO); + struct timespec ts = {0}; + (void)clock_gettime(CLOCK_REALTIME, &ts); + msg.tv_sec = static_cast(ts.tv_sec); + msg.tv_nsec = static_cast(ts.tv_nsec); + if (strncpy_s(msg.tag, tagLen + 1, tagStr.c_str(), tagLen) != 0) { return {}; } if (strncpy_s(CONTENT_PTR((&msg)), MAX_LOG_LEN, kmsgStr.c_str(), len) != 0) { diff --git a/services/hilogd/log_buffer.cpp b/services/hilogd/log_buffer.cpp index 90199d86774941d2580f7341c44703fa0edcc96c..788949d5ef6c8c072420c4f5054f0b206e982e2f 100644 --- a/services/hilogd/log_buffer.cpp +++ b/services/hilogd/log_buffer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,7 @@ using namespace std; static size_t g_maxBufferSizeByType[LOG_TYPE_MAX] = {262144, 262144, 262144, 262144, 262144}; static int GenerateHilogMsgInside(HilogMsg& hilogMsg, const string& msg, uint16_t logType); -HilogBuffer::HilogBuffer() +HilogBuffer::HilogBuffer(bool isSupportSkipLog) : m_isSupportSkipLog(isSupportSkipLog) { for (int i = 0; i < LOG_TYPE_MAX; i++) { sizeByType[i] = 0; @@ -70,40 +71,46 @@ void HilogBuffer::InitBuffHead() } string tmpStr = msg + typeStr; if (GenerateHilogMsgInside(*headMsg, tmpStr, i) == RET_SUCCESS) { - Insert(*headMsg); + bool isFull = false; + Insert(*headMsg, isFull); } } } HilogBuffer::~HilogBuffer() {} -size_t HilogBuffer::Insert(const HilogMsg& msg) +size_t HilogBuffer::Insert(const HilogMsg& msg, bool& isFull) { size_t elemSize = CONTENT_LEN((&msg)); /* include '\0' */ - - if (unlikely(msg.tag_len > MAX_TAG_LEN || msg.tag_len == 0 || elemSize > MAX_LOG_LEN || elemSize <= 0)) { + if (unlikely(msg.tag_len > MAX_TAG_LEN || msg.tag_len == 0 || elemSize > MAX_LOG_LEN || + elemSize == 0 || msg.type >= LOG_TYPE_MAX)) { return 0; } - - LogMsgContainer &msgList = (msg.type == LOG_KMSG) ? hilogKlogList : hilogDataList; + isFull = false; { - std::unique_lock lock(hilogBufferMutex); + std::lock_guard lock(hilogBufferMutex); // Delete old entries when full if (elemSize + sizeByType[msg.type] >= g_maxBufferSizeByType[msg.type]) { // Drop 5% of maximum log when full - std::list::iterator it = msgList.begin(); + std::list::iterator it = hilogDataList.begin(); static const float DROP_RATIO = 0.05; while (sizeByType[msg.type] > g_maxBufferSizeByType[msg.type] * (1 - DROP_RATIO) && - it != msgList.end()) { + it != hilogDataList.end()) { if ((*it).type != msg.type) { // Only remove old logs of the same type ++it; continue; } + + if (IsItemUsed(it)) { + isFull = true; + return 0; + } + OnDeleteItem(it, DeleteReason::BUFF_OVERFLOW); size_t cLen = it->len - it->tag_len; sizeByType[(*it).type] -= cLen; - it = msgList.erase(it); + it = hilogDataList.erase(it); } // Re-confirm if enough elements has been removed @@ -113,18 +120,38 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) } // Append new log into HilogBuffer - msgList.emplace_back(msg); - OnPushBackedItem(msgList); + hilogDataList.emplace_back(msg); + // Update current size of HilogBuffer + sizeByType[msg.type] += elemSize; + OnPushBackedItem(hilogDataList); } - // Update current size of HilogBuffer - sizeByType[msg.type] += elemSize; - // Notify readers about new element added - OnNewItem(msgList); + OnNewItem(hilogDataList); return elemSize; } +// Replace wildcard with regex +static std::string WildcardToRegex(const std::string& wildcard) +{ + // Original and Replacement char array + const static char* WILDCARDS = "*?[]+.^&"; + const static std::string REPLACEMENT_S[] = {".*", ".", "\\[", "\\]", "\\+", "\\.", "\\^", "\\&"}; + // Modify every wildcard to regex + std::string result = ""; + for (char c : wildcard) { + // strchr matches wildcard and char + if (std::strchr(WILDCARDS, c) != nullptr) { + size_t index = std::strchr(WILDCARDS, c) - WILDCARDS; + result += REPLACEMENT_S[index]; + } + else { + result += c; + } + } + return result; +} + static bool LogMatchFilter(const LogFilter& filter, const HilogData& logData) { // types & levels match @@ -178,7 +205,9 @@ static bool LogMatchFilter(const LogFilter& filter, const HilogData& logData) } // regular expression match if (filter.regex[0] != 0) { - std::regex regExpress(filter.regex); + // Added a WildcardToRegex function for invalid regex. + std::string wildcardRegex = WildcardToRegex(filter.regex); + std::regex regExpress(wildcardRegex); if (std::regex_search(logData.content, regExpress) == false) { return false; } @@ -193,20 +222,18 @@ std::optional HilogBuffer::Query(const LogFilter& filter, const Reade std::cerr << "Reader not registered!\n"; return std::nullopt; } - uint16_t qTypes = filter.types; - LogMsgContainer &msgList = (qTypes == (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; std::shared_lock lock(hilogBufferMutex); - if (reader->m_msgList != &msgList) { - reader->m_msgList = &msgList; + if (reader->m_msgList != &hilogDataList) { + reader->m_msgList = &hilogDataList; if (tailCount == 0) { - reader->m_pos = msgList.begin(); + reader->m_pos = hilogDataList.begin(); } else { - reader->m_pos = msgList.end(); + reader->m_pos = hilogDataList.end(); reader->m_pos--; } - for (int i = 0; (i < tailCount) && (reader->m_pos != msgList.begin());) { + for (int i = 0; (i < tailCount) && (reader->m_pos != hilogDataList.begin());) { if (LogMatchFilter(filter, (*reader->m_pos))) { i++; } @@ -226,7 +253,7 @@ std::optional HilogBuffer::Query(const LogFilter& filter, const Reade } } - while (reader->m_pos != msgList.end()) { + while (reader->m_pos != hilogDataList.end()) { const HilogData& logData = *reader->m_pos; reader->m_pos++; if (LogMatchFilter(filter, logData)) { @@ -238,16 +265,15 @@ std::optional HilogBuffer::Query(const LogFilter& filter, const Reade int32_t HilogBuffer::Delete(uint16_t logType) { - std::list &msgList = (logType == LOG_KMSG) ? hilogKlogList : hilogDataList; if (logType >= LOG_TYPE_MAX) { return ERR_LOG_TYPE_INVALID; } size_t sum = 0; std::unique_lock lock(hilogBufferMutex); - std::list::iterator it = msgList.begin(); + std::list::iterator it = hilogDataList.begin(); // Delete logs corresponding to queryCondition - while (it != msgList.end()) { + while (it != hilogDataList.end()) { // Only remove old logs of the same type if ((*it).type != logType) { ++it; @@ -259,7 +285,7 @@ int32_t HilogBuffer::Delete(uint16_t logType) size_t cLen = it->len - it->tag_len; sum += cLen; sizeByType[(*it).type] -= cLen; - it = msgList.erase(it); + it = hilogDataList.erase(it); } return sum; } @@ -286,6 +312,20 @@ void HilogBuffer::RemoveBufReader(const ReaderId& id) } } +bool HilogBuffer::IsItemUsed(LogMsgContainer::iterator itemPos) +{ + if (m_isSupportSkipLog) { + return false; + } + std::shared_lock lock(m_logReaderMtx); + for (auto& [id, readerPtr] : m_logReaders) { + if (readerPtr->m_pos == itemPos) { + return true; + } + } + return false; +} + void HilogBuffer::OnDeleteItem(LogMsgContainer::iterator itemPos, DeleteReason reason) { std::shared_lock lock(m_logReaderMtx); diff --git a/services/hilogd/log_collector.cpp b/services/hilogd/log_collector.cpp index b90236bc2a80c9da51bcd9f22341bf757b62b0a6..26969c6891abb7b3b9b18ba189cb0508444c7711 100644 --- a/services/hilogd/log_collector.cpp +++ b/services/hilogd/log_collector.cpp @@ -64,20 +64,20 @@ void LogCollector::InsertDropInfo(const HilogMsg &msg, int droppedCount) } } #ifndef __RECV_MSG_WITH_UCRED_ -void LogCollector::onDataRecv(std::vector& data) +void LogCollector::onDataRecv(std::vector& data, int dataLen) #else -void LogCollector::onDataRecv(const ucred& cred, std::vector& data) +void LogCollector::onDataRecv(const ucred& cred, std::vector& data, int dataLen) #endif { - if (data.size() < sizeof(HilogMsg)) { - std::cerr << "Internal error - received data less than HilogMsg size"; + if (dataLen < sizeof(HilogMsg)) { return; } - HilogMsg& msg = *(reinterpret_cast(data.data())); + if (dataLen != msg.len) { + return; + } // check domain id - if (!debug && IsValidDomain(static_cast(msg.type), msg.domain) == false) { - std::cout << "Invalid domain id: 0x" << std::hex << msg.domain << std::dec << ", type:" << msg.type << endl; + if (IsValidDomain(static_cast(msg.type), msg.domain) == false) { return; } #ifdef __RECV_MSG_WITH_UCRED_ @@ -98,11 +98,17 @@ void LogCollector::onDataRecv(const ucred& cred, std::vector& data) // >0 means a new statistic period start, "ret" is the number of dropping lines in last period InsertDropInfo(msg, ret); } - InsertLogToBuffer(msg); + // If insert msg fail, return 0 + if (InsertLogToBuffer(msg) == 0) { + return; + } } while (0); // Log statistics if (countEnable) { + if (*(msg.tag + msg.tag_len - 1) != '\0') { + return; + } StatsInfo info = { .level = msg.level, .type = msg.type, @@ -121,10 +127,8 @@ void LogCollector::onDataRecv(const ucred& cred, std::vector& data) size_t LogCollector::InsertLogToBuffer(const HilogMsg& msg) { - if (msg.type >= LOG_TYPE_MAX) { - return ERR_LOG_TYPE_INVALID; - } - return m_hilogBuffer.Insert(msg); + bool isFull = false; + return m_hilogBuffer.Insert(msg, isFull); } void LogCollector::SetLogFlowControl(bool on) diff --git a/services/hilogd/log_domains.cpp b/services/hilogd/log_domains.cpp index 1699bbc5650b3964f8d5056bbb595de96b08ece5..3167deb2179959ccb00166eff40efc34b0f682c7 100644 --- a/services/hilogd/log_domains.cpp +++ b/services/hilogd/log_domains.cpp @@ -65,6 +65,20 @@ static const KVMap g_DomainList({ {0xD004300, "Storage"}, {0xD004400, "DeviceProfile"}, {0xD004500, "WebView"}, + {0xD004600, "Interconnection"}, + {0xD004700, "Cloud"}, + {0xD004800, "Manufacture"}, + {0xD004900, "HealthSport"}, + {0xD005100, "PcService"}, + {0xD005200, "WpaSupplicant"}, + {0xD005300, "Push"}, + {0xD005400, "CarService"}, + {0xD005500, "DeviceCloudGateway"}, + {0xD005600, "AppSecurityPrivacy"}, + {0xD005700, "DSoftBus"}, + {0xD005800, "FindNetwork"}, + {0xD005900, "VirtService"}, + {0xD005A00, "AccessControl"}, {0xD00AD00, "ASystem"}, }, __UINT32_MAX__, "Invalid"); @@ -78,7 +92,7 @@ bool IsValidDomain(LogType type, uint32_t domain) } return false; } else { - if (domain > DOMAIN_OS_MIN && domain < DOMAIN_OS_MAX) { + if (domain >= DOMAIN_OS_MIN && domain <= DOMAIN_OS_MAX) { return g_DomainList.IsValidKey((domain & OS_SUB_DOMAIN_MASK)); } return false; diff --git a/services/hilogd/log_kmsg.cpp b/services/hilogd/log_kmsg.cpp index 7b4b479269d0785c4000b2cc3fd97e7a26352caa..aa98c7885feb13a323bca14cfee4f18d6f1ce273 100644 --- a/services/hilogd/log_kmsg.cpp +++ b/services/hilogd/log_kmsg.cpp @@ -35,6 +35,11 @@ namespace OHOS { namespace HiviewDFX { using namespace std; +constexpr int OPEN_KMSG_TIME = 3000; // 3s +constexpr int RETRY_WAIT = 10; // 10us +const char* PROC_KMSG = "/proc/kmsg"; +const char* DEV_KMSG = "/dev/kmsg"; + LogKmsg& LogKmsg::GetInstance(HilogBuffer& hilogBuffer) { static LogKmsg logKmsg(hilogBuffer); @@ -51,9 +56,11 @@ ssize_t LogKmsg::LinuxReadOneKmsg(KmsgParser& parser) if (size > 0) { std::optional msgWrap = parser.ParseKmsg(kmsgBuffer); if (msgWrap.has_value()) { - size_t result = hilogBuffer.Insert(msgWrap->GetHilogMsg()); - if (result <= 0) { - return result; + bool isFull = false; + hilogBuffer.Insert(msgWrap->GetHilogMsg(), isFull); + while (isFull) { + usleep(RETRY_WAIT); + hilogBuffer.Insert(msgWrap->GetHilogMsg(), isFull); } } } @@ -64,12 +71,26 @@ int LogKmsg::LinuxReadAllKmsg() { ssize_t rdFailTimes = 0; const ssize_t maxFailTime = 10; - kmsgCtl = GetControlFile("/dev/kmsg"); - if (kmsgCtl < 0) { - std::cout << "Cannot open kmsg! "; - PrintErrorno(errno); - return -1; + if (access(PROC_KMSG, R_OK) != 0) { + this->kmsgCtl = GetControlFile(DEV_KMSG); + if (this->kmsgCtl < 0) { + return RET_FAIL; + } + } else { + int ret = WaitingToDo(OPEN_KMSG_TIME, PROC_KMSG, [this] (const string &path) { + this->kmsgCtl = open(path.c_str(), O_RDONLY); + if (this->kmsgCtl < 0) { + std::cout << "Cannot open kmsg " << this->kmsgCtl << std::endl; + return RET_FAIL; + } + return RET_SUCCESS; + }); + if (ret != RET_SUCCESS) { + return RET_FAIL; + } } + + std::cout << "Open kmsg success." << std::endl; std::unique_ptr parser = std::make_unique(); if (parser == nullptr) { return -1; diff --git a/services/hilogd/log_persister.cpp b/services/hilogd/log_persister.cpp index 3cf611d14acf07e29d9ec4e181b497cb1dded862..43e4b6bd59bda2bc9cd4a85fa9721da9e5388048 100644 --- a/services/hilogd/log_persister.cpp +++ b/services/hilogd/log_persister.cpp @@ -59,9 +59,6 @@ std::list> LogPersister::s_logPersisters; std::shared_ptr LogPersister::CreateLogPersister(HilogBuffer &buffer) { - // Because of: - // - static_assert(is_constructible<_Tp, _Args...>::value, "Can't construct object in make_shared"); - // make shared can't be used! return std::shared_ptr(new LogPersister(buffer)); } @@ -351,7 +348,6 @@ int LogPersister::ReceiveLogLoop() (void)m_compressor->Compress(*m_mappedPlainLogFile, *m_compressBuffer); WriteCompressedLogs(); } - cout << "6" << endl; } } // try to compress the remaining log in cache diff --git a/services/hilogd/log_persister_rotator.cpp b/services/hilogd/log_persister_rotator.cpp index 83918ea5b9e5257ea6ca8d70f7cf24143187c752..68f1fff81f179a4e39dd0fecc0e0017d1a7ba19d 100644 --- a/services/hilogd/log_persister_rotator.cpp +++ b/services/hilogd/log_persister_rotator.cpp @@ -97,7 +97,7 @@ int LogPersisterRotator::Input(const char *buf, uint32_t length) if (m_needRotate) { Rotate(); m_needRotate = false; - } else if (!m_currentLogOutput.is_open()) { + } else if ((access(m_currentLogFileName.c_str(), F_OK) != 0) || !m_currentLogOutput.is_open()) { CreateLogFile(); } m_currentLogOutput.write(buf, length); @@ -147,6 +147,10 @@ void LogPersisterRotator::CreateLogFile() std::stringstream newFile; newFile << m_logsPath << "." << GetFileNameIndex(m_currentLogFileIdx) << "." << timeBuf << m_fileNameSuffix; std::cout << "Filename: " << newFile.str() << std::endl; + m_currentLogFileName = newFile.str(); + if (m_currentLogOutput.is_open()) { + m_currentLogOutput.close(); + } m_currentLogOutput.open(newFile.str(), std::ios::out | std::ios::trunc); } diff --git a/services/hilogd/main.cpp b/services/hilogd/main.cpp index f20bd52d73a5180a7f828fc5f08c26d0a4413ea5..1dc3814b02aea7d6122be0ad5b5641064d029516 100644 --- a/services/hilogd/main.cpp +++ b/services/hilogd/main.cpp @@ -16,13 +16,11 @@ #include #include #include -#include +#include #include #include #include -#include #include - #include #include #include @@ -34,7 +32,6 @@ #include "service_controller.h" #ifdef DEBUG -#include #include #include #endif @@ -42,12 +39,10 @@ namespace OHOS { namespace HiviewDFX { using namespace std; -using namespace std::chrono; static const string SYSTEM_BG_STUNE = "/dev/stune/system-background/cgroup.procs"; static const string SYSTEM_BG_CPUSET = "/dev/cpuset/system-background/cgroup.procs"; static const string SYSTEM_BG_BLKIO = "/dev/blkio/system-background/cgroup.procs"; -static constexpr int WAITING_DATA_MS = 5000; #ifdef DEBUG static int g_fd = -1; @@ -62,50 +57,9 @@ static void SigHandler(int sig) g_fd = -1; } #endif - std::cout<<"Exited!"< func) -{ - chrono::steady_clock::time_point start = chrono::steady_clock::now(); - chrono::milliseconds wait(max); - while (true) { - if (func(path) != -1) { - cout << "waiting for " << path << " successfully!" << endl; - return 0; - } - - std::this_thread::sleep_for(10ms); - if ((chrono::steady_clock::now() - start) > wait) { - cerr << "waiting for " << path << " failed!" << endl; - return -1; - } } } -static int WaitingDataMounted(const string &path) -{ - struct stat st; - if (stat(path.c_str(), &st) != -1) { - return 0; - } - return -1; -} - -static int WaitingCgroupMounted(const string &path) -{ - int fd; - if (!access(path.c_str(), W_OK)) { - fd = open(path.c_str(), O_WRONLY | O_CLOEXEC); - if (fd >= 0) { - close(fd); - return 0; - } - } - return -1; -} - static bool WriteStringToFile(int fd, const std::string& content) { const char *p = content.data(); @@ -123,7 +77,18 @@ static bool WriteStringToFile(int fd, const std::string& content) static bool WriteStringToFile(const std::string& content, const std::string& filePath) { - if (WaitingToDo(WAITING_DATA_MS, filePath, WaitingCgroupMounted) == -1) { + int ret = WaitingToDo(WAITING_DATA_MS, filePath, [](const string &path) { + int fd; + if (!access(path.c_str(), W_OK)) { + fd = open(path.c_str(), O_WRONLY | O_CLOEXEC); + if (fd >= 0) { + close(fd); + return RET_SUCCESS; + } + } + return RET_FAIL; + }); + if (ret != RET_SUCCESS) { return false; } if (access(filePath.c_str(), W_OK)) { @@ -141,7 +106,14 @@ static bool WriteStringToFile(const std::string& content, const std::string& fil #ifdef DEBUG static void RedirectStdStreamToLogFile() { - if (WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, WaitingDataMounted) == 0) { + int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) { + struct stat s; + if (stat(path.c_str(), &s) != -1) { + return RET_SUCCESS; + } + return RET_FAIL; + }); + if (ret == RET_SUCCESS) { const char *path = HILOG_FILE_DIR"hilogd_debug.txt"; int mask = O_WRONLY | O_APPEND | O_CREAT; struct stat st; @@ -168,17 +140,17 @@ int HilogdEntry() RedirectStdStreamToLogFile(); #endif std::signal(SIGINT, SigHandler); - HilogBuffer hilogBuffer; + HilogBuffer hilogBuffer(true); LogCollector logCollector(hilogBuffer); // Start log_collector #ifndef __RECV_MSG_WITH_UCRED_ - auto onDataReceive = [&logCollector](std::vector& data) { - logCollector.onDataRecv(data); + auto onDataReceive = [&logCollector](std::vector& data, int dataLen) { + logCollector.onDataRecv(data, dataLen); }; #else - auto onDataReceive = [&logCollector](const ucred& cred, std::vector& data) { - logCollector.onDataRecv(cred, data); + auto onDataReceive = [&logCollector](const ucred& cred, std::vector& data, int dataLen) { + logCollector.onDataRecv(cred, data, dataLen); }; #endif @@ -195,21 +167,28 @@ int HilogdEntry() incomingLogsServer.RunServingThread(); } - auto startupCheckTask = std::async(std::launch::async, [&hilogBuffer]() { + HilogBuffer kmsgBuffer(false); + auto startupCheckTask = std::async(std::launch::async, [&hilogBuffer, &kmsgBuffer]() { prctl(PR_SET_NAME, "hilogd.pst_res"); - if (WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, WaitingDataMounted) == 0) { - hilogBuffer.InitBuffLen(); - RestorePersistJobs(hilogBuffer); + int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) { + struct stat s; + if (stat(path.c_str(), &s) != -1) { + return RET_SUCCESS; + } + return RET_FAIL; + }); + if (ret == RET_SUCCESS) { + RestorePersistJobs(hilogBuffer, kmsgBuffer); } }); bool kmsgEnable = IsKmsgSwitchOn(); if (kmsgEnable) { - LogKmsg& logKmsg = LogKmsg::GetInstance(hilogBuffer); + LogKmsg& logKmsg = LogKmsg::GetInstance(kmsgBuffer); logKmsg.Start(); } - auto cgroupWriteTask = std::async(std::launch::async, [&hilogBuffer]() { + auto cgroupWriteTask = std::async(std::launch::async, []() { prctl(PR_SET_NAME, "hilogd.cgroup_set"); string myPid = to_string(getpid()); (void)WriteStringToFile(myPid, SYSTEM_BG_STUNE); @@ -217,7 +196,7 @@ int HilogdEntry() (void)WriteStringToFile(myPid, SYSTEM_BG_BLKIO); }); - auto cmdExecuteTask = std::async(std::launch::async, [&logCollector, &hilogBuffer]() { + auto cmdExecuteTask = std::async(std::launch::async, [&logCollector, &hilogBuffer, &kmsgBuffer]() { prctl(PR_SET_NAME, "hilogd.cmd"); CmdList controlCmdList { IoctlCmd::PERSIST_START_RQST, @@ -231,12 +210,12 @@ int HilogdEntry() IoctlCmd::LOG_REMOVE_RQST, IoctlCmd::KMSG_ENABLE_RQST, }; - CmdExecutor controlExecutor(logCollector, hilogBuffer, controlCmdList, ("hilogd.control")); + CmdExecutor controlExecutor(logCollector, hilogBuffer, kmsgBuffer, controlCmdList, ("hilogd.control")); controlExecutor.MainLoop(CONTROL_SOCKET_NAME); }); CmdList outputList {IoctlCmd::OUTPUT_RQST}; - CmdExecutor outputExecutor(logCollector, hilogBuffer, outputList, ("hilogd.output")); + CmdExecutor outputExecutor(logCollector, hilogBuffer, kmsgBuffer, outputList, ("hilogd.output")); outputExecutor.MainLoop(OUTPUT_SOCKET_NAME); return 0; diff --git a/services/hilogd/service_controller.cpp b/services/hilogd/service_controller.cpp index 9623023abc7c84a29e09a04829cd697d0a5cbb70..3c526a60237c7eac2a84ffaab047e59b2780b512 100644 --- a/services/hilogd/service_controller.cpp +++ b/services/hilogd/service_controller.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -55,19 +56,28 @@ static constexpr uint32_t DEFAULT_PERSIST_KMSG_JOB_ID = 2; static constexpr int INFO_SUFFIX = 5; static const uid_t SHELL_UID = 2000; static const uid_t ROOT_UID = 0; +static const uid_t LOGD_UID = 1036; + +inline bool IsKmsg(uint16_t types) +{ + return types == (0b01 << LOG_KMSG); +} ServiceController::ServiceController(std::unique_ptr communicationSocket, - LogCollector& collector, HilogBuffer& buffer) + LogCollector& collector, HilogBuffer& hilogBuffer, HilogBuffer& kmsgBuffer) : m_communicationSocket(std::move(communicationSocket)) , m_logCollector(collector) - , m_hilogBuffer(buffer) + , m_hilogBuffer(hilogBuffer) + , m_kmsgBuffer(kmsgBuffer) { - m_bufReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); }); + m_hilogBufferReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); }); + m_kmsgBufferReader = m_kmsgBuffer.CreateBufReader([this]() { NotifyForNewData(); }); } ServiceController::~ServiceController() { - m_hilogBuffer.RemoveBufReader(m_bufReader); + m_hilogBuffer.RemoveBufReader(m_hilogBufferReader); + m_kmsgBuffer.RemoveBufReader(m_kmsgBufferReader); m_notifyNewDataCv.notify_all(); } @@ -468,7 +478,7 @@ void ServiceController::LogFilterFromOutputRqst(const OutputRqst& rqst, LogFilte // Permission check uid_t uid = m_communicationSocket->GetUid(); uint32_t pid = static_cast(m_communicationSocket->GetPid()); - if (uid != ROOT_UID && uid != SHELL_UID) { + if (uid != ROOT_UID && uid != SHELL_UID && uid != LOGD_UID) { filter.blackPid = false; filter.pidCount = 1; filter.pids[0] = pid; @@ -494,9 +504,13 @@ void ServiceController::HandleOutputRqst(const OutputRqst &rqst) int tailCount = rqst.tailLines; int linesCountDown = lines; + bool isKmsg = IsKmsg(filter.types); + HilogBuffer& logBuffer = isKmsg ? m_kmsgBuffer : m_hilogBuffer; + HilogBuffer::ReaderId readId = isKmsg ? m_kmsgBufferReader : m_hilogBufferReader; + WriteRspHeader(IoctlCmd::OUTPUT_RSP, sizeof(OutputRsp)); for (;;) { - std::optional data = m_hilogBuffer.Query(filter, m_bufReader, tailCount); + std::optional data = logBuffer.Query(filter, readId, tailCount); if (!data.has_value()) { if (rqst.noBlock) { // reach the end of buffer and don't block @@ -577,7 +591,18 @@ int StartPersistStoreJob(const PersistRecoveryInfo& info, HilogBuffer& hilogBuff void ServiceController::HandlePersistStartRqst(const PersistStartRqst &rqst) { - int ret = CheckPersistStartRqst(rqst); + int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) { + struct stat s; + if (stat(path.c_str(), &s) != -1) { + return RET_SUCCESS; + } + return RET_FAIL; + }); + if (ret != RET_SUCCESS) { + WriteErrorRsp(ERR_LOG_PERSIST_FILE_PATH_INVALID); + return; + } + ret = CheckPersistStartRqst(rqst); if (ret != RET_SUCCESS) { WriteErrorRsp(ret); return; @@ -591,7 +616,8 @@ void ServiceController::HandlePersistStartRqst(const PersistStartRqst &rqst) LogPersistStartMsg msg = { 0 }; PersistStartRqst2Msg(rqst, msg); PersistRecoveryInfo info = {0, msg}; - ret = StartPersistStoreJob(info, m_hilogBuffer, false); + HilogBuffer& logBuffer = IsKmsg(rqst.outputFilter.types) ? m_kmsgBuffer : m_hilogBuffer; + ret = StartPersistStoreJob(info, logBuffer, false); if (ret != RET_SUCCESS) { WriteErrorRsp(ret); return; @@ -661,7 +687,8 @@ void ServiceController::HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst) BufferSizeGetRsp rsp = { 0 }; for (uint16_t t : allTypes) { if ((1 << t) & types) { - rsp.size[t] = static_cast(m_hilogBuffer.GetBuffLen(t)); + HilogBuffer& hilogBuffer = t == LOG_KMSG ? m_kmsgBuffer : m_hilogBuffer; + rsp.size[t] = static_cast(hilogBuffer.GetBuffLen(t)); i++; } } @@ -684,7 +711,8 @@ void ServiceController::HandleBufferSizeSetRqst(const BufferSizeSetRqst& rqst) BufferSizeSetRsp rsp = { 0 }; for (uint16_t t : allTypes) { if ((1 << t) & types) { - int ret = m_hilogBuffer.SetBuffLen(t, rqst.size); + HilogBuffer& hilogBuffer = t == LOG_KMSG ? m_kmsgBuffer : m_hilogBuffer; + int ret = hilogBuffer.SetBuffLen(t, rqst.size); if (ret != RET_SUCCESS) { rsp.size[t] = ret; } else { @@ -754,7 +782,8 @@ void ServiceController::HandleLogRemoveRqst(const LogRemoveRqst& rqst) LogRemoveRsp rsp = { types }; for (uint16_t t : allTypes) { if ((1 << t) & types) { - (void)m_hilogBuffer.Delete(t); + HilogBuffer& hilogBuffer = (t == LOG_KMSG) ? m_kmsgBuffer : m_hilogBuffer; + (void)hilogBuffer.Delete(t); i++; } } @@ -770,7 +799,7 @@ void ServiceController::HandleLogKmsgEnableRqst(const KmsgEnableRqst& rqst) { SetKmsgSwitchOn(rqst.on); - LogKmsg& logKmsg = LogKmsg::GetInstance(m_hilogBuffer); + LogKmsg& logKmsg = LogKmsg::GetInstance(m_kmsgBuffer); if (rqst.on) { logKmsg.Start(); } else { @@ -884,7 +913,7 @@ void ServiceController::NotifyForNewData() m_notifyNewDataCv.notify_one(); } -int RestorePersistJobs(HilogBuffer& hilogBuffer) +int RestorePersistJobs(HilogBuffer& hilogBuffer, HilogBuffer& kmsgBuffer) { std::cout << " Start restoring persist jobs!\n"; DIR *dir = opendir(LOG_PERSISTER_DIR.c_str()); @@ -916,7 +945,8 @@ int RestorePersistJobs(HilogBuffer& hilogBuffer) std::cout << " Info file checksum Failed!\n"; continue; } - int result = StartPersistStoreJob(info, hilogBuffer, true); + HilogBuffer& logBuffer = IsKmsg(info.msg.filter.types) ? kmsgBuffer : hilogBuffer; + int result = StartPersistStoreJob(info, logBuffer, true); std::cout << " Recovery Info:\n" << " restoring result: " << (result == RET_SUCCESS ? std::string("Success\n") diff --git a/services/hilogtool/BUILD.gn b/services/hilogtool/BUILD.gn index 690dce74c8a33c47c42b2ef4ea14bf9a2ac19b58..a4186d813f80cb2ce16aef6662e19f127dc7763d 100644 --- a/services/hilogtool/BUILD.gn +++ b/services/hilogtool/BUILD.gn @@ -31,19 +31,17 @@ ohos_executable("hilog") { ] deps = [ + "../../interfaces/native/innerkits:libhilog", "//third_party/bounds_checking_function:libsec_shared", - "//third_party/zlib:libz", + "//third_party/zlib:shared_libz", ] - external_deps = [ - "c_utils:utils", - "hilog_native:libhilog", - ] + external_deps = [ "c_utils:utils" ] install_images = [ "system", "updater", ] install_enable = true - part_name = "hilog_service" + part_name = "hilog" subsystem_name = "hiviewdfx" } diff --git a/services/hilogtool/main.cpp b/services/hilogtool/main.cpp index bcbbb93271474ea209576f11263e0d8ce5a342f3..7f07aea4ebf076caca7fad6f855f041df0cbdbe8 100644 --- a/services/hilogtool/main.cpp +++ b/services/hilogtool/main.cpp @@ -217,10 +217,10 @@ static void DomainHelper() cout << endl << endl << "Domain description:" << endl - << " Log type \"core\" & \"init\" are used for OS subsystems, the range is (0x" << hex << DOMAIN_OS_MIN << "," - << " 0x" << DOMAIN_OS_MAX << ")" << endl - << " Log type \"app\" is used for applications, the range is (0x" << DOMAIN_APP_MIN << "," - << " 0x" << DOMAIN_APP_MAX << ")" << dec << endl + << " Log type \"core\" & \"init\" are used for OS subsystems, the range is [0x" << hex << DOMAIN_OS_MIN << "," + << " 0x" << DOMAIN_OS_MAX << "]" << endl + << " Log type \"app\" is used for applications, the range is [0x" << DOMAIN_APP_MIN << "," + << " 0x" << DOMAIN_APP_MAX << "]" << dec << endl << " To reduce redundant info when printing logs, only last five hex numbers of domain are printed" << endl << " So if user wants to use -D option to filter OS logs, user should add 0xD0 as prefix to the printed domain:" << endl diff --git a/test/BUILD.gn b/test/BUILD.gn index 426db23fea4cff32b3fddded26abd011367932bf..df1d9aa1a98de3ffe979544d31245bd66a5bd7a1 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") -module_output_path = "hiviewdfx/hilog" +module_output_path = "hilog/hilog" config("module_private_config") { visibility = [ ":*" ] @@ -32,8 +32,8 @@ ohos_moduletest("HiLogNDKTest") { deps = [ "//third_party/googletest:gtest_main" ] external_deps = [ - "hilog_native:libhilog", - "hilog_native:libhilog_base", + "hilog:libhilog", + "hilog:libhilog_base", "init:libbegetutil", ] @@ -52,7 +52,7 @@ ohos_moduletest("HiLogAdapterTest") { deps = [ "//third_party/googletest:gtest_main" ] - external_deps = [ "hilog_native:libhilog" ] + external_deps = [ "hilog:libhilog" ] include_dirs = [ "//base/hiviewdfx/hilog/adapter", @@ -60,3 +60,26 @@ ohos_moduletest("HiLogAdapterTest") { "//base/hiviewdfx/hilog/frameworks/libhilog/utils/include/", ] } + +group("hilog_moduletest") { + testonly = true + deps = [ + ":HiLogAdapterTest", + ":HiLogNDKTest", + ] +} + +group("hilog_unittest") { + testonly = true + deps = [] + + deps += [ "unittest/common:unittest" ] +} + +group("fuzztest") { + testonly = true + deps = [ + "fuzztest/hilogclient_fuzzer:HiLogClientFuzzTest", + "fuzztest/hilogserver_fuzzer:HiLogServerFuzzTest", + ] +} diff --git a/test/fuzztest/hilogclient_fuzzer/BUILD.gn b/test/fuzztest/hilogclient_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2a9e3f687feeb0686e712118f0f296bf8778663f --- /dev/null +++ b/test/fuzztest/hilogclient_fuzzer/BUILD.gn @@ -0,0 +1,38 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/features.gni") +import("//build/test.gni") +module_output_path = "hilog/hilog" + +ohos_fuzztest("HiLogClientFuzzTest") { + module_out_path = module_output_path + + fuzz_config_file = "../hilogclient_fuzzer" + + include_dirs = [ "../../../interfaces/native/innerkits/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "hilogclient_fuzzer.cpp" ] + configs = [ "../../../frameworks/libhilog:libhilog_config" ] + deps = [ "../../../interfaces/native/innerkits:libhilog" ] + external_deps = [ "init:libbegetutil" ] + part_name = "hilog" + subsystem_name = "hiviewdfx" +} diff --git a/test/fuzztest/hilogclient_fuzzer/corpus/init b/test/fuzztest/hilogclient_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..184a6a356388013e15878c37ab1b2c309042c736 --- /dev/null +++ b/test/fuzztest/hilogclient_fuzzer/corpus/init @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +FUZZ diff --git a/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.cpp b/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56f88960e86bd3b3d43d57a20f3cef0a91f4d36b --- /dev/null +++ b/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.cpp @@ -0,0 +1,63 @@ +/* + +Copyright (c) 2021 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include "hilogclient_fuzzer.h" + +#include +#include +#include +#include +#include +#include +#include "hilog/log.h" +#include "hilog_common.h" +#include "hilog_input_socket_client.h" + +namespace OHOS { + static const char FUZZ_TEST[] = "fuzz test"; + static const uint32_t FUZZ_DOMAIN = 0xD002D01; + bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) + { + HilogMsg header = {0}; + struct timespec ts = {0}; + (void)clock_gettime(CLOCK_REALTIME, &ts); + struct timespec tsMono = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &tsMono); + header.tv_sec = static_cast(ts.tv_sec); + header.tv_nsec = static_cast(ts.tv_nsec); + header.mono_sec = static_cast(tsMono.tv_sec); + header.pid = getpid(); + header.tid = static_cast(syscall(SYS_gettid)); + header.type = LOG_CORE; + header.level = LOG_INFO; + header.domain = FUZZ_DOMAIN; + int ret = HilogWriteLogMessage(&header, FUZZ_TEST, + strlen(FUZZ_TEST) + 1, reinterpret_cast(data), size); + if (ret < 0) { + return false; + } + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (data == nullptr || size == 0) { + std::cout << "invalid data" << std::endl; + return 0; + } + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.h b/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..964e886b60857aea529ae049bde1d4bb291f1b4a --- /dev/null +++ b/test/fuzztest/hilogclient_fuzzer/hilogclient_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FAULTLOGGER_CLIENT_FUZZER_H +#define FAULTLOGGER_CLIENT_FUZZER_H + +#define FUZZ_PROJECT_NAME "hilogclient_fuzzer" + +#endif diff --git a/test/fuzztest/hilogclient_fuzzer/project.xml b/test/fuzztest/hilogclient_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..1134e635235da2a4688db9a207b4608617dc23da --- /dev/null +++ b/test/fuzztest/hilogclient_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/test/fuzztest/hilogserver_fuzzer/BUILD.gn b/test/fuzztest/hilogserver_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9bd73e40542aad7489d62af2fffb7acc99a07c6d --- /dev/null +++ b/test/fuzztest/hilogserver_fuzzer/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/features.gni") +import("//build/test.gni") +module_output_path = "hilog/hilog" + +ohos_fuzztest("HiLogServerFuzzTest") { + module_out_path = module_output_path + + fuzz_config_file = "../hilogserver_fuzzer" + + include_dirs = [ + "../../../services/hilogd/include", + "../../../interfaces/native/innerkits/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "../../../services/hilogd/flow_control.cpp", + "../../../services/hilogd/log_buffer.cpp", + "../../../services/hilogd/log_collector.cpp", + "../../../services/hilogd/log_domains.cpp", + "../../../services/hilogd/log_stats.cpp", + "hilogserver_fuzzer.cpp", + ] + configs = [ "../../../frameworks/libhilog:libhilog_config" ] + deps = [ + "../../../interfaces/native/innerkits:libhilog", + "//third_party/bounds_checking_function:libsec_shared", + "//third_party/zlib:shared_libz", + ] + external_deps = [ "init:libbegetutil" ] + part_name = "hilog" + subsystem_name = "hiviewdfx" +} diff --git a/test/fuzztest/hilogserver_fuzzer/corpus/init b/test/fuzztest/hilogserver_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..184a6a356388013e15878c37ab1b2c309042c736 --- /dev/null +++ b/test/fuzztest/hilogserver_fuzzer/corpus/init @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +FUZZ diff --git a/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.cpp b/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f4c49f186b5b65ec24b204de79e24bda85c36c1 --- /dev/null +++ b/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.cpp @@ -0,0 +1,45 @@ +/* +Copyright (c) 2021 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include "hilogserver_fuzzer.h" + +#include +#include +#include +#include +#include +#include +#include "hilog/log.h" +#include "hilog_common.h" +#include "log_collector.h" + +namespace OHOS { + void DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) + { + HiviewDFX::HilogBuffer hilogBuffer(true); + HiviewDFX::LogCollector logCollector(hilogBuffer); + std::vector fuzzerData(reinterpret_cast(data), reinterpret_cast(data) + size); + logCollector.onDataRecv(fuzzerData, size); + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (data == nullptr || size == 0) { + std::cout << "invalid data" << std::endl; + return 0; + } + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.h b/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..cf7aec3dc91b294833a9027762c316127ea372b4 --- /dev/null +++ b/test/fuzztest/hilogserver_fuzzer/hilogserver_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FAULTLOGGER_CLIENT_FUZZER_H +#define FAULTLOGGER_CLIENT_FUZZER_H + +#define FUZZ_PROJECT_NAME "hilogserver_fuzzer" + +#endif diff --git a/test/fuzztest/hilogserver_fuzzer/project.xml b/test/fuzztest/hilogserver_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..1134e635235da2a4688db9a207b4608617dc23da --- /dev/null +++ b/test/fuzztest/hilogserver_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/test/moduletest/common/adapter_test.cpp b/test/moduletest/common/adapter_test.cpp index 9658d355ad1b143c8504e8a1012f15a1192e7c26..c0e32693348ba0847f69412fd7ce1d9b3544af1d 100644 --- a/test/moduletest/common/adapter_test.cpp +++ b/test/moduletest/common/adapter_test.cpp @@ -28,6 +28,7 @@ using namespace std::chrono_literals; using namespace OHOS::HiviewDFX; namespace { +constexpr uint32_t QUERY_INTERVAL = 100000; // sleep 0.1s class PropertiesTest : public testing::Test { public: static void SetUpTestCase() {} @@ -45,6 +46,7 @@ HWTEST_F(PropertiesTest, SwitchTest, TestSize.Level1) SetKmsgSwitchOn(true); SetPersistDebugOn(true); + usleep(QUERY_INTERVAL); EXPECT_TRUE(IsDebugOn()); EXPECT_TRUE(IsOnceDebugOn()); EXPECT_TRUE(IsPersistDebugOn()); @@ -60,6 +62,7 @@ HWTEST_F(PropertiesTest, SwitchTest, TestSize.Level1) SetKmsgSwitchOn(false); SetPersistDebugOn(false); + usleep(QUERY_INTERVAL); EXPECT_FALSE(IsDebugOn()); EXPECT_FALSE(IsOnceDebugOn()); EXPECT_FALSE(IsPersistDebugOn()); @@ -70,10 +73,12 @@ HWTEST_F(PropertiesTest, SwitchTest, TestSize.Level1) SetOnceDebugOn(true); SetPersistDebugOn(false); + usleep(QUERY_INTERVAL); EXPECT_TRUE(IsDebugOn()); SetOnceDebugOn(false); SetPersistDebugOn(true); + usleep(QUERY_INTERVAL); EXPECT_TRUE(IsDebugOn()); } @@ -90,19 +95,34 @@ HWTEST_F(PropertiesTest, LevelTest, TestSize.Level1) for (size_t i = 0; i < charLevels.size(); ++i) { SetGlobalLevel(ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); EXPECT_EQ(GetGlobalLevel(), expected[i]); } uint32_t domain = 12345; for (size_t i = 0; i < charLevels.size(); ++i) { SetDomainLevel(domain, ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); EXPECT_EQ(GetDomainLevel(domain), expected[i]); } std::string tag = "test_tag"; for (size_t i = 0; i < charLevels.size(); ++i) { SetTagLevel(tag, ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); EXPECT_EQ(GetTagLevel(tag), expected[i]); } } + +HWTEST_F(PropertiesTest, BufferTest, TestSize.Level1) +{ + static const std::array logType = {-1, 0, 1, 3, 4, 5, 100}; + static const size_t size = 512 * 1024; + static const std::array expectedSize = {0, size, size, size, size, size, 0}; + + for (size_t i = 0; i < logType.size(); ++i) { + SetBufferSize(logType[i], false, size); + EXPECT_EQ(GetBufferSize(logType[i], false), expectedSize[i]); + } +} } // namespace diff --git a/test/moduletest/common/hilog_base_ndk_test.cpp b/test/moduletest/common/hilog_base_ndk_test.cpp index 4fe2dea20cd45f635f49ad768c8e7c4bde403922..e8b2af21d2de2715f82a6f4abf47f6ddde8fb3d2 100644 --- a/test/moduletest/common/hilog_base_ndk_test.cpp +++ b/test/moduletest/common/hilog_base_ndk_test.cpp @@ -94,12 +94,18 @@ static std::string PopenToString(const std::string &command) class HiLogBaseNDKTest : public testing::Test { public: - static void SetUpTestCase() {} + static void SetUpTestCase(); static void TearDownTestCase() {} void SetUp(); void TearDown() {} }; +void HiLogBaseNDKTest::SetUpTestCase() +{ + (void)PopenToString("hilog -Q pidoff"); + (void)PopenToString("hilog -Q domainoff"); +} + void HiLogBaseNDKTest::SetUp() { (void)PopenToString("hilog -r"); @@ -222,6 +228,7 @@ HWTEST_F(HiLogBaseNDKTest, IsLoggable, TestSize.Level1) EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_ERROR)); EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_FATAL)); EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_WARN)); + EXPECT_FALSE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_LEVEL_MIN)); } } // namespace HiLogTest diff --git a/test/moduletest/common/hilog_ndk_test.cpp b/test/moduletest/common/hilog_ndk_test.cpp index 56e781f4d0aa7225ff1d2fbaa303d476d0933765..e4c0cabebf727ffb7c4308efba121c5fd9393dc8 100644 --- a/test/moduletest/common/hilog_ndk_test.cpp +++ b/test/moduletest/common/hilog_ndk_test.cpp @@ -38,10 +38,12 @@ using namespace testing::ext; namespace OHOS { namespace HiviewDFX { namespace HiLogTest { +const HiLogLabel APP_LABEL = { LOG_APP, 0x002a, "HILOGTEST_CPP" }; const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "HILOGTEST_CPP" }; const HiLogLabel ILLEGAL_DOMAIN_LABEL = { LOG_CORE, 0xD00EEEE, "HILOGTEST_CPP" }; static constexpr unsigned int SOME_LOGS = 10; static constexpr unsigned int MORE_LOGS = 100; +static constexpr unsigned int OVER_LOGS = 1000; enum LogInterfaceType { DEBUG_METHOD = 0, @@ -110,12 +112,18 @@ static std::string PopenToString(const std::string &command) class HiLogNDKTest : public testing::Test { public: - static void SetUpTestCase() {} + static void SetUpTestCase(); static void TearDownTestCase() {} void SetUp(); void TearDown() {} }; +void HiLogNDKTest::SetUpTestCase() +{ + (void)PopenToString("hilog -Q pidoff"); + (void)PopenToString("hilog -Q domainoff"); +} + void HiLogNDKTest::SetUp() { (void)PopenToString("hilog -r"); @@ -158,6 +166,18 @@ static void HiLogWriteTest(LogInterfaceType methodType, unsigned int count, EXPECT_GE(realCount, allowedLeastLogCount); } +static void FlowCtlTest(const HiLogLabel &label, const std::string keyWord) +{ + const std::string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + for (unsigned int i = 0; i < OVER_LOGS; ++i) { + HiLog::Info(label, "%{public}s:%{public}d", str.c_str(), i); + } + sleep(1); /* 1: sleep 1 s */ + HiLog::Info(label, "%{public}s", str.c_str()); + std::string logMsgs = PopenToString("hilog -x -T LOGLIMIT"); + EXPECT_TRUE(logMsgs.find(keyWord) != std::string::npos); +} + /** * @tc.name: Dfx_HiLogNDKTest_PrintDebugLog_001 * @tc.desc: Call HILOG_DEBUG to print logs. @@ -357,6 +377,8 @@ HWTEST_F(HiLogNDKTest, IsLoggable_001, TestSize.Level1) */ HWTEST_F(HiLogNDKTest, DomainCheck_001, TestSize.Level1) { + (void)PopenToString("param set hilog.debug.on false"); + (void)PopenToString("param set persist.sys.hilog.debug.on false"); std::string logMsg(RandomStringGenerator()); for (unsigned int i = 0; i < SOME_LOGS; ++i) { HiLog::Info(ILLEGAL_DOMAIN_LABEL, "%{public}s", logMsg.c_str()); @@ -375,22 +397,6 @@ HWTEST_F(HiLogNDKTest, DomainCheck_001, TestSize.Level1) EXPECT_EQ(realCount, 0); } -/** - * @tc.name: Dfx_HiLogNDKTest_hilogStatisticsTest - * @tc.desc: test hilog statistics function - * @tc.type: FUNC - * @tc.require:issueI5NU71 - */ -HWTEST_F(HiLogNDKTest, hilogStatisticsTest, TestSize.Level1) -{ - std::string logStatsLog = "Statistic info query failed"; - std::string logMsgs = PopenToString("/system/bin/hilog -s"); - std::stringstream ss(logMsgs); - std::string str; - getline(ss, str); - EXPECT_TRUE(str.find(logStatsLog) != std::string::npos); -} - /** * @tc.name: Dfx_HiLogNDKTest_hilogSocketTest * @tc.desc: Query hilog socket rights @@ -406,6 +412,32 @@ HWTEST_F(HiLogNDKTest, hilogSocketTest, TestSize.Level1) getline(ss, str); EXPECT_TRUE(str.find(hilogControlRights) != std::string::npos); } + +/** + * @tc.name: Dfx_HiLogNDKTest_pidFlowCtrlTest + * @tc.desc: hilog pidFlowCtrlTest + * @tc.type: FUNC + */ +HWTEST_F(HiLogNDKTest, pidFlowCtrlTest, TestSize.Level1) +{ + (void)PopenToString("hilog -Q pidon"); + const std::string pidCtrlLog = "DROPPED"; + FlowCtlTest(APP_LABEL, pidCtrlLog); + (void)PopenToString("hilog -Q pidoff"); +} + +/** + * @tc.name: Dfx_HiLogNDKTest_domainFlowCtrlTest + * @tc.desc: hilog domainFlowCtrlTest + * @tc.type: FUNC + */ +HWTEST_F(HiLogNDKTest, domainFlowCtrlTest, TestSize.Level1) +{ + (void)PopenToString("hilog -Q domainon"); + const std::string domainCtrlLog = "dropped"; + FlowCtlTest(LABEL, domainCtrlLog); + (void)PopenToString("hilog -Q domainoff"); +} } // namespace HiLogTest } // namespace HiviewDFX } // namespace OHOS diff --git a/test/unittest/common/BUILD.gn b/test/unittest/common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d00aa1e38acb21984a2cb780ca4724c904fa7ea0 --- /dev/null +++ b/test/unittest/common/BUILD.gn @@ -0,0 +1,83 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "hilog/hilog" + +config("module_private_config") { + visibility = [ ":*" ] +} + +ohos_unittest("HilogToolTest") { + module_out_path = module_output_path + + sources = [ "hilogtool_test.cpp" ] + + configs = [ + ":module_private_config", + "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_config", + ] + + deps = [ "//third_party/googletest:gtest_main" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] +} + +ohos_unittest("HilogUtilsTest") { + module_out_path = module_output_path + + sources = [ "hilog_utils_test.cpp" ] + + configs = [ + ":module_private_config", + "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_config", + ] + + deps = [ "//third_party/googletest:gtest_main" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] +} + +ohos_unittest("HilogPrintTest") { + module_out_path = module_output_path + + sources = [ "hilog_print_test.cpp" ] + + configs = [ + ":module_private_config", + "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_config", + ] + + deps = [ "//third_party/googletest:gtest_main" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] +} + +group("unittest") { + testonly = true + deps = [ + ":HilogPrintTest", + ":HilogToolTest", + ":HilogUtilsTest", + ] +} diff --git a/test/unittest/common/hilog_print_test.cpp b/test/unittest/common/hilog_print_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..542b322bdc1ea367c64783f124c6b5cdfc5b5b1a --- /dev/null +++ b/test/unittest/common/hilog_print_test.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hilog_print_test.h" +#include "hilog/log.h" +#include + +using namespace std; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HiviewDFX; + +namespace { +const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "HILOGTEST_C" }; +const int LOGINDEX = 42 + strlen("HILOGTEST_C"); + +std::string GetCmdResultFromPopen(const std::string& cmd) +{ + if (cmd.empty()) { + return ""; + } + FILE* fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return ""; + } + std::string ret = ""; + char* buffer = nullptr; + size_t len = 0; + while (getline(&buffer, &len, fp) != -1) { + std::string line = buffer; + ret += line; + } + if (buffer != nullptr) { + free(buffer); + buffer = nullptr; + } + pclose(fp); + return ret; +} +} + +void HilogPrintTest::SetUpTestCase() +{ + (void)GetCmdResultFromPopen("hilog -b X"); + (void)GetCmdResultFromPopen("hilog -b I -D d002d00"); +} + +void HilogPrintTest::TearDownTestCase() +{ + (void)GetCmdResultFromPopen("hilog -b I"); +} + +void HilogPrintTest::SetUp() +{ + (void)GetCmdResultFromPopen("hilog -r"); +} + +namespace { +/** + * @tc.name: Dfx_HilogPrintTest_HilogTypeTest + * @tc.desc: HilogTypeTest. + * @tc.type: FUNC + */ +HWTEST_F(HilogPrintTest, HilogTypeTest, TestSize.Level1) +{ +const vector typeVec = { + {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'+-/,.-~:;<=>?_[]{}|\\\""}, + {"123"}, + {"173"}, + {"123"}, + {"0x7b, 0x7B"}, + {"0.000123, 0.000123"}, + {"1.230000e-04, 1.230000E-04"}, + {"0.000123, 0.123"}, + {"0.000123, 0.123"}, + {"A"}, +}; + + GTEST_LOG_(INFO) << "HilogTypeTest: start."; + HiLog::Info(LABEL, "%{public}s", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'+-/,.-~:;<=>?_[]{}|\\\""); + HiLog::Info(LABEL, "%{public}i", 123); + HiLog::Info(LABEL, "%{public}o", 123); + HiLog::Info(LABEL, "%{public}u", 123); + HiLog::Info(LABEL, "0x%{public}x, 0x%{public}X", 123, 123); + HiLog::Info(LABEL, "%{public}.6f, %{public}.6lf", 0.000123, 0.000123); + HiLog::Info(LABEL, "%{public}e, %{public}E", 0.000123, 0.000123); + HiLog::Info(LABEL, "%{public}g, %{public}g", 0.000123, 0.123); + HiLog::Info(LABEL, "%{public}G, %{public}G", 0.000123, 0.123); + HiLog::Info(LABEL, "%{public}c", 65); + + std::string res = GetCmdResultFromPopen("hilog -T HILOGTEST_C -x"); + vector vec; + std::string log = ""; + Split(res, vec, "\n"); + for (unsigned int i = 0; i < vec.size(); i++) { + log = vec[i].substr(LOGINDEX); + EXPECT_EQ(log, typeVec[i]); + } +} + +/** + * @tc.name: Dfx_HilogPrintTest_HilogFlagTest + * @tc.desc: HilogFlagTest. + * @tc.type: FUNC + */ +HWTEST_F(HilogPrintTest, HilogFlagTest, TestSize.Level1) +{ +const vector FlagVec = { + {" 1000"}, + {"1000 "}, + {"+1000, -1000"}, + {" 1000, -1000"}, + {"3e8, 0x3e8"}, + {"1000, 1000."}, + {"1000, 1000.00"}, + {"01000"}, +}; + + GTEST_LOG_(INFO) << "HilogFlagTest: start."; + HiLog::Info(LABEL, "%{public}5d", 1000); + HiLog::Info(LABEL, "%{public}-5d", 1000); + HiLog::Info(LABEL, "%{public}+d, %{public}+d", 1000, -1000); + HiLog::Info(LABEL, "%{public} d, %{public} d", 1000, -1000); + HiLog::Info(LABEL, "%{public}x, %{public}#x", 1000, 1000); + HiLog::Info(LABEL, "%{public}.0f, %{public}#.0f", 1000.0, 1000.0); + HiLog::Info(LABEL, "%{public}g, %{public}#g", 1000.0, 1000.0); + HiLog::Info(LABEL, "%{public}05d", 1000); + + std::string res = GetCmdResultFromPopen("hilog -T HILOGTEST_C -x"); + vector vec; + std::string log = ""; + Split(res, vec, "\n"); + for (unsigned int i = 0; i < vec.size(); i++) { + log = vec[i].substr(LOGINDEX); + EXPECT_EQ(log, FlagVec[i]); + } +} + +/** + * @tc.name: Dfx_HilogPrintTest_HilogWidthTest + * @tc.desc: HilogWidthTest. + * @tc.type: FUNC + */ +HWTEST_F(HilogPrintTest, HilogWidthTest, TestSize.Level1) +{ +const vector WidthVec = { + {"001000"}, + {"001000"}, +}; + + GTEST_LOG_(INFO) << "HilogWidthTest: start."; + HiLog::Info(LABEL, "%{public}06d", 1000); + HiLog::Info(LABEL, "%{public}0*d", 6, 1000); + + std::string res = GetCmdResultFromPopen("hilog -T HILOGTEST_C -x"); + vector vec; + std::string log = ""; + Split(res, vec, "\n"); + for (unsigned int i = 0; i < vec.size(); i++) { + log = vec[i].substr(LOGINDEX); + EXPECT_EQ(log, WidthVec[i]); + } +} + +/** + * @tc.name: Dfx_HilogPrintTest_HilogPrecisionTest + * @tc.desc: HilogPrecisionTest. + * @tc.type: FUNC + */ +HWTEST_F(HilogPrintTest, HilogPrecisionTest, TestSize.Level1) +{ +const vector PrecisionVec = { + {"00001000"}, + {"1000.12345679"}, + {"1000.12345600"}, + {"1000.1235"}, + {"abcdefgh"}, +}; + + GTEST_LOG_(INFO) << "HilogPrecisionTest: start."; + HiLog::Info(LABEL, "%{public}.8d", 1000); + HiLog::Info(LABEL, "%{public}.8f", 1000.123456789); + HiLog::Info(LABEL, "%{public}.8f", 1000.123456); + HiLog::Info(LABEL, "%{public}.8g", 1000.123456); + HiLog::Info(LABEL, "%{public}.8s", "abcdefghij"); + + std::string res = GetCmdResultFromPopen("hilog -T HILOGTEST_C -x"); + vector vec; + std::string log = ""; + Split(res, vec, "\n"); + for (unsigned int i = 0; i < vec.size(); i++) { + log = vec[i].substr(LOGINDEX); + EXPECT_EQ(log, PrecisionVec[i]); + } +} +} // namespace \ No newline at end of file diff --git a/test/unittest/common/hilog_print_test.h b/test/unittest/common/hilog_print_test.h new file mode 100644 index 0000000000000000000000000000000000000000..137c5873e0290e017b61171ed9beae293d0322d6 --- /dev/null +++ b/test/unittest/common/hilog_print_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HILOGPRINT_TEST_H +#define HILOGPRINT_TEST_H + +#include + +namespace OHOS { +namespace HiviewDFX { +class HilogPrintTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown() {} +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // HILOGPRINT_TEST_H diff --git a/test/unittest/common/hilog_utils_test.cpp b/test/unittest/common/hilog_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c64fa03f01c7cd22210ece21882f2d5951d274be --- /dev/null +++ b/test/unittest/common/hilog_utils_test.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hilog_utils_test.h" +#include "hilog_common.h" +#include +#include +#include + +using namespace std; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HiviewDFX; + +static std::string GetCmdResultFromPopen(const std::string& cmd) +{ + if (cmd.empty()) { + return ""; + } + FILE* fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return ""; + } + std::string ret = ""; + char* buffer = nullptr; + size_t len = 0; + while (getline(&buffer, &len, fp) != -1) { + std::string line = buffer; + ret += line; + } + if (buffer != nullptr) { + free(buffer); + buffer = nullptr; + } + pclose(fp); + return ret; +} + +namespace { +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_001 + * @tc.desc: Size2Str & Str2Size. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_001: start."; + const std::list> sizeStrList = { + /* size, unit */ + {1, "B"}, + {1ULL << 10, "K"}, + {1ULL << 20, "M"}, + {1ULL << 30, "G"}, + {1ULL << 40, "T"}, + }; + for (auto &it : sizeStrList) { + EXPECT_EQ(Size2Str(it.first), "1.0" + it.second); + EXPECT_EQ(Str2Size("1" + it.second), it.first); + } + + // valid str reg [0-9]+[BKMGT]? + EXPECT_EQ(Str2Size("1.2A"), 0); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_002 + * @tc.desc: LogType2Str & Str2LogType. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_002: start."; + const std::list> logTypesList = { + {LOG_INIT, "init"}, + {LOG_CORE, "core"}, + {LOG_APP, "app"}, + {LOG_KMSG, "kmsg"}, + {LOG_TYPE_MAX, "invalid"}, + }; + for (auto &it : logTypesList) { + EXPECT_EQ(LogType2Str(it.first), it.second); + EXPECT_EQ(Str2LogType(it.second), it.first); + } +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_003 + * @tc.desc: ComboLogType2Str & Str2ComboLogType. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_003: start."; + const std::list> logTypesList = { + /* ComboLogType, str */ + {1 << LOG_APP, "app"}, + {1 << LOG_INIT, "init"}, + {1 << LOG_CORE, "core"}, + {1 << LOG_KMSG, "kmsg"}, + {(1 << LOG_APP) + (1 << LOG_INIT) + (1 << LOG_CORE) + (1 << LOG_KMSG), "init,core,app,kmsg"}, + }; + for (auto &it : logTypesList) { + EXPECT_EQ(ComboLogType2Str(it.first), it.second); + EXPECT_EQ(Str2ComboLogType(it.second), it.first); + } + + EXPECT_EQ(Str2ComboLogType(""), (1 << LOG_APP) + (1 << LOG_CORE)); + EXPECT_EQ(Str2ComboLogType("invalid"), 0); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_004 + * @tc.desc: LogLevel2Str & Str2LogLevel. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_004: start."; + struct LogLevelEntry { + const LogLevel logLevel; + const std::string str; + const std::string shortStr; + const int comboLogLevel; + }; + + LogLevelEntry logLevelEntries[] = { + {LOG_LEVEL_MIN, "INVALID", "V", 0}, + {LOG_DEBUG, "DEBUG", "D", 1 << LOG_DEBUG}, + {LOG_INFO, "INFO", "I", 1 << LOG_INFO}, + {LOG_WARN, "WARN", "W", 1 << LOG_WARN}, + {LOG_ERROR, "ERROR", "E", 1 << LOG_ERROR}, + {LOG_FATAL, "FATAL", "F", 1 << LOG_FATAL, }, + {LOG_LEVEL_MAX, "X", "X", 0}, + }; + + constexpr int logLevelEntryCnt = sizeof(logLevelEntries) / sizeof(LogLevelEntry); + + for (int i = 0; i < logLevelEntryCnt; i++) { + EXPECT_EQ(LogLevel2Str(logLevelEntries[i].logLevel), logLevelEntries[i].str); + EXPECT_EQ(Str2LogLevel(logLevelEntries[i].str), logLevelEntries[i].logLevel); + EXPECT_EQ(LogLevel2ShortStr(logLevelEntries[i].logLevel), logLevelEntries[i].shortStr); + EXPECT_EQ(ShortStr2LogLevel(logLevelEntries[i].shortStr), logLevelEntries[i].logLevel); + if (logLevelEntries[i].comboLogLevel != 0) { + EXPECT_EQ(ComboLogLevel2Str(logLevelEntries[i].comboLogLevel), logLevelEntries[i].str); + } + EXPECT_EQ(Str2ComboLogLevel(logLevelEntries[i].str), logLevelEntries[i].comboLogLevel); + } + + EXPECT_EQ(Str2ComboLogLevel(""), 0xFFFF); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_005 + * @tc.desc: GetBitsCount & GetBitPos. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HelperTest_005: start."; + uint64_t num1 = 1 << 4; + uint64_t num2 = (1 << 2) + (1 << 3) + (1 << 4); + EXPECT_EQ(GetBitPos(num1), 4); + // only accpet the number which is power of 2 + EXPECT_EQ(GetBitPos(num2), 0); + EXPECT_EQ(GetBitsCount(num2), 3); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_006 + * @tc.desc: Uint2DecStr DecStr2Uint Uint2HexStr & HexStr2Uint. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_006: start."; + uint32_t decNum = 1250; + uint32_t hexNum = 0xd002d00; + std::string decStr = "1250"; + std::string hexStr = "d002d00"; + EXPECT_EQ(Uint2DecStr(decNum), decStr); + EXPECT_EQ(DecStr2Uint(decStr), decNum); + EXPECT_EQ(Uint2HexStr(hexNum), hexStr); + EXPECT_EQ(HexStr2Uint(hexStr), hexNum); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_007 + * @tc.desc: GetAllLogTypes. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_007, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_007: start."; + vector vec = GetAllLogTypes(); + sort(vec.begin(), vec.end()); + vector allTypes {0, 1, 3, 4}; + EXPECT_TRUE(vec == allTypes); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_008 + * @tc.desc: GetPPidByPid. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_008, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_008: start."; + uint32_t pid = stoi(GetCmdResultFromPopen("pidof hilogd")); + EXPECT_EQ(GetPPidByPid(pid), 1); + + uint32_t invalidPid = 999999; + EXPECT_EQ(GetPPidByPid(invalidPid), 0); +} + +/** + * @tc.name: Dfx_HilogUtilsTest_HilogUtilsTest_009 + * @tc.desc: WaitingToDo. + * @tc.type: FUNC + */ +HWTEST_F(HilogUtilsTest, HilogUtilsTest_009, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HilogUtilsTest_009: start."; + int ret = WaitingToDo(WAITING_DATA_MS, "/data/log", [](const string &path) { + if (!access(path.c_str(), F_OK)) { + return RET_SUCCESS; + } + return RET_FAIL; + }); + EXPECT_EQ(ret, RET_SUCCESS); + + ret = WaitingToDo(WAITING_DATA_MS, "/test/ttt", [](const string &path) { + if (!access(path.c_str(), F_OK)) { + return RET_SUCCESS; + } + return RET_FAIL; + }); + PrintErrorno(errno); + EXPECT_EQ(ret, RET_FAIL); +} +} // namespace diff --git a/test/unittest/common/hilog_utils_test.h b/test/unittest/common/hilog_utils_test.h new file mode 100644 index 0000000000000000000000000000000000000000..4e6f5ee178c2e82998f63aab973778a4174dc886 --- /dev/null +++ b/test/unittest/common/hilog_utils_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HILOGUTILS_TEST_H +#define HILOGUTILS_TEST_H + +#include + +namespace OHOS { +namespace HiviewDFX { +class HilogUtilsTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {}; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // HILOGUTILS_TEST_H diff --git a/test/unittest/common/hilogtool_test.cpp b/test/unittest/common/hilogtool_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92b37b015a46bb99ed439623c04bde583f9a0b52 --- /dev/null +++ b/test/unittest/common/hilogtool_test.cpp @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hilogtool_test.h" +#include "hilog/log_c.h" +#include +#include +#include +#include +#include + +using namespace std; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HiviewDFX; + +static int GetCmdLinesFromPopen(const std::string& cmd) +{ + if (cmd.empty()) { + return 0; + } + FILE* fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return 0; + } + int ret = 0; + char* buffer = nullptr; + size_t len = 0; + while (getline(&buffer, &len, fp) != -1) { + ret++; + } + if (buffer != nullptr) { + free(buffer); + buffer = nullptr; + } + pclose(fp); + return ret; +} + +static std::string GetCmdResultFromPopen(const std::string& cmd) +{ + if (cmd.empty()) { + return ""; + } + FILE* fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return ""; + } + std::string ret = ""; + char* buffer = nullptr; + size_t len = 0; + while (getline(&buffer, &len, fp) != -1) { + std::string line = buffer; + ret += line; + } + if (buffer != nullptr) { + free(buffer); + buffer = nullptr; + } + pclose(fp); + return ret; +} + +static bool IsExistInCmdResult(const std::string &cmd, const std::string &str) +{ + if (cmd.empty()) { + return false; + } + FILE* fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return false; + } + bool ret = false; + char* buffer = nullptr; + size_t len = 0; + while (getline(&buffer, &len, fp) != -1) { + std::string line = buffer; + if (line.find(str) != string::npos) { + ret = true; + break; + } + } + if (buffer != nullptr) { + free(buffer); + buffer = nullptr; + } + pclose(fp); + return ret; +} + +void HilogToolTest::TearDownTestCase() +{ + (void)GetCmdResultFromPopen("hilog -b I"); + (void)GetCmdResultFromPopen("hilog -G 256K"); + (void)GetCmdResultFromPopen("hilog -w stop"); + (void)GetCmdResultFromPopen("hilog -w start"); +} + +namespace { +const std::list> helperList = { + /* help cmd suffix, information key word */ + {"", "Usage"}, + {"query", "Query"}, + {"clear", "Remove"}, + {"buffer", "buffer"}, + {"stats", "statistics"}, + {"persist", "persistance"}, + {"private", "privacy"}, + {"kmsg", "kmsg"}, + {"flowcontrol", "flow-control"}, + {"baselevel", "baselevel"}, + {"combo", "combination"}, + {"domain", "domain"}, +}; + +/** + * @tc.name: Dfx_HilogToolTest_HelperTest_001 + * @tc.desc: hilog help information. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HelperTest_001, TestSize.Level1) +{ + /** + * @tc.steps: step1. show hilog help information. + * @tc.steps: step2. invalid cmd. + */ + GTEST_LOG_(INFO) << "HelperTest_001: start."; + std::string prefix = "hilog -h "; + std::string cmd = ""; + for (auto &it : helperList) { + cmd = prefix + it.first; + EXPECT_TRUE(IsExistInCmdResult(cmd, it.second)); + } + + prefix = "hilog --help "; + for (auto &it : helperList) { + cmd = prefix + it.first; + EXPECT_TRUE(IsExistInCmdResult(cmd, it.second)); + } +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_001 + * @tc.desc: BaseLogLevelHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_001, TestSize.Level1) +{ + /** + * @tc.steps: step1. set global log level to INFO. + * @tc.steps: step2. invalid log level. + */ + GTEST_LOG_(INFO) << "HandleTest_001: start."; + std::string level = "I"; + std::string cmd = "hilog -b " + level; + std::string str = "Set global log level to " + level + " successfully\n"; + std::string query = "param get hilog.loggable.global"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n"); + + // stderr redirect to stdout + cmd = "hilog -b test_level 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_LOG_LEVEL_INVALID) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_002 + * @tc.desc: DomainHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_002, TestSize.Level1) +{ + /** + * @tc.steps: step1. set domain xxx log level to INFO. + * @tc.steps: step2. invaild domain. + */ + GTEST_LOG_(INFO) << "HandleTest_002: start."; + uint32_t domain = 0xd002d00; + std::string level = "I"; + std::string cmd = "hilog -b " + level + " -D " + Uint2HexStr(domain); + std::string str = "Set domain 0x" + Uint2HexStr(domain) + " log level to " + level + " successfully\n"; + std::string query = "param get hilog.loggable.domain." + Uint2HexStr(domain); + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n"); + + cmd = "hilog -D test_domain 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_DOMAIN_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_003 + * @tc.desc: TagHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_003, TestSize.Level1) +{ + /** + * @tc.steps: step1. set tag xxx log level to INFO. + * @tc.steps: step2. invalid tag. + */ + GTEST_LOG_(INFO) << "HandleTest_003: start."; + std::string tag = "test"; + std::string level = "I"; + std::string cmd = "hilog -b " + level + " -T " + tag; + std::string str = "Set tag " + tag + " log level to " + level + " successfully\n"; + std::string query = "param get hilog.loggable.tag." + tag; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n"); + + cmd = "hilog -T abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_TAG_STR_TOO_LONG) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_004 + * @tc.desc: BufferSizeSetHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_004, TestSize.Level1) +{ + /** + * @tc.steps: step1. set app,init.core buffer size [valid]. + * @tc.expected: step1. set app,init.core buffer size successfully. + * @tc.steps: step2. set app,init.core buffer size [invalid]. + * @tc.expected: step2 set app,init.core buffer size failed. + * buffer size should be in range [64.0K, 512.0M]. + * @tc.expected: step3 invalid buffer size str. + */ + GTEST_LOG_(INFO) << "HandleTest_004: start."; + std::string cmd = "hilog -G 512K"; + std::string str = "Set log type app buffer size to 512.0K successfully\n" + "Set log type init buffer size to 512.0K successfully\n" + "Set log type core buffer size to 512.0K successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -G 512G"; + str = "failed"; + EXPECT_TRUE(IsExistInCmdResult(cmd, str)); + + std::string inValidStrCmd = "hilog -G test_buffersize 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_SIZE_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(inValidStrCmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_005 + * @tc.desc: BufferSizeGetHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_005, TestSize.Level1) +{ + /** + * @tc.steps: step1. get app,init.core valid buffer size. + */ + GTEST_LOG_(INFO) << "HandleTest_005: start."; + std::string cmd = "hilog -g"; + std::string str = "Log type app buffer size is 512.0K\n" + "Log type init buffer size is 512.0K\n" + "Log type core buffer size is 512.0K\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_006 + * @tc.desc: KmsgFeatureSetHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_006, TestSize.Level1) +{ + /** + * @tc.steps: step1. set hilogd storing kmsg log feature on. + * @tc.steps: step2. set hilogd storing kmsg log feature off. + * @tc.steps: step3. set hilogd storing kmsg log feature invalid. + */ + GTEST_LOG_(INFO) << "HandleTest_006: start."; + std::string cmd = "hilog -k on"; + std::string str = "Set hilogd storing kmsg log on successfully\n"; + std::string query = "param get persist.sys.hilog.kmsg.on"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "true \n"); + + cmd = "hilog -k off"; + str = "Set hilogd storing kmsg log off successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "false \n"); + + cmd = "hilog -k test_feature 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_007 + * @tc.desc: PrivateFeatureSetHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_007, TestSize.Level1) +{ + /** + * @tc.steps: step1. set hilog api privacy formatter feature on. + * @tc.steps: step2. set hilog api privacy formatter feature off. + * @tc.steps: step3. set hilog api privacy formatter feature invalid. + */ + GTEST_LOG_(INFO) << "HandleTest_007: start."; + std::string cmd = "hilog -p on"; + std::string str = "Set hilog privacy format on successfully\n"; + std::string query = "param get hilog.private.on"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "true \n"); + + cmd = "hilog -p off"; + str = "Set hilog privacy format off successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "false \n"); + + cmd = "hilog -p test_feature 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_008 + * @tc.desc: FlowControlFeatureSetHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_008, TestSize.Level1) +{ + /** + * @tc.steps: step1. set process flow control on. + * @tc.steps: step2. set process flow control off. + * @tc.steps: step3. set domain flow control on. + * @tc.steps: step4. set domain flow control off. + * @tc.steps: step5. invalid cmd. + */ + GTEST_LOG_(INFO) << "HandleTest_008: start."; + std::string cmd = "hilog -Q pidon"; + std::string str = "Set flow control by process to enabled, result: Success [CODE: 0]\n"; + std::string query = "param get hilog.flowctrl.proc.on"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "true \n"); + + cmd = "hilog -Q pidoff"; + str = "Set flow control by process to disabled, result: Success [CODE: 0]\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "false \n"); + + cmd = "hilog -Q domainon"; + str = "Set flow control by domain to enabled, result: Success [CODE: 0]\n"; + query = "param get hilog.flowctrl.domain.on"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "true \n"); + + cmd = "hilog -Q domainoff"; + str = "Set flow control by domain to disabled, result: Success [CODE: 0]\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + EXPECT_EQ(GetCmdResultFromPopen(query), "false \n"); + + cmd = "hilog -Q test_cmd 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_009 + * @tc.desc: HeadHandler & TailHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_009, TestSize.Level1) +{ + /** + * @tc.steps: step1. show n lines logs on head of buffer. + * @tc.steps: step2. show n lines logs on tail of buffer. + * @tc.steps: step3. invalid cmd. + */ + GTEST_LOG_(INFO) << "HandleTest_009: start."; + int lines = 5; + std::string cmd = "hilog -a " + std::to_string(lines); + EXPECT_EQ(GetCmdLinesFromPopen(cmd), lines); + + cmd = "hilog -z " + std::to_string(lines); + EXPECT_EQ(GetCmdLinesFromPopen(cmd), lines); + + cmd = "hilog -a test 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -z test 2>&1"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -a 10 -z 10 2>&1"; + errMsg = ErrorCode2Str(ERR_COMMAND_INVALID) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_010 + * @tc.desc: RemoveHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_010, TestSize.Level1) +{ + /** + * @tc.steps: step1. get the localtime. + * @tc.steps: step2. remove all logs in hilogd buffer. + * @tc.steps: step3. compare the logtime to localtime. + */ + GTEST_LOG_(INFO) << "HandleTest_010: start."; + time_t tnow = time(nullptr); + struct tm *tmNow = localtime(&tnow); + char clearTime[32] = {0}; + if (tmNow != nullptr) { + strftime(clearTime, sizeof(clearTime), "%m-%d %H:%M:%S.%s", tmNow); + } + std::string cmd = "hilog -r"; + std::string str = "Log type core,app buffer clear successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + sleep(1); + std::string res = GetCmdResultFromPopen("hilog -a 5"); + std::string initStr = "HiLog: ========Zeroth log of type: init"; + vector vec; + std::string logTime = ""; + Split(res, vec, "\n"); + for (auto& it : vec) { + if (it.find(initStr) == string::npos) { + logTime = it.substr(0, 18); + EXPECT_LT(clearTime, logTime); + } + } +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_011 + * @tc.desc: TypeHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_011, TestSize.Level1) +{ + /** + * @tc.steps: step1. remove app logs in hilogd buffer. + * @tc.steps: step2. remove core logs in hilogd buffer. + * @tc.steps: step3. invalid log type. + */ + GTEST_LOG_(INFO) << "HandleTest_011: start."; + std::string cmd = "hilog -r -t app"; + std::string str = "Log type app buffer clear successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -r -t core"; + str = "Log type core buffer clear successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -r -t test_type 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_LOG_TYPE_INVALID) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_012 + * @tc.desc: PersistTaskHandler FileNameHandler JobIdHandler FileLengthHandler FileNumberHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_012, TestSize.Level1) +{ + /** + * @tc.steps: step1. start hilog persistance task control. + * @tc.steps: step2. stop hilog persistance task control. + * @tc.steps: step3. start hilog persistance task control with advanced options. + * @tc.steps: step4. query tasks informations. + * @tc.steps: step5. invalid persistance cmd. + * @tc.steps: step6. query invalid filename. + * @tc.steps: step7. query invalid jobid. + * @tc.steps: step8. query invalid filelength. + * @tc.steps: step9. query invalid filenumber. + */ + GTEST_LOG_(INFO) << "HandleTest_012: start."; + (void)GetCmdResultFromPopen("hilog -w stop"); + std::string cmd = "hilog -w start"; + std::string str = "Persist task [jobid:1] start successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -w stop"; + str = "Persist task [jobid:1] stop successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + std::string filename = "test"; + uint64_t length = 2 * 1024 * 1024; + std::string unit = "B"; + std::string compress = "zlib"; + int num = 25; + int jobid = 200; + cmd = "hilog -w start -f " + filename + " -l " + std::to_string(length) + unit + + " -n " + std::to_string(num) + " -m " + compress + " -j " + std::to_string(jobid); + str = "Persist task [jobid:" + std::to_string(jobid) + "] start successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -w query"; + str = std::to_string(jobid) + " init,core,app " + compress + " /data/log/hilog/" + filename + + " " + Size2Str(length) + " " + std::to_string(num) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + cmd = "hilog -w test 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + filename = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + cmd = "hilog -w query -f " + filename + " 2>&1"; + errMsg = ErrorCode2Str(ERR_FILE_NAME_TOO_LONG) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -w query -j test 2>&1"; + errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -w query -l test 2>&1"; + errMsg = ErrorCode2Str(ERR_INVALID_SIZE_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -w query -n test 2>&1"; + errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_013 + * @tc.desc: RegexHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_013, TestSize.Level1) +{ + /** + * @tc.steps: step1. show the logs which match the regular expression. + * @tc.steps: step2. invaild regex. + */ + GTEST_LOG_(INFO) << "HandleTest_013: start."; + std::string cmd = "hilog -x -e "; + std::string regex = "service"; + std::string res = GetCmdResultFromPopen(cmd + regex); + if (res != "") { + vector vec; + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(it.find(regex) != string::npos); + } + } + + cmd = "hilog -x -e abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_REGEX_STR_TOO_LONG) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_013 + * @tc.desc: LevelHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_014, TestSize.Level1) +{ + /** + * @tc.steps: step1. filter log level. + * @tc.steps: step2. invaild log level usage. + */ + GTEST_LOG_(INFO) << "HandleTest_014: start."; + std::string cmd = "hilog -a 10 -L "; + std::string level = "I"; + std::string res = GetCmdResultFromPopen(cmd + level); + vector vec; + Split(res, vec, "\n"); + for (auto& it : vec) { + std::string logLevel = it.substr(31, 1); + EXPECT_EQ(logLevel, level); + } + + cmd = "hilog -L test_level 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_LOG_LEVEL_INVALID) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -L E F 2>&1"; + errMsg = ErrorCode2Str(ERR_TOO_MANY_ARGUMENTS) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -L E -L F 2>&1"; + errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_013 + * @tc.desc: PidHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_015, TestSize.Level1) +{ + /** + * @tc.steps: step1. filter PID. + */ + GTEST_LOG_(INFO) << "HandleTest_015: start."; + std::string pid = GetCmdResultFromPopen("hilog -z 1").substr(19, 5); + std::string cmd = "hilog -a 10 -P "; + std::string res = GetCmdResultFromPopen(cmd + pid); + if (res != "") { + vector vec; + Split(res, vec, "\n"); + for (auto& it : vec) { + std::string logPid = it.substr(19, 5); + EXPECT_EQ(logPid, pid); + } + } + + cmd = "hilog -P test 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_016 + * @tc.desc: StatsInfoQueryHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_016, TestSize.Level1) +{ + /** + * @tc.steps: step1. set stats property. + * @tc.steps: step2. restart hilog service. + * @tc.steps: step3. show log statistic report. + * @tc.steps: step4. clear hilogd statistic information. + */ + GTEST_LOG_(INFO) << "HandleTest_016: start."; + (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats false"); + (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats.tag false"); + (void)GetCmdResultFromPopen("service_control stop hilogd"); + (void)GetCmdResultFromPopen("service_control start hilogd"); + sleep(3); + std::string cmd = "hilog -s"; + std::string str = "Statistic info query failed"; + EXPECT_TRUE(IsExistInCmdResult(cmd, str)); + + (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats true"); + (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats.tag true"); + (void)GetCmdResultFromPopen("service_control stop hilogd"); + (void)GetCmdResultFromPopen("service_control start hilogd"); + sleep(10); + str = "report"; + EXPECT_TRUE(IsExistInCmdResult(cmd, str)); + EXPECT_TRUE(IsStatsEnable()); + EXPECT_TRUE(IsTagStatsEnable()); + + cmd = "hilog -S"; + str = "Statistic info clear successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_017 + * @tc.desc: FormatHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_017, TestSize.Level1) +{ + /** + * @tc.steps: step1. log format time. + * @tc.steps: step2. log format epoch. + * @tc.steps: step3. log format monotonic. + * @tc.steps: step4. log format msec. + * @tc.steps: step5. log format usec. + * @tc.steps: step6. log format nsec. + * @tc.steps: step7. log format year. + * @tc.steps: step8. log format zone. + * @tc.steps: step9. invalid log format. + */ + GTEST_LOG_(INFO) << "HandleTest_017: start."; + std::string cmd = "hilog -v time -z 5"; + std::regex pattern("(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$"); + std::string res = GetCmdResultFromPopen(cmd); + vector vec; + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 18), pattern)); + } + + cmd = "hilog -v epoch -z 5"; + pattern = ("\\d{0,10}.\\d{3}$"); + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 14), pattern)); + } + + cmd = "hilog -v monotonic -z 5"; + pattern = ("\\d{0,8}.\\d{3}$"); + res = GetCmdResultFromPopen(cmd); + std::string initStr = "HiLog: ========Zeroth log of type"; + Split(res, vec, "\n"); + for (auto& it : vec) { + if (it.find(initStr) == string::npos) { + std::string str = it.substr(0, 12); + // remove the head blank space + str.erase(0, str.find_first_not_of(" ")); + EXPECT_TRUE(regex_match(str, pattern)); + } + } + + cmd = "hilog -v msec -z 5"; + pattern = ("(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$"); + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 18), pattern)); + } + + cmd = "hilog -v usec -z 5"; + pattern = "(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,6})?$"; + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 21), pattern)); + } + + cmd = "hilog -v nsec -z 5"; + pattern = "(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,9})?$"; + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 24), pattern)); + } + + cmd = "hilog -v year -z 5"; + pattern = "(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$"; + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 23), pattern)); + } + + cmd = "hilog -v zone -z 5"; + std::regex gmtPattern("GMT (0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$"); + std::regex cstPattern("CST (0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])" + ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$"); + res = GetCmdResultFromPopen(cmd); + Split(res, vec, "\n"); + for (auto& it : vec) { + EXPECT_TRUE(regex_match(it.substr(0, 22), gmtPattern) || regex_match(it.substr(0, 22), cstPattern)); + } + + cmd = "hilog -v test 2>&1"; + std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -v time -v epoch 2>&1"; + errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -v msec -v usec 2>&1"; + errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg); + + cmd = "hilog -x -v color"; + EXPECT_GT(GetCmdLinesFromPopen(cmd), 0); +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_018 + * @tc.desc: QueryLogHandler. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_018, TestSize.Level1) +{ + /** + * @tc.steps: step1. query log of specific pid. + * @tc.steps: step2. query log of specific domain. + * @tc.steps: step3. query log of specific tag. + */ + GTEST_LOG_(INFO) << "HandleTest_018: start."; + std::string res = GetCmdResultFromPopen("hilog -z 1"); + std::string pid = res.substr(19, 5); + std::string domain = res.substr(34, 5); + int tagLen = res.substr(40).find(":") + 1; + std::string tag = res.substr(40, tagLen); + std::string queryDomainCmd = "hilog -x -D d0" + domain; + std::string queryPidCmd = "hilog -x -P " + pid; + std::string queryTagCmd = "hilog -x -T " + tag; + vector vec; + + res = GetCmdResultFromPopen(queryPidCmd); + if (res != "") { + Split(res, vec, "\n"); + for (auto& it : vec) { + std::string logPid = it.substr(19, 5); + EXPECT_EQ(logPid, pid); + } + } + + res = GetCmdResultFromPopen(queryDomainCmd); + if (res != "") { + Split(res, vec, "\n"); + for (auto& it : vec) { + std::string logDomain = it.substr(34, 5); + EXPECT_EQ(logDomain, domain); + } + } + + res = GetCmdResultFromPopen(queryTagCmd); + if (res != "") { + Split(res, vec, "\n"); + for (auto& it : vec) { + std::string logTag = it.substr(40, tagLen); + EXPECT_EQ(logTag, tag); + } + } +} + +/** + * @tc.name: Dfx_HilogToolTest_HandleTest_019 + * @tc.desc: tag & domain level ctl. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_019, TestSize.Level1) +{ + /** + * @tc.steps: step1. tag level ctl. + * @tc.steps: step2. domain level ctl. + */ + GTEST_LOG_(INFO) << "HandleTest_019: start."; + std::string res = GetCmdResultFromPopen("hilog -z 1"); + uint32_t domain = std::stoi(res.substr(34, 5)); + int tagLen = res.substr(40).find(":") + 1; + std::string tag = res.substr(40, tagLen); + + // Priority: TagLevel > DomainLevel > GlobalLevel + SetTagLevel(tag, LOG_ERROR); + SetDomainLevel(domain, LOG_INFO); + EXPECT_FALSE(HiLogIsLoggable(domain, tag.c_str(), LOG_INFO)); + EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_ERROR)); + + SetTagLevel(tag, LOG_INFO); + SetDomainLevel(domain, LOG_ERROR); + EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_INFO)); + EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_ERROR)); + + // restore log level + SetDomainLevel(domain, LOG_INFO); +} +} // namespace diff --git a/test/unittest/common/hilogtool_test.h b/test/unittest/common/hilogtool_test.h new file mode 100644 index 0000000000000000000000000000000000000000..c8565ce0ef1eaa8e0fd275192bb110d6afd3ac6d --- /dev/null +++ b/test/unittest/common/hilogtool_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HILOGTOOL_TEST_H +#define HILOGTOOL_TEST_H + +#include + +namespace OHOS { +namespace HiviewDFX { +class HilogToolTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase(); + void SetUp() {} + void TearDown() {} +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // HILOGTOOL_TEST_H