diff --git a/adapter/properties.cpp b/adapter/properties.cpp index 939b0ea34b062c20073e4ca70b1ca05c2b662b3c..da2acb72ee40b0efba6b92b3c8b952f3a37c7b0e 100644 --- a/adapter/properties.cpp +++ b/adapter/properties.cpp @@ -47,6 +47,7 @@ static pthread_mutex_t g_persistDebugLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_privateLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_processFlowLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_domainFlowLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_kmsgLock = PTHREAD_MUTEX_INITIALIZER; using PropertyCache = struct { const void* pinfo; @@ -115,6 +116,9 @@ string GetPropertyName(uint32_t propType) case PROP_SINGLE_DEBUG: key = "hilog.debug.on"; break; + case PROP_KMSG: + key = "persist.sys.hilog.kmsg.on"; + break; case PROP_PERSIST_DEBUG: key = "persist.sys.hilog.debug.on"; break; @@ -141,6 +145,8 @@ static int LockByProp(uint32_t propType) return pthread_mutex_trylock(&g_tagLevelLock); case PROP_SINGLE_DEBUG: return pthread_mutex_trylock(&g_debugLock); + case PROP_KMSG: + return pthread_mutex_trylock(&g_kmsgLock); case PROP_PERSIST_DEBUG: return pthread_mutex_trylock(&g_persistDebugLock); default: @@ -172,6 +178,9 @@ static void UnlockByProp(uint32_t propType) case PROP_SINGLE_DEBUG: pthread_mutex_unlock(&g_debugLock); break; + case PROP_KMSG: + pthread_mutex_unlock(&g_kmsgLock); + break; case PROP_PERSIST_DEBUG: pthread_mutex_unlock(&g_persistDebugLock); break; @@ -271,6 +280,14 @@ bool IsDomainSwitchOn() return GetSwitchCache(isFirst, *switchCache, PROP_DOMAIN_FLOWCTRL, false); } +bool IsKmsgSwitchOn() +{ + static SwitchCache* switchCache = new SwitchCache {{nullptr, 0xffffffff, ""}, false}; + static atomic_flag isFirstFlag = ATOMIC_FLAG_INIT; + bool isFirst = !isFirstFlag.test_and_set(); + return GetSwitchCache(isFirst, *switchCache, PROP_KMSG, false); +} + static uint16_t GetCacheLevel(char propertyChar) { uint16_t cacheLevel = LOG_LEVEL_MIN; @@ -394,4 +411,4 @@ uint16_t GetTagLevel(const string& tag) return it->second->logLevel; } } -} \ No newline at end of file +} diff --git a/adapter/properties.h b/adapter/properties.h index cebbaa193af0ecdd55d7bffdbf5d18deefea87d0..12d2e5d075fa3a7e1266b492f081dd91ed400bd6 100644 --- a/adapter/properties.h +++ b/adapter/properties.h @@ -30,6 +30,7 @@ using PropType = enum { PROP_DOMAIN_LOG_LEVEL, PROP_TAG_LOG_LEVEL, PROP_SINGLE_DEBUG, + PROP_KMSG, PROP_PERSIST_DEBUG, }; @@ -44,6 +45,7 @@ bool IsPersistDebugOn(); bool IsPrivateSwitchOn(); bool IsProcessSwitchOn(); bool IsDomainSwitchOn(); +bool IsKmsgSwitchOn(); uint16_t GetGlobalLevel(); uint16_t GetDomainLevel(uint32_t domain); diff --git a/frameworks/native/format.cpp b/frameworks/native/format.cpp index b814ed70686f2fdcdbd05dd7383a609c448ae8e8..30cd5205ac2c5a6948d52289db1a5eca214af463 100644 --- a/frameworks/native/format.cpp +++ b/frameworks/native/format.cpp @@ -30,9 +30,6 @@ static const int HILOG_COLOR_GREEN = 40; static const int HILOG_COLOR_ORANGE = 166; static const int HILOG_COLOR_RED = 196; static const int HILOG_COLOR_YELLOW = 226; -static const long long NS = 1000000000LL; -static const long long NS2US = 1000LL; -static const long long NS2MS = 1000000LL; const char* ParsedFromLevel(uint16_t level) { @@ -66,7 +63,7 @@ int HilogShowTimeBuffer(char* buffer, int bufLen, HilogShowFormat showFormat, struct tm* ptm = nullptr; size_t timeLen = 0; int ret = 0; - nsecTime = (now < 0) ? (NS - nsecTime) : nsecTime; + nsecTime = (now < 0) ? (NSEC - nsecTime) : nsecTime; if ((showFormat == EPOCH_SHOWFORMAT) || (showFormat == MONOTONIC_SHOWFORMAT)) { ret = snprintf_s(buffer, bufLen, bufLen - 1, diff --git a/frameworks/native/include/hilog_common.h b/frameworks/native/include/hilog_common.h index e6e365f0c88870160a842d68021b93ecfd8a1bc6..89e4524b488044286bfe31868d6704bbd372d88f 100644 --- a/frameworks/native/include/hilog_common.h +++ b/frameworks/native/include/hilog_common.h @@ -44,11 +44,15 @@ #define ONE_MB (1UL<<20) #define ONE_GB (1UL<<30) #define ONE_TB (1ULL<<40) - +const long long NSEC = 1000000000LL; +const long long US = 1000000LL; +const long long NS2US = 1000LL; +const long long NS2MS = 1000000LL; const uint32_t MAX_BUFFER_SIZE = 1UL<<30; const uint32_t MAX_PERSISTER_BUFFER_SIZE = 64 * 1024; const int MSG_MAX_LEN = 2048; - +constexpr uint64_t PRIME = 0x100000001B3ull; +constexpr uint64_t BASIS = 0xCBF29CE484222325ull; /* * header of log message from libhilog to hilogd */ @@ -122,5 +126,6 @@ typedef enum { ERR_FLOWCTRL_SWITCH_VALUE_INVALID = -29, ERR_BUFF_SIZE_INVALID = -30, ERR_COMMAND_INVALID = -31, + ERR_KMSG_SWITCH_VALUE_INVALID = -32, } ErrorCode; #endif /* HILOG_COMMON_H */ diff --git a/frameworks/native/include/hilogtool_msg.h b/frameworks/native/include/hilogtool_msg.h index bf3b9f9184f8c9ace1e270a259de2f05c1426fee..1123a5f3c7dda2d47c4126e2bfa59a51978ee181 100644 --- a/frameworks/native/include/hilogtool_msg.h +++ b/frameworks/native/include/hilogtool_msg.h @@ -55,6 +55,7 @@ typedef enum { */ typedef enum { OT_PRIVATE_SWITCH = 0x01, + OT_KMSG_SWITCH, OT_LOG_LEVEL, OT_FLOW_SWITCH, } OperateType; @@ -310,6 +311,7 @@ typedef struct { typedef struct { std::string privateSwitchStr; + std::string kmsgSwitchStr; std::string flowSwitchStr; std::string logLevelStr; std::string domainStr; diff --git a/interfaces/native/innerkits/include/hilog/log_c.h b/interfaces/native/innerkits/include/hilog/log_c.h index 5622eaaad15a03e76911cefaaf031ca52a35e325..a32b3ed5a076d83e367a6d427e0683ab49c5e5c6 100644 --- a/interfaces/native/innerkits/include/hilog/log_c.h +++ b/interfaces/native/innerkits/include/hilog/log_c.h @@ -1,17 +1,17 @@ -/* - * 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. - */ +/* + * 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. + */ #ifndef HIVIEWDFX_HILOG_C_H #define HIVIEWDFX_HILOG_C_H @@ -37,10 +37,10 @@ extern "C" { typedef enum { LOG_TYPE_MIN = 0, LOG_APP = 0, - // Log to kmsg, only used by init phase. LOG_INIT = 1, // Used by core service, framework. LOG_CORE = 3, + LOG_KMSG = 4, LOG_TYPE_MAX } LogType; diff --git a/services/hilogd/BUILD.gn b/services/hilogd/BUILD.gn index e241cd5b412b2c1dfe5268366cf5e3c96d3bb6fe..6c6736acb88647df90038ca4e60830f6706e0de3 100644 --- a/services/hilogd/BUILD.gn +++ b/services/hilogd/BUILD.gn @@ -24,6 +24,7 @@ ohos_executable("hilogd") { "cmd_executor.cpp", "flow_control_init.cpp", "log_buffer.cpp", + "log_kmsg.cpp", "log_collector.cpp", "log_compress.cpp", "log_persister.cpp", diff --git a/services/hilogd/etc/hilogd.cfg b/services/hilogd/etc/hilogd.cfg index e5516f34463e0f81c40dad5384995300ce3824ab..340977ecb16fac3453a6e9fbfd774efed8659061 100644 --- a/services/hilogd/etc/hilogd.cfg +++ b/services/hilogd/etc/hilogd.cfg @@ -9,6 +9,7 @@ "cmds" : [ "mkdir /data/log/ 0770 system log", "mkdir /data/log/hilog/ 0750 logd log", + "chmod 0664 /dev/kmsg", "start hilogd" ] } @@ -25,4 +26,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/services/hilogd/include/log_buffer.h b/services/hilogd/include/log_buffer.h index a0ad2ddd411cfd4c00602a320838211db9e5717c..5dd12f96637bc32283ba9d7b7145b16e5ccb618f 100644 --- a/services/hilogd/include/log_buffer.h +++ b/services/hilogd/include/log_buffer.h @@ -53,6 +53,7 @@ private: size_t size; size_t sizeByType[LOG_TYPE_MAX]; std::list hilogDataList; + std::list hilogKlogList; std::shared_mutex hilogBufferMutex; std::map cacheLenByDomain; std::map printLenByDomain; diff --git a/services/hilogd/include/log_collector.h b/services/hilogd/include/log_collector.h index 3109a7d8a647ff28c70ac761a82b20dc61ba49f1..1eaa729a15e8ffc818d5fd24fd8ab238150b9a32 100644 --- a/services/hilogd/include/log_collector.h +++ b/services/hilogd/include/log_collector.h @@ -38,4 +38,4 @@ private: }; } // namespace HiviewDFX } // namespace OHOS -#endif \ No newline at end of file +#endif diff --git a/services/hilogd/include/log_kmsg.h b/services/hilogd/include/log_kmsg.h new file mode 100644 index 0000000000000000000000000000000000000000..3221ce0146eac22eb1f84d96f168d0c18e48b0a1 --- /dev/null +++ b/services/hilogd/include/log_kmsg.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef LOG_KMSG_H +#define LOG_KMSG_H + +#include "log_collector.h" + +namespace OHOS { +namespace HiviewDFX { +class LogKmsg { +public: + LogKmsg(const LogCollector& collector) : collector(collector) {}; + LogKmsg(const LogCollector&&) = delete; + ~LogKmsg(); + ssize_t LinuxReadOneKmsg(); + int LinuxReadAllKmsg(); + void ReadAllKmsg(); + void Start(); + void FreeKmsg(); + std::chrono::time_point BootTime(); +private: + int kmsgCtl = -1; + char *kmsgBuffer; + char *mtag; + HilogMsg *msg; + const LogCollector& collector; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif + diff --git a/services/hilogd/log_buffer.cpp b/services/hilogd/log_buffer.cpp index 7a4e68356ffef06eca30dca42505de73a323fc4c..420b1675745b633b2a55f05900e563e3d908ab88 100644 --- a/services/hilogd/log_buffer.cpp +++ b/services/hilogd/log_buffer.cpp @@ -15,15 +15,7 @@ #include "log_buffer.h" -#include #include -#include -#include -#include -#include -#include -#include - #include "hilog_common.h" #include "flow_control_init.h" @@ -60,13 +52,14 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) return 0; } + std::list &list = (msg.type == LOG_KMSG) ? hilogKlogList : hilogDataList; // Delete old entries when full if (eleSize + sizeByType[msg.type] >= (size_t)g_maxBufferSizeByType[msg.type]) { hilogBufferMutex.lock(); // Drop 5% of maximum log when full - std::list::iterator it = hilogDataList.begin(); + std::list::iterator it = list.begin(); while (sizeByType[msg.type] > g_maxBufferSizeByType[msg.type] * (1 - DROP_RATIO) && - it != hilogDataList.end()) { + it != list.end()) { if ((*it).type != msg.type) { // Only remove old logs of the same type ++it; continue; @@ -84,7 +77,7 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) size_t cLen = it->len - it->tag_len; size -= cLen; sizeByType[(*it).type] -= cLen; - it = hilogDataList.erase(it); + it = list.erase(it); } // Re-confirm if enough elements has been removed @@ -95,13 +88,13 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) } // Insert new log into HilogBuffer - std::list::reverse_iterator rit = hilogDataList.rbegin(); + std::list::reverse_iterator rit = list.rbegin(); if (msg.tv_sec >= (rit->tv_sec)) { - hilogDataList.emplace_back(msg); + list.emplace_back(msg); } else { // Find the place with right timestamp ++rit; - for (; rit != hilogDataList.rend() && msg.tv_sec < rit->tv_sec; ++rit) { + for (; rit != list.rend() && msg.tv_sec < rit->tv_sec; ++rit) { logReaderListMutex.lock_shared(); for (auto &itr :logReaderList) { if (itr.lock()->readPos == std::prev(rit.base())) { @@ -110,7 +103,7 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) } logReaderListMutex.unlock_shared(); } - hilogDataList.emplace(rit.base(), msg); + list.emplace(rit.base(), msg); } // Update current size of HilogBuffer size += eleSize; @@ -127,15 +120,17 @@ size_t HilogBuffer::Insert(const HilogMsg& msg) bool HilogBuffer::Query(std::shared_ptr reader) { + uint16_t qTypes = reader->queryCondition.types; + std::list &list = (qTypes == (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; hilogBufferMutex.lock_shared(); if (reader->GetReload()) { - reader->readPos = hilogDataList.begin(); - reader->lastPos = hilogDataList.begin(); + reader->readPos = list.begin(); + reader->lastPos = list.begin(); reader->SetReload(false); } if (reader->isNotified) { - if (reader->readPos == hilogDataList.end()) { + if (reader->readPos == list.end()) { reader->readPos = std::next(reader->lastPos); } } @@ -154,7 +149,7 @@ bool HilogBuffer::Query(std::shared_ptr reader) hilogBufferMutex.unlock_shared(); return true; } - while (reader->readPos != hilogDataList.end()) { + while (reader->readPos != list.end()) { reader->lastPos = reader->readPos; if (ConditionMatch(reader)) { reader->SetSendId(SENDIDA); diff --git a/services/hilogd/log_collector.cpp b/services/hilogd/log_collector.cpp index 14e20d9d0c1c5e2942723bc684112e45cd4c4fe0..4bfcfd26aa8bbd246d92fcd7028650429a9827ab 100644 --- a/services/hilogd/log_collector.cpp +++ b/services/hilogd/log_collector.cpp @@ -14,18 +14,22 @@ */ #include "log_collector.h" +#include "log_kmsg.h" #include "flow_control_init.h" #include #include +#include #include #include #include - +#include +#include namespace OHOS { namespace HiviewDFX { using namespace std; HilogBuffer* LogCollector::hilogBuffer = nullptr; + int LogCollector::FlowCtrlDataRecv(HilogMsg *msg, int ret) { string dropLog = to_string(ret) + " line(s) dropped!"; diff --git a/services/hilogd/log_kmsg.cpp b/services/hilogd/log_kmsg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..015dae1b9e52f3def9239fcb51f0ebc7e1058628 --- /dev/null +++ b/services/hilogd/log_kmsg.cpp @@ -0,0 +1,216 @@ +/* + * 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 "log_kmsg.h" +#include "hilog/log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HiviewDFX { +using namespace std; +using namespace std::chrono; + +constexpr int DEC = 10; + +// Avoid name collision between sys/syslog.h and our log_c.h +#undef LOG_FATAL +#undef LOG_ERR +#undef LOG_WARN +#undef LOG_INFO +#undef LOG_DEBUG + +// Parse pid if exists +uint32_t ParsePid(const char *str, bool *found) +{ + constexpr int pidPos = 5; + if (strncmp(str, "[pid=", pidPos) != 0) { + *found = false; + return 0; + } + uint32_t pid = strtoul(str + pidPos, nullptr, DEC); + *found = true; + return pid; +} + +// Log levels are different in syslog.h and hilog log_c.h +uint16_t KmsgLevelMap(uint16_t prio) +{ + uint16_t level; + switch (prio) { + case 0: + case 1: + case 2: + level = LOG_FATAL; + break; + case 3: + level = LOG_ERROR; + break; + case 4: + case 5: + level = LOG_WARN; + break; + case 6: + level = LOG_INFO; + break; + default: + level = LOG_DEBUG; + break; + } + return level; +} + +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. +time_point LogKmsg::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; +} +void LogKmsg::FreeKmsg() +{ + free(mtag); + free(msg); +} +ssize_t LogKmsg::LinuxReadOneKmsg() +{ + ssize_t size = -1; + do { + size = read(kmsgCtl, kmsgBuffer, BUFSIZ - 1); + } while (size < 0 && errno == EPIPE); + if (size > 0) { + mtag = (char*)calloc(MAX_TAG_LEN, sizeof(char)); + char *savePtr = nullptr; + // Parses header of kmsg entry: priority,sequence,timestamp,flag; + uint16_t mLevel = strtoul(strtok_r(kmsgBuffer, ",", &savePtr), nullptr, DEC); + strtok_r(nullptr, ",", &savePtr); // Kmsg seq is not needed at present + uint64_t timestamp = strtoumax(strtok_r(nullptr, ",", &savePtr), nullptr, DEC); + strtok_r(nullptr, ";", &savePtr); // Kmsg flag is not needed at present + // Parses pid if exists. Pid in kmsg content is like: [pid=xxx,...] + uint32_t mpid = 0; + bool found = false; + mpid = ParsePid(savePtr, &found); + if (found) strtok_r(nullptr, "]", &savePtr); + // If there are some other content wrapped in square brackets "[]", parse it as tag + // Otherwise, use default tag "kmsg" + int tagLen = 0; + if (savePtr[0] == '[') { + char *sep = strtok_r(nullptr, "]", &savePtr); + if (sep != nullptr) { + tagLen = strlen(sep) - 1; + if (strncpy_s(mtag, MAX_TAG_LEN - 1, sep + 1, tagLen) != 0) { + free(mtag); + return size; + } + } + } else { + char kmsgStr[] = "kmsg"; + tagLen = strlen(kmsgStr); + if (strncpy_s(mtag, MAX_TAG_LEN - 1, "kmsg", tagLen) != 0) { + free(mtag); + return size; + } + } + // Now build HilogMsg and insert it into buffer + int len = strlen(savePtr) + 1; + int msgLen = sizeof(HilogMsg) + tagLen + len + 1; + msg = (HilogMsg*)malloc(msgLen); + msg->len = msgLen; + msg->tag_len = tagLen + 1; + msg->type = LOG_KMSG; + msg->domain = 0xdfffffff; + msg->level = KmsgLevelMap(mLevel); + time_point logtime = BootTime() + microseconds{timestamp}; + struct timespec logts = TimepointToTimespec(logtime); + msg->tv_sec = logts.tv_sec; + msg->tv_nsec = logts.tv_nsec; + msg->pid = mpid; + msg->tid = mpid; + if (strncpy_s(msg->tag, tagLen + 1, mtag, tagLen) != 0) { + FreeKmsg(); + return size; + } + if (strncpy_s(CONTENT_PTR((msg)), MAX_LOG_LEN, savePtr, len) != 0) { + FreeKmsg(); + return size; + } + collector.InsertLogToBuffer(*msg); + FreeKmsg(); + } + return size; +} + +int LogKmsg::LinuxReadAllKmsg() +{ + kmsgBuffer = (char*)calloc(BUFSIZ, sizeof(char)); + kmsgCtl = open("/dev/kmsg", O_RDONLY); + if (kmsgCtl < 0) { + std::cout << "Cannot open kmsg! Err=" << strerror(errno) << std::endl; + return -1; + } + ssize_t sz = LinuxReadOneKmsg(); + while (sz > 0) { + memset_s(kmsgBuffer, BUFSIZ, '\0', BUFSIZ); + sz = LinuxReadOneKmsg(); + } + return 1; +} + +void LogKmsg::ReadAllKmsg() +{ +#ifdef __linux__ + std::cout << "Platform: Linux" << std::endl; + LinuxReadAllKmsg(); +#endif +} + +void LogKmsg::Start() +{ + std::thread KmsgThread([this]() { + ReadAllKmsg(); + }); + KmsgThread.join(); +} + +LogKmsg::~LogKmsg() +{ + close(kmsgCtl); + free(kmsgBuffer); +} +} // namespace HiviewDFX +} // namespace OHOS + diff --git a/services/hilogd/log_persister.cpp b/services/hilogd/log_persister.cpp index 93929f6c42943776845d7fc059ff0dfcecb9bcdd..832100fe1507ebaf52106624e257349382d2544f 100644 --- a/services/hilogd/log_persister.cpp +++ b/services/hilogd/log_persister.cpp @@ -328,7 +328,7 @@ int LogPersister::Query(uint16_t logType, list &results) cout << "Persister.Query: logType " << logType << endl; for (auto it = logPersisters.begin(); it != logPersisters.end(); ++it) { cout << "Persister.Query: (*it)->queryCondition.types " - << (*it)->queryCondition.types << endl; + << unsigned((*it)->queryCondition.types) << endl; if (((*it)->queryCondition.types & logType) != 0) { LogPersistQueryResult response; response.logType = (*it)->queryCondition.types; diff --git a/services/hilogd/log_persister_rotator.cpp b/services/hilogd/log_persister_rotator.cpp index 4865edd1a6cd579b10ba3026691a62a67019ce07..470ba48800de5b12d94b08c7bce58b5abd7741f7 100644 --- a/services/hilogd/log_persister_rotator.cpp +++ b/services/hilogd/log_persister_rotator.cpp @@ -25,8 +25,6 @@ namespace OHOS { namespace HiviewDFX { using namespace std; -constexpr uint64_t PRIME = 0x100000001B3ull; -constexpr uint64_t BASIS = 0xCBF29CE484222325ull; uint64_t GetInfoHash(const PersistRecoveryInfo &info) { uint64_t ret {BASIS}; diff --git a/services/hilogd/log_querier.cpp b/services/hilogd/log_querier.cpp index 2a604e1ebdf2131a9edfe4a5bcdb889c7e85ee50..d9a62304849b086bf1773b7b984ef32781de02fc 100644 --- a/services/hilogd/log_querier.cpp +++ b/services/hilogd/log_querier.cpp @@ -44,7 +44,7 @@ using namespace std; constexpr int MAX_DATA_LEN = 2048; string g_logPersisterDir = HILOG_FILE_DIR; constexpr int DEFAULT_LOG_LEVEL = 1< logReade string logPersisterPath; if (pLogPersistStartRst == nullptr) { return; + } else if (LogTypeForbidden(pLogPersistStartMsg->logType) == false) { + pLogPersistStartRst->result = ERR_QUERY_TYPE_INVALID; } else if (pLogPersistStartMsg->jobId <= 0) { pLogPersistStartRst->result = ERR_LOG_PERSIST_JOBID_INVALID; } else if (pLogPersistStartMsg->fileSize < MAX_PERSISTER_BUFFER_SIZE) { @@ -150,7 +163,9 @@ void HandlePersistStartRequest(char* reqMsg, std::shared_ptr logReade cout << "FileName is not valid!" << endl; pLogPersistStartRst->result = ERR_LOG_PERSIST_FILE_NAME_INVALID; } else { - logPersisterPath = (strlen(pLogPersistStartMsg->filePath) == 0) ? (g_logPersisterDir + "hilog") + string logPersisterFileName = (pLogPersistStartMsg->logType == (0b01 << LOG_KMSG)) ? "hilog_kmsg" : "hilog"; + cout << "logPersisterFileName" << logPersisterFileName << endl; + logPersisterPath = (strlen(pLogPersistStartMsg->filePath) == 0) ? (g_logPersisterDir + logPersisterFileName) : (g_logPersisterDir + string(pLogPersistStartMsg->filePath)); if (strcpy_s(pLogPersistStartMsg->filePath, FILE_PATH_MAX_LEN, logPersisterPath.c_str()) != 0) { pLogPersistStartRst->result = RET_FAIL; @@ -463,6 +478,9 @@ void LogQuerier::LogQuerierThreadFunc(std::shared_ptr logReader) case LOG_QUERY_REQUEST: qRstMsg = (LogQueryRequest*) g_tempBuffer; SetCondition(logReader, *qRstMsg); + if (!LogTypeForbidden(logReader->queryCondition.types)) { + return; + } HandleLogQueryRequest(logReader, *hilogBuffer); break; case NEXT_REQUEST: diff --git a/services/hilogd/main.cpp b/services/hilogd/main.cpp index df060f299a81f276d8ff1ad2b9bf4a7e5b0a7b65..dcfd01333c10bdae6397fec59789e8ecaacdb5d7 100644 --- a/services/hilogd/main.cpp +++ b/services/hilogd/main.cpp @@ -12,17 +12,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include #include #include +#include #include -#include #include "cmd_executor.h" #include "log_querier.h" #include "hilog_input_socket_server.h" #include "log_collector.h" +#include "log_kmsg.h" #include "flow_control_init.h" +#include "properties.h" #ifdef DEBUG #include @@ -38,22 +41,9 @@ using namespace std; static int g_fd = -1; #endif -static void SigHandler(int sig) -{ - if (sig == SIGINT) { -#ifdef DEBUG - if (g_fd > 0) { - close(g_fd); - } -#endif - std::cout<<"Exited!"< 0) { @@ -62,43 +52,38 @@ int HilogdEntry(int argc, char* argv[]) std::cout << "open file error:" << strerror(errno) << std::endl; } #endif - std::signal(SIGINT, SigHandler); InitDomainFlowCtrl(); // Start log_collector - LogCollector logCollector(&hilogBuffer); + LogCollector logCollector(hilogBuffer); HilogInputSocketServer server(logCollector.onDataRecv); if (server.Init() < 0) { #ifdef DEBUG cout << "Failed to init input server socket ! error=" << strerror(errno) << std::endl; #endif } else { - if (chmod(INPUT_SOCKET, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) < 0) { - cout << "chmod input socket failed !\n"; - } #ifdef DEBUG cout << "Begin to listen !\n"; #endif server.RunServingThread(); } + LogKmsg klog(logCollector); + auto klogTask = std::async(std::launch::async, &LogKmsg::ReadAllKmsg, klog); - std::thread startupCheckThread([&hilogBuffer]() { - std::shared_ptr logQuerier = std::make_shared(nullptr, &hilogBuffer); - logQuerier->RestorePersistJobs(hilogBuffer); + auto startupCheckTask = std::async(std::launch::async, [&hilogBuffer]() { + std::shared_ptr logQuerier = std::make_shared(nullptr, hilogBuffer); + logQuerier->RestorePersistJobs(*hilogBuffer); }); - startupCheckThread.detach(); - - CmdExecutor cmdExecutor(&hilogBuffer); + CmdExecutor cmdExecutor(hilogBuffer); cmdExecutor.StartCmdExecutorThread(); - return 0; } } // namespace HiviewDFX } // namespace OHOS -int main(int argc, char* argv[]) +int main() { - OHOS::HiviewDFX::HilogdEntry(argc, argv); + OHOS::HiviewDFX::HilogdEntry(); return 0; } diff --git a/services/hilogtool/include/hilogtool.h b/services/hilogtool/include/hilogtool.h index 4bcce3af41dd4dec150a6f978826b5f1cfca2dd9..ef74cc97a528e57c2203b8052a4b09f00a991983 100644 --- a/services/hilogtool/include/hilogtool.h +++ b/services/hilogtool/include/hilogtool.h @@ -51,6 +51,7 @@ typedef struct { std::string fileNameArgs; std::string jobIdArgs; std::string personalArgs; + std::string kmsgArgs; std::string logClearArgs; std::string logTypeArgs; std::string domainArgs; diff --git a/services/hilogtool/include/log_controller.h b/services/hilogtool/include/log_controller.h index 1b7085ceda7a6c3d66bfa5e820b3cf92eee5d7d2..d0d6690166ba97fc1bb2edc975775435c5a436d2 100644 --- a/services/hilogtool/include/log_controller.h +++ b/services/hilogtool/include/log_controller.h @@ -30,7 +30,6 @@ constexpr int RECV_BUF_LEN = MAX_LOG_LEN * 2; void SetMsgHead(MessageHeader* msgHeader, const uint8_t msgCmd, const uint16_t msgLen); int MultiQuerySplit(const std::string& src, const char& delim, std::vector& vec); -inline void PrintBuffer(void* pBuff, unsigned int nLen); void NextRequestOp(SeqPacketSocketClient& controller, uint16_t sendId); void LogQueryRequestOp(SeqPacketSocketClient& controller, const HilogArgs* context); void LogQueryResponseOp(SeqPacketSocketClient& controller, char* recvBuffer, uint32_t bufLen, diff --git a/services/hilogtool/log_controller.cpp b/services/hilogtool/log_controller.cpp index 17f1e8102065c9709a2510fd02afb31c828e9ec4..60ac33b32a3442e12df0a4f852e9af283d409c53 100644 --- a/services/hilogtool/log_controller.cpp +++ b/services/hilogtool/log_controller.cpp @@ -16,12 +16,11 @@ #include "log_controller.h" #include +#include #include #include -#include #include #include -#include #include #include "hilog/log.h" #include "hilog_common.h" @@ -37,7 +36,7 @@ using namespace std; const int LOG_PERSIST_FILE_SIZE = 4 * ONE_MB; const int LOG_PERSIST_FILE_NUM = 10; const uint32_t DEFAULT_JOBID = 1; - +const uint32_t DEFAULT_KMSG_JOBID = 2; void SetMsgHead(MessageHeader* msgHeader, const uint8_t msgCmd, const uint16_t msgLen) { if (!msgHeader) { @@ -82,6 +81,8 @@ uint16_t GetLogType(const string& logTypeStr) logType = LOG_CORE; } else if (logTypeStr == "app") { logType = LOG_APP; + } else if (logTypeStr == "kmsg") { + logType = LOG_KMSG; } else { return 0xffff; } @@ -418,8 +419,13 @@ int32_t LogPersistOp(SeqPacketSocketClient& controller, uint8_t msgCmd, LogPersi } pLogPersistStartMsg->logType = (0b01 << tmpType) | pLogPersistStartMsg->logType; } - pLogPersistStartMsg->jobId = (logPersistParam->jobIdStr == "") ? DEFAULT_JOBID - : stoi(logPersistParam->jobIdStr); + if (pLogPersistStartMsg->logType == (0b01 << LOG_KMSG)) { + pLogPersistStartMsg->jobId = (logPersistParam->jobIdStr == "") ? DEFAULT_KMSG_JOBID : stoi( + logPersistParam->jobIdStr); + } else { + pLogPersistStartMsg->jobId = (logPersistParam->jobIdStr == "") ? DEFAULT_JOBID + : stoi(logPersistParam->jobIdStr); + } if (pLogPersistStartMsg->jobId <= 0) { cout << ParseErrorCode(ERR_LOG_PERSIST_JOBID_INVALID) << endl; return RET_FAIL; @@ -521,7 +527,19 @@ int32_t SetPropertiesOp(SeqPacketSocketClient& controller, uint8_t operationType return RET_FAIL; } break; - + case OT_KMSG_SWITCH: + key = GetPropertyName(PROP_KMSG); + if (propertyParm->kmsgSwitchStr == "on") { + PropertySet(key.c_str(), "true"); + std::cout << "hilog will store kmsg log" << std::endl; + } else if (propertyParm->kmsgSwitchStr == "off") { + PropertySet(key.c_str(), "false"); + std::cout << "hilog will not store kmsg log" << std::endl; + } else { + std::cout << ParseErrorCode(ERR_KMSG_SWITCH_VALUE_INVALID) << std::endl; + return RET_FAIL; + } + break; case OT_LOG_LEVEL: if (propertyParm->tagStr != "" && propertyParm->domainStr != "") { return RET_FAIL; diff --git a/services/hilogtool/log_display.cpp b/services/hilogtool/log_display.cpp index 1b19a39bda8611af5fef544e2fbd4a40c25016c4..2f9190cd7fac34d8d28551c0d09028107aaa8d2b 100644 --- a/services/hilogtool/log_display.cpp +++ b/services/hilogtool/log_display.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -31,16 +30,13 @@ namespace HiviewDFX { using namespace std; using hash_t = std::uint64_t; - -constexpr hash_t PRIME = 0x100000001B3ull; -constexpr hash_t BASIS = 0xCBF29CE484222325ull; - unordered_map errorMsg { {RET_FAIL, "Unexpected error"}, {ERR_LOG_LEVEL_INVALID, "Invalid log level, the valid log levels include D/I/W/E/F"}, - {ERR_LOG_TYPE_INVALID, "Invalid log type, the valid log types include app/core/init"}, - {ERR_QUERY_TYPE_INVALID, "Query condition on both types and excluded types is undefined"}, + {ERR_LOG_TYPE_INVALID, "Invalid log type, the valid log types include app/core/init/kmsg"}, + {ERR_QUERY_TYPE_INVALID, "Query condition on both types and excluded types is undefined or\ + queryTypes can not contain app/core/init and kmsg at the same time"}, {ERR_QUERY_LEVEL_INVALID, "Query condition on both levels and excluded levels is undefined"}, {ERR_QUERY_DOMAIN_INVALID, "Invalid domain format, a hexadecimal number is needed"}, {ERR_QUERY_TAG_INVALID, "Query condition on both tags and excluded tags is undefined"}, @@ -68,7 +64,8 @@ unordered_map errorMsg {ERR_FORMAT_INVALID, "Invalid format parameter"}, {ERR_BUFF_SIZE_INVALID, "Invalid buffer size, buffer size should be more than 0 and less than " + to_string(MAX_BUFFER_SIZE)}, - {ERR_COMMAND_INVALID, "Invalid command, only one control command can be executed each time"} + {ERR_COMMAND_INVALID, "Invalid command, only one control command can be executed each time"}, + {ERR_KMSG_SWITCH_VALUE_INVALID, "Invalid kmsg switch value, valid:on/off"} }; string ParseErrorCode(ErrorCode errorCode) @@ -111,6 +108,9 @@ string GetLogTypeStr(uint16_t logType) if (logType == LOG_APP) { logTypeStr = "app"; } + if (logType == LOG_KMSG) { + logTypeStr = "kmsg"; + } return logTypeStr; } @@ -126,6 +126,9 @@ string GetOrigType(uint16_t shiftType) if (((1 << LOG_APP) & shiftType) != 0) { logType += "app,"; } + if (((1 << LOG_KMSG) & shiftType) != 0) { + logType += "kmsg,"; + } logType.erase(logType.end() - 1); return logType; } diff --git a/services/hilogtool/main.cpp b/services/hilogtool/main.cpp index 9d3c0eb4e9449ab7790e8417aa7170a93e6df68d..a1d36c622b99623be50139819074d1db55bd70b4 100644 --- a/services/hilogtool/main.cpp +++ b/services/hilogtool/main.cpp @@ -16,12 +16,11 @@ #include #include #include +#include #include #include #include -#include #include -#include #include #include #include @@ -51,6 +50,10 @@ static void Helper() " set privacy formatter feature on or off.\n" " on turn on\n" " off turn off\n" + " -k\n" + " store log type kmsg or not\n" + " on yes\n" + " off no\n" " -s, --statistics query hilogd statistic information.\n" " -S clear hilogd statistic information.\n" " -r remove the logs in hilog buffer, use -t to specify log type\n" @@ -127,6 +130,8 @@ static int GetTypes(HilogArgs context, const string& typesArgs, bool exclude = f types |= 1<