diff --git a/frameworks/libhilog/hilog_printf.cpp b/frameworks/libhilog/hilog_printf.cpp index 1e92587d263630ecfb315d260ff5c1fccd74d7af..25ba4f761bd9f80ec1936af817c5d059546fd949 100644 --- a/frameworks/libhilog/hilog_printf.cpp +++ b/frameworks/libhilog/hilog_printf.cpp @@ -103,10 +103,18 @@ static uint16_t GetFinalLevel(unsigned int domain, const std::string& tag) if (tagLevel != LOG_LEVEL_MIN) { return tagLevel; } + uint16_t persistTagLevel = GetPersistTagLevel(tag); + if (persistTagLevel != LOG_LEVEL_MIN) { + return persistTagLevel; + } uint16_t domainLevel = GetDomainLevel(domain); if (domainLevel != LOG_LEVEL_MIN) { return domainLevel; } + uint16_t persistDomainLevel = GetPersistDomainLevel(domain); + if (persistDomainLevel != LOG_LEVEL_MIN) { + return persistDomainLevel; + } // 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)) { @@ -115,7 +123,7 @@ static uint16_t GetFinalLevel(unsigned int domain, const std::string& tag) return LOG_LEVEL_MIN; } } - return GetGlobalLevel(); + return GetGlobalLogLevel(); #else return LOG_LEVEL_MIN; #endif diff --git a/frameworks/libhilog/param/include/properties.h b/frameworks/libhilog/param/include/properties.h index fecf644233732654f7acb2bbcf31c4cca0978acb..afade48a530109bf88340a0326352444c47cb964 100644 --- a/frameworks/libhilog/param/include/properties.h +++ b/frameworks/libhilog/param/include/properties.h @@ -34,9 +34,13 @@ bool IsPrivateSwitchOn(); } #endif bool IsDebuggableHap(); +uint16_t GetGlobalLogLevel(); uint16_t GetGlobalLevel(); +uint16_t GetPersistGlobalLevel(); uint16_t GetDomainLevel(uint32_t domain); +uint16_t GetPersistDomainLevel(uint32_t domain); uint16_t GetTagLevel(const std::string& tag); +uint16_t GetPersistTagLevel(const std::string& tag); bool IsProcessSwitchOn(); bool IsDomainSwitchOn(); bool IsKmsgSwitchOn(); @@ -50,8 +54,11 @@ int SetPrivateSwitchOn(bool on); int SetOnceDebugOn(bool on); int SetPersistDebugOn(bool on); int SetGlobalLevel(uint16_t lvl); +int SetPersistGlobalLevel(uint16_t lvl); int SetTagLevel(const std::string& tag, uint16_t lvl); +int SetPersistTagLevel(const std::string& tag, uint16_t lvl); int SetDomainLevel(uint32_t domain, uint16_t lvl); +int SetPersistDomainLevel(uint32_t domain, uint16_t lvl); int SetProcessSwitchOn(bool on); int SetDomainSwitchOn(bool on); int SetKmsgSwitchOn(bool on); diff --git a/frameworks/libhilog/param/properties.cpp b/frameworks/libhilog/param/properties.cpp index 725924c3044bb0cd8151989ee599ca03a204f6b0..ec968ae9434fe0b94338f07b5a7aa20ba59c885a 100644 --- a/frameworks/libhilog/param/properties.cpp +++ b/frameworks/libhilog/param/properties.cpp @@ -47,8 +47,11 @@ enum class PropType { PROP_ONCE_DEBUG, PROP_PERSIST_DEBUG, PROP_GLOBAL_LOG_LEVEL, + PROP_PERSIST_GLOBAL_LOG_LEVEL, PROP_DOMAIN_LOG_LEVEL, + PROP_PERSIST_DOMAIN_LOG_LEVEL, PROP_TAG_LOG_LEVEL, + PROP_PERSIST_TAG_LOG_LEVEL, PROP_DOMAIN_FLOWCTRL, PROP_PROCESS_FLOWCTRL, @@ -74,8 +77,11 @@ static pthread_mutex_t g_privateLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_onceDebugLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_persistDebugLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_globalLevelLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_persistGlobalLevelLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_domainLevelLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_persistDomainLevelLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_tagLevelLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_persistTagLevelLock = 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"; @@ -90,8 +96,11 @@ static PropRes g_propResources[static_cast(PropType::PROP_MAX)] = { {"hilog.debug.on", &g_onceDebugLock}, // PROP_ONCE_DEBUG {"persist.sys.hilog.debug.on", &g_persistDebugLock}, // PROP_PERSIST_DEBUG {"hilog.loggable.global", &g_globalLevelLock}, // PROP_GLOBAL_LOG_LEVEL + {"persist.sys.hilog.loggable.global", &g_persistGlobalLevelLock}, // PROP_PERSIST_GLOBAL_LOG_LEVEL {"hilog.loggable.domain.", &g_domainLevelLock}, // PROP_DOMAIN_LOG_LEVEL + {"persist.sys.hilog.loggable.domain.", &g_persistDomainLevelLock}, // PROP_PERSIST_DOMAIN_LOG_LEVEL {"hilog.loggable.tag.", &g_tagLevelLock}, // PROP_TAG_LOG_LEVEL + {"persist.sys.hilog.loggable.tag.", &g_persistTagLevelLock}, // PROP_PERSIST_TAG_LOG_LEVEL {"hilog.flowctrl.domain.on", &g_domainFlowLock}, // PROP_DOMAIN_FLOWCTRL {"hilog.flowctrl.proc.on", &g_processFlowLock}, // PROP_PROCESS_FLOWCTRL @@ -326,31 +335,45 @@ bool IsDebuggableHap() return true; } +uint16_t GetGlobalLogLevel() +{ + uint16_t globalLevel = GetGlobalLevel(); + if (globalLevel == LOG_LEVEL_MIN) { + globalLevel = GetPersistGlobalLevel(); + } + return globalLevel; +} + uint16_t GetGlobalLevel() { static auto *logLevelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, PropType::PROP_GLOBAL_LOG_LEVEL); return logLevelCache->getValue(); } -uint16_t GetDomainLevel(uint32_t domain) +uint16_t GetPersistGlobalLevel() { - static auto *domainMap = new std::unordered_map(); - static shared_timed_mutex* mtx = new shared_timed_mutex; - std::decay::type::iterator it; + static auto *logLevelCache = + new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, PropType::PROP_PERSIST_GLOBAL_LOG_LEVEL); + return logLevelCache->getValue(); +} + +uint16_t GetLevel(std::unordered_map* map, uint32_t key, PropType propType) +{ + static shared_timed_mutex* levelMtx = new shared_timed_mutex; + std::decay::type::iterator it; { - ReadLock lock(*mtx); - it = domainMap->find(domain); - if (it != domainMap->end()) { + ReadLock lock(*levelMtx); + it = map->find(key); + if (it != map->end()) { LogLevelCache* levelCache = it->second; return levelCache->getValue(); } } - InsertLock lock(*mtx); - it = domainMap->find(domain); // secured for two thread went across above condition - if (it == domainMap->end()) { - LogLevelCache* levelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, - PropType::PROP_DOMAIN_LOG_LEVEL, Uint2HexStr(domain)); - auto result = domainMap->insert({ domain, levelCache }); + InsertLock lock(*levelMtx); + it = map->find(key); // secured for two thread went across above condition + if (it == map->end()) { + LogLevelCache* levelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, propType, Uint2HexStr(key)); + auto result = map->insert({ key, levelCache }); if (!result.second) { delete levelCache; return LOG_LEVEL_MIN; @@ -361,25 +384,23 @@ uint16_t GetDomainLevel(uint32_t domain) return levelCache->getValue(); } -uint16_t GetTagLevel(const string& tag) +uint16_t GetLevel(std::unordered_map* map, const string& key, PropType propType) { - static auto *tagMap = new std::unordered_map(); - static shared_timed_mutex* mtx = new shared_timed_mutex; - std::decay::type::iterator it; + static shared_timed_mutex* levelMtx = new shared_timed_mutex; + std::decay::type::iterator it; { - ReadLock lock(*mtx); - it = tagMap->find(tag); - if (it != tagMap->end()) { + ReadLock lock(*levelMtx); + it = map->find(key); + if (it != map->end()) { LogLevelCache* levelCache = it->second; return levelCache->getValue(); } } - InsertLock lock(*mtx); - it = tagMap->find(tag); // secured for two thread went across above condition - if (it == tagMap->end()) { - LogLevelCache* levelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, - PropType::PROP_TAG_LOG_LEVEL, tag); - auto result = tagMap->insert({ tag, levelCache }); + InsertLock lock(*levelMtx); + it = map->find(key); // secured for two thread went across above condition + if (it == map->end()) { + LogLevelCache* levelCache = new LogLevelCache(TextToLogLevel, LOG_LEVEL_MIN, propType, key); + auto result = map->insert({ key, levelCache }); if (!result.second) { delete levelCache; return LOG_LEVEL_MIN; @@ -390,6 +411,31 @@ uint16_t GetTagLevel(const string& tag) return levelCache->getValue(); } +uint16_t GetDomainLevel(uint32_t domain) +{ + static auto *domainMap = new std::unordered_map(); + return GetLevel(domainMap, domain, PropType::PROP_DOMAIN_LOG_LEVEL); +} + +uint16_t GetPersistDomainLevel(uint32_t domain) +{ + static auto *persistDomainMap = new std::unordered_map(); + return GetLevel(persistDomainMap, domain, PropType::PROP_PERSIST_DOMAIN_LOG_LEVEL); +} + +uint16_t GetTagLevel(const std::string& tag) +{ + static auto *tagMap = new std::unordered_map(); + return GetLevel(tagMap, tag, PropType::PROP_TAG_LOG_LEVEL); +} + +uint16_t GetPersistTagLevel(const std::string& tag) +{ + static auto *persistTagMap = new std::unordered_map(); + return GetLevel(persistTagMap, tag, PropType::PROP_PERSIST_TAG_LOG_LEVEL); +} + + bool IsProcessSwitchOn() { static auto *switchCache = new SwitchCache(TextToBool, false, PropType::PROP_PROCESS_FLOWCTRL); @@ -524,16 +570,31 @@ int SetGlobalLevel(uint16_t lvl) return SetLevel(PropType::PROP_GLOBAL_LOG_LEVEL, "", lvl); } +int SetPersistGlobalLevel(uint16_t lvl) +{ + return SetLevel(PropType::PROP_PERSIST_GLOBAL_LOG_LEVEL, "", lvl); +} + int SetTagLevel(const std::string& tag, uint16_t lvl) { return SetLevel(PropType::PROP_TAG_LOG_LEVEL, tag, lvl); } +int SetPersistTagLevel(const std::string& tag, uint16_t lvl) +{ + return SetLevel(PropType::PROP_PERSIST_TAG_LOG_LEVEL, tag, lvl); +} + int SetDomainLevel(uint32_t domain, uint16_t lvl) { return SetLevel(PropType::PROP_DOMAIN_LOG_LEVEL, Uint2HexStr(domain), lvl); } +int SetPersistDomainLevel(uint32_t domain, uint16_t lvl) +{ + return SetLevel(PropType::PROP_PERSIST_DOMAIN_LOG_LEVEL, Uint2HexStr(domain), lvl); +} + int SetProcessSwitchOn(bool on) { return SetBoolValue(PropType::PROP_PROCESS_FLOWCTRL, on); diff --git a/interfaces/native/innerkits/libhilog.map b/interfaces/native/innerkits/libhilog.map index 0312d454d1835a24dbaf0c14130cb6a10e3ce455..72e1a8e1215c3f5d2d2d6923a2ebd4021a18b850 100644 --- a/interfaces/native/innerkits/libhilog.map +++ b/interfaces/native/innerkits/libhilog.map @@ -46,9 +46,12 @@ "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::SetPersistGlobalLevel(unsigned short)"; "OHOS::HiviewDFX::SetDomainLevel(unsigned int, unsigned short)"; + "OHOS::HiviewDFX::SetPersistDomainLevel(unsigned int, unsigned short)"; "OHOS::HiviewDFX::Uint2HexStr(unsigned int)"; "OHOS::HiviewDFX::SetTagLevel(std::__h::basic_string, std::__h::allocator> const&, unsigned short)"; + "OHOS::HiviewDFX::SetPersistTagLevel(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)"; @@ -87,8 +90,11 @@ "OHOS::HiviewDFX::IsProcessSwitchOn()"; "OHOS::HiviewDFX::ShortStr2LogLevel(std::__h::basic_string, std::__h::allocator> const&)"; "OHOS::HiviewDFX::GetGlobalLevel()"; + "OHOS::HiviewDFX::GetPersistGlobalLevel()"; "OHOS::HiviewDFX::GetDomainLevel(unsigned int)"; + "OHOS::HiviewDFX::GetPersistDomainLevel(unsigned int)"; "OHOS::HiviewDFX::GetTagLevel(std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::HiviewDFX::GetPersistTagLevel(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)"; diff --git a/services/hilogd/etc/hilog.para b/services/hilogd/etc/hilog.para index 83c775eb3dce14f9c4466afdefe7a464ac80c05b..6a23f1e8e578d95197021671bccda800a03ad6e0 100644 --- a/services/hilogd/etc/hilog.para +++ b/services/hilogd/etc/hilog.para @@ -19,5 +19,5 @@ persist.sys.hilog.debug.on=false hilog.flowctrl.proc.on=false hilog.flowctrl.domain.on=false -hilog.loggable.global=I +persist.sys.hilog.loggable.global=I hilog.buffersize.global=262144 \ No newline at end of file diff --git a/services/hilogtool/main.cpp b/services/hilogtool/main.cpp index ddc77ccfe7e76eb9a0c0cab50b07a96bbae051be..63cd0c0ad681974b53c2b45b0656c8170457eb67 100644 --- a/services/hilogtool/main.cpp +++ b/services/hilogtool/main.cpp @@ -218,7 +218,11 @@ static void BaseLevelHelper() << " -T , --tag=" << endl << " Set specific tag loggable level." << endl << " The priority is: tag level > domain level > global level." << endl - << " **It's a temporary configuration, will be lost after reboot**" << endl; + << " **It's a temporary configuration, will be lost after reboot**" << endl + << " --persist" << endl + << " Set persist configuration." << endl + << " The priority is: tag level > persist tag level > domain level > persist domain level > global level" + " > persist global level." << endl; } static void DomainHelper() @@ -301,40 +305,35 @@ enum class ControlCmd { }; struct HilogArgs { - uint16_t headLines; - uint16_t baseLevel; - bool blackDomain; - int domainCount; - uint32_t domains[MAX_DOMAINS]; - string regex; - string fileName; - int32_t buffSize; - uint32_t jobId; - uint32_t fileSize; - uint16_t levels; - string stream; - uint16_t fileNum; - bool blackPid; - int pidCount; - uint32_t pids[MAX_PIDS]; - uint16_t types; - bool blackTag; - int tagCount; - string tags[MAX_TAGS]; - bool colorful; - FormatTime timeFormat; - FormatTimeAccu timeAccuFormat; - bool year; - bool zone; - bool wrap; - bool noBlock; - uint16_t tailLines; - - HilogArgs() : headLines (0), baseLevel(0), blackDomain(false), domainCount(0), domains { 0 }, regex(""), - fileName(""), buffSize(0), jobId(0), fileSize(0), levels(0), stream(""), fileNum(0), blackPid(false), - pidCount(0), pids { 0 }, types(0), blackTag(false), tagCount(0), tags { "" }, colorful(false), - timeFormat(FormatTime::INVALID), timeAccuFormat(FormatTimeAccu::INVALID), year(false), zone(false), - wrap(false), noBlock(false), tailLines(0) {} + uint16_t headLines = 0; + uint16_t baseLevel = 0; + bool blackDomain = false; + int domainCount = 0; + uint32_t domains[MAX_DOMAINS] = {0}; + string regex = ""; + string fileName = ""; + int32_t buffSize = 0; + uint32_t jobId = 0; + uint32_t fileSize = 0; + uint16_t levels = 0; + string stream = ""; + uint16_t fileNum = 0; + bool persist = false; + bool blackPid = false; + int pidCount = 0; + uint32_t pids[MAX_PIDS] = {0}; + uint16_t types = 0; + bool blackTag = false; + int tagCount = 0; + string tags[MAX_TAGS] = {""}; + bool colorful = false; + FormatTime timeFormat = FormatTime::INVALID; + FormatTimeAccu timeAccuFormat = FormatTimeAccu::INVALID; + bool year = false; + bool zone = false; + bool wrap = false; + bool noBlock = false; + uint16_t tailLines = 0; void ToOutputRqst(OutputRqst& rqst) { @@ -468,17 +467,30 @@ static int BaseLogLevelHandler(HilogArgs& context, const char *arg) if (context.domainCount == 0 && context.tagCount == 0) { ret = SetGlobalLevel(context.baseLevel); PrintResult(ret, (string("Set global log level to ") + arg)); + if (context.persist) { + ret = SetPersistGlobalLevel(context.baseLevel); + PrintResult(ret, (string("Set persist global log level to ") + arg)); + } } if (context.domainCount != 0) { for (int i = 0; i < context.domainCount; i++) { ret = SetDomainLevel(context.domains[i], context.baseLevel); PrintResult(ret, (string("Set domain 0x") + Uint2HexStr(context.domains[i]) + " log level to " + arg)); + if (context.persist) { + ret = SetPersistDomainLevel(context.domains[i], context.baseLevel); + PrintResult(ret, (string("Set persist domain 0x") + + Uint2HexStr(context.domains[i]) + " log level to " + arg)); + } } } if (context.tagCount != 0) { for (int i = 0; i < context.tagCount; i++) { ret = SetTagLevel(context.tags[i], context.baseLevel); PrintResult(ret, (string("Set tag ") + context.tags[i] + " log level to " + arg)); + if (context.persist) { + ret = SetPersistTagLevel(context.tags[i], context.baseLevel); + PrintResult(ret, (string("Set persist tag ") + context.tags[i] + " log level to " + arg)); + } } } return RET_SUCCESS; @@ -517,6 +529,12 @@ static int RegexHandler(HilogArgs& context, const char *arg) return RET_SUCCESS; } +static int PersistHandler(HilogArgs& context, const char *arg) +{ + context.persist = true; + return RET_SUCCESS; +} + static int FileNameHandler(HilogArgs& context, const char *arg) { context.fileName = arg; @@ -1002,6 +1020,7 @@ static OptEntry optEntries[] = { {'b', "baselevel", ControlCmd::CMD_LOGLEVEL_SET, BaseLogLevelHandler, true, 1}, {'D', "domain", ControlCmd::NOT_CMD, DomainHandler, true, 1}, {'e', "regex", ControlCmd::NOT_CMD, RegexHandler, true, 1}, + {0, "persist", ControlCmd::NOT_CMD, PersistHandler, false, 1}, {'f', "filename", ControlCmd::NOT_CMD, FileNameHandler, true, 1}, {'g', nullptr, ControlCmd::CMD_BUFFER_SIZE_QUERY, BufferSizeGetHandler, false, 1}, {'G', "buffer-size", ControlCmd::CMD_BUFFER_SIZE_SET, BufferSizeSetHandler, true, 1}, @@ -1034,13 +1053,12 @@ static void GetOpts(string& opts, struct option(&longOptions)[OPT_ENTRY_CNT]) opts = ""; int i; for (i = 0; i < OPT_ENTRY_CNT; i++) { - if (optEntries[i].opt == 0) { - break; - } - // opts - opts += optEntries[i].opt; - if (optEntries[i].needArg) { - opts += ':'; + if (optEntries[i].opt != 0) { + // opts + opts += optEntries[i].opt; + if (optEntries[i].needArg) { + opts += ':'; + } } // long option if (optEntries[i].longOpt == nullptr) { diff --git a/test/moduletest/common/adapter_test.cpp b/test/moduletest/common/adapter_test.cpp index c0e32693348ba0847f69412fd7ce1d9b3544af1d..b759d5bb8a9291df36628d9230d779944642ab6d 100644 --- a/test/moduletest/common/adapter_test.cpp +++ b/test/moduletest/common/adapter_test.cpp @@ -114,6 +114,38 @@ HWTEST_F(PropertiesTest, LevelTest, TestSize.Level1) } } +HWTEST_F(PropertiesTest, PersistLevelTest, TestSize.Level1) +{ + static const std::array charLevels = {"d", "D", "f", "F", "e", "E", "w", "W", "i", "I"}; + static const std::array expected = { + LOG_DEBUG, LOG_DEBUG, + LOG_FATAL, LOG_FATAL, + LOG_ERROR, LOG_ERROR, + LOG_WARN, LOG_WARN, + LOG_INFO, LOG_INFO, + }; + + for (size_t i = 0; i < charLevels.size(); ++i) { + SetPersistGlobalLevel(ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); + EXPECT_EQ(GetPersistGlobalLevel(), expected[i]); + } + + uint32_t domain = 12345; + for (size_t i = 0; i < charLevels.size(); ++i) { + SetPersistDomainLevel(domain, ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); + EXPECT_EQ(GetPersistDomainLevel(domain), expected[i]); + } + + std::string tag = "test_tag"; + for (size_t i = 0; i < charLevels.size(); ++i) { + SetPersistTagLevel(tag, ShortStr2LogLevel(charLevels[i])); + usleep(QUERY_INTERVAL); + EXPECT_EQ(GetPersistTagLevel(tag), expected[i]); + } +} + HWTEST_F(PropertiesTest, BufferTest, TestSize.Level1) { static const std::array logType = {-1, 0, 1, 3, 4, 5, 100};