logger-factory.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "logger-factory.hpp"
27 
28 #include <ndn-cxx/util/logging.hpp>
29 
30 #include <boost/algorithm/string/case_conv.hpp>
31 #include <boost/range/adaptor/map.hpp>
32 
33 #ifdef HAVE_CUSTOM_LOGGER
34 #error "This file should not be compiled when custom logger is used"
35 #endif
36 
37 namespace nfd {
38 
39 NFD_LOG_INIT("LoggerFactory");
40 
41 LoggerFactory&
43 {
44  static LoggerFactory globalLoggerFactory;
45 
46  return globalLoggerFactory;
47 }
48 
49 LoggerFactory::LoggerFactory()
50  : m_defaultLevel(LOG_INFO)
51 {
52  m_levelNames["NONE"] = LOG_NONE;
53  m_levelNames["ERROR"] = LOG_ERROR;
54  m_levelNames["WARN"] = LOG_WARN;
55  m_levelNames["INFO"] = LOG_INFO;
56  m_levelNames["DEBUG"] = LOG_DEBUG;
57  m_levelNames["TRACE"] = LOG_TRACE;
58  m_levelNames["ALL"] = LOG_ALL;
59 
60  // Let ndn-cxx logging facility initialize Boost.Log backend,
61  // so that only one sink is attached to Boost.Log core.
62  ndn::util::Logging::setDestination(std::clog);
63 }
64 
65 LoggerFactory::~LoggerFactory()
66 {
67  ndn::util::Logging::flush();
68 }
69 
70 void
72 {
73  config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
74 }
75 
77 LoggerFactory::parseLevel(const std::string& level)
78 {
79  std::string upperLevel = boost::to_upper_copy(level);
80 
81  // std::cerr << "parsing level: " << upperLevel << std::endl;;
82  // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
83  // std::cerr << m_levelNames.begin()->first << std::endl;
84 
85  LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
86  if (levelIt != m_levelNames.end()) {
87  return levelIt->second;
88  }
89  try {
90  uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
91 
92  if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
93  levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
94  levelNo == LOG_ALL) {
95  return static_cast<LogLevel>(levelNo);
96  }
97  }
98  catch (const boost::bad_lexical_cast& error) {
99  }
100 
101  BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
102 }
103 
104 LogLevel
105 LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
106 {
107  std::string levelString;
108  try {
109  levelString = item.get_value<std::string>();
110  }
111  catch (const boost::property_tree::ptree_error& error) {
112  }
113 
114  if (levelString.empty()) {
115  BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
116  }
117 
118  return parseLevel(levelString);
119 }
120 
121 void
123  bool isDryRun,
124  const std::string& filename)
125 {
126  // log
127  // {
128  // ; default_level specifies the logging level for modules
129  // ; that are not explicitly named. All debugging levels
130  // ; listed above the selected value are enabled.
131  //
132  // default_level INFO
133  //
134  // ; You may also override the default for specific modules:
135  //
136  // FibManager DEBUG
137  // Forwarder WARN
138  // }
139 
140  if (!isDryRun) {
141  ConfigSection::const_assoc_iterator item = section.find("default_level");
142  if (item != section.not_found()) {
143  LogLevel level = extractLevel(item->second, "default_level");
144  setDefaultLevel(level);
145  }
146  else {
147  setDefaultLevel(LOG_INFO);
148  }
149  }
150 
151  for (const auto& i : section) {
152  LogLevel level = extractLevel(i.second, i.first);
153 
154  if (i.first == "default_level") {
155  // do nothing
156  }
157  else {
158  std::unique_lock<std::mutex> lock(m_loggersGuard);
159  LoggerMap::iterator loggerIt = m_loggers.find(i.first);
160  if (loggerIt == m_loggers.end()) {
161  lock.unlock();
162  NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
163  i.first << "\" (module not found)");
164  }
165  else if (!isDryRun) {
166  loggerIt->second.setLogLevel(level);
167  lock.unlock();
168  NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
169  }
170  }
171  }
172 }
173 
174 void
175 LoggerFactory::setDefaultLevel(LogLevel level)
176 {
177  // std::cerr << "changing to default_level " << level << std::endl;
178  std::lock_guard<std::mutex> lock(m_loggersGuard);
179 
180  m_defaultLevel = level;
181  for (auto&& logger : m_loggers) {
182  // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
183  logger.second.setLogLevel(m_defaultLevel);
184  }
185 }
186 
187 void
188 LoggerFactory::flushBackend()
189 {
190  ndn::util::Logging::flush();
191 }
192 
193 Logger&
194 LoggerFactory::create(const std::string& moduleName)
195 {
196  return LoggerFactory::getInstance().createLogger(moduleName);
197 }
198 
199 Logger&
200 LoggerFactory::createLogger(const std::string& moduleName)
201 {
202  // std::cerr << "creating logger for " << moduleName
203  // << " with level " << m_defaultLevel << std::endl;
204 
205  std::lock_guard<std::mutex> lock(m_loggersGuard);
206 
207  std::pair<LoggerMap::iterator, bool> loggerIt =
208  m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
209 
210  return loggerIt.first->second;
211 }
212 
213 std::list<std::string>
215 {
216  std::lock_guard<std::mutex> lock(m_loggersGuard);
217 
218  std::list<std::string> modules;
219  for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
220  modules.push_back(loggerName);
221  }
222 
223  return modules;
224 }
225 
226 } // namespace nfd
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:79
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:161
configuration file parsing utility
Definition: config-file.hpp:58
void setConfigFile(ConfigFile &config)
void onConfig(const ConfigSection &section, bool isDryRun, const std::string &filename)
static LoggerFactory & getInstance()
Table::const_iterator iterator
Definition: cs-internal.hpp:41
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
boost::property_tree::ptree ConfigSection
a config file section
Definition: config-file.hpp:37
static Logger & create(const std::string &moduleName)
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
LogLevel
indicates a log level
Definition: logger.hpp:42
provides logging for a module
Definition: logger.hpp:58
std::list< std::string > getModules() const