util: Advanced filtering of the logging modules
refs: #3918
Change-Id: I766deb5ccd0d7f4472679d9955c8e55bad41f375
diff --git a/src/util/logging.cpp b/src/util/logging.cpp
index 06948c1..21a573c 100644
--- a/src/util/logging.cpp
+++ b/src/util/logging.cpp
@@ -25,6 +25,7 @@
#include <boost/log/expressions.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
+#include <boost/range/iterator_range.hpp>
#include <cstdlib>
#include <iostream>
@@ -65,18 +66,14 @@
std::lock_guard<std::mutex> lock(m_mutex);
const std::string& moduleName = logger.getModuleName();
- m_loggers.insert({moduleName, &logger});
+ m_loggers.emplace(moduleName, &logger);
- auto levelIt = m_enabledLevel.find(moduleName);
- if (levelIt == m_enabledLevel.end()) {
- levelIt = m_enabledLevel.find("*");
- }
- LogLevel level = levelIt == m_enabledLevel.end() ? INITIAL_DEFAULT_LEVEL : levelIt->second;
+ LogLevel level = findLevel(moduleName);
logger.setLevel(level);
}
std::set<std::string>
-Logging::getLoggerNamesImpl()
+Logging::getLoggerNamesImpl() const
{
std::lock_guard<std::mutex> lock(m_mutex);
@@ -85,6 +82,42 @@
return loggerNames;
}
+LogLevel
+Logging::findLevel(const std::string& moduleName) const
+{
+ std::string mn = moduleName;
+ while (!mn.empty()) {
+ auto it = m_enabledLevel.find(mn);
+ if (it != m_enabledLevel.end()) {
+ return it->second;
+ }
+ size_t pos = mn.find_last_of('.');
+ if (pos < mn.size() - 1) {
+ mn = mn.substr(0, pos + 1);
+ }
+ else if (pos == mn.size() - 1) {
+ mn.pop_back();
+ pos = mn.find_last_of('.');
+ if (pos != std::string::npos) {
+ mn = mn.substr(0, pos + 1);
+ }
+ else {
+ mn = "";
+ }
+ }
+ else {
+ mn = "";
+ }
+ }
+ auto it = m_enabledLevel.find(mn);
+ if (it != m_enabledLevel.end()) {
+ return it->second;
+ }
+ else {
+ return INITIAL_DEFAULT_LEVEL;
+ }
+}
+
#ifdef NDN_CXX_HAVE_TESTS
bool
Logging::removeLogger(Logger& logger)
@@ -102,30 +135,38 @@
#endif // NDN_CXX_HAVE_TESTS
void
-Logging::setLevelImpl(const std::string& moduleName, LogLevel level)
+Logging::setLevelImpl(const std::string& prefix, LogLevel level)
{
std::lock_guard<std::mutex> lock(m_mutex);
- if (moduleName == "*") {
- this->setDefaultLevel(level);
- return;
+ if (prefix.empty() || prefix.back() == '*') {
+ std::string p = prefix;
+ if (!p.empty()) {
+ p.pop_back();
+ }
+
+ for (auto i = m_enabledLevel.begin(); i != m_enabledLevel.end();) {
+ if (i->first.compare(0, p.size(), p) == 0) {
+ i = m_enabledLevel.erase(i);
+ }
+ else {
+ ++i;
+ }
+ }
+ m_enabledLevel[p] = level;
+
+ for (auto&& it : m_loggers) {
+ if (it.first.compare(0, p.size(), p) == 0) {
+ it.second->setLevel(level);
+ }
+ }
}
-
- m_enabledLevel[moduleName] = level;
- auto range = m_loggers.equal_range(moduleName);
- for (auto i = range.first; i != range.second; ++i) {
- i->second->setLevel(level);
- }
-}
-
-void
-Logging::setDefaultLevel(LogLevel level)
-{
- m_enabledLevel.clear();
- m_enabledLevel["*"] = level;
-
- for (auto i = m_loggers.begin(); i != m_loggers.end(); ++i) {
- i->second->setLevel(level);
+ else {
+ m_enabledLevel[prefix] = level;
+ auto range = boost::make_iterator_range(m_loggers.equal_range(prefix));
+ for (auto&& it : range) {
+ it.second->setLevel(level);
+ }
}
}
@@ -141,43 +182,16 @@
}
std::string moduleName = configModule.substr(0, ind);
- LogLevel level = parseLogLevel(configModule.substr(ind+1));
-
+ LogLevel level = parseLogLevel(configModule.substr(ind + 1));
this->setLevelImpl(moduleName, level);
}
}
#ifdef NDN_CXX_HAVE_TESTS
-std::string
-Logging::getLevels() const
-{
- std::ostringstream os;
-
- auto defaultLevelIt = m_enabledLevel.find("*");
- if (defaultLevelIt != m_enabledLevel.end()) {
- os << "*=" << defaultLevelIt->second << ':';
- }
-
- for (auto it = m_enabledLevel.begin(); it != m_enabledLevel.end(); ++it) {
- if (it->first == "*") {
- continue;
- }
- os << it->first << '=' << it->second << ':';
- }
-
- std::string s = os.str();
- if (!s.empty()) {
- s.pop_back(); // delete last ':'
- }
- return s;
-}
-#endif // NDN_CXX_HAVE_TESTS
-
-#ifdef NDN_CXX_HAVE_TESTS
void
Logging::resetLevels()
{
- this->setDefaultLevel(INITIAL_DEFAULT_LEVEL);
+ this->setLevelImpl("*", INITIAL_DEFAULT_LEVEL);
m_enabledLevel.clear();
}
#endif // NDN_CXX_HAVE_TESTS
@@ -193,11 +207,11 @@
{
std::lock_guard<std::mutex> lock(m_mutex);
- m_destination = os;
+ m_destination = std::move(os);
auto backend = boost::make_shared<boost::log::sinks::text_ostream_backend>();
backend->auto_flush(true);
- backend->add_stream(boost::shared_ptr<std::ostream>(os.get(), bind([]{})));
+ backend->add_stream(boost::shared_ptr<std::ostream>(m_destination.get(), bind([]{})));
if (m_sink != nullptr) {
boost::log::core::get()->remove_sink(m_sink);
@@ -212,10 +226,25 @@
#ifdef NDN_CXX_HAVE_TESTS
shared_ptr<std::ostream>
-Logging::getDestination()
+Logging::getDestination() const
{
return m_destination;
}
+
+void
+Logging::setLevelImpl(const std::unordered_map<std::string, LogLevel>& prefixRules)
+{
+ resetLevels();
+ for (const auto& rule : prefixRules) {
+ setLevelImpl(rule.first, rule.second);
+ }
+}
+
+const std::unordered_map<std::string, LogLevel>&
+Logging::getLevels() const
+{
+ return m_enabledLevel;
+}
#endif // NDN_CXX_HAVE_TESTS
void