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