blob: 36ce5b3117cf9c25e68b292cbce18a6ccd619e6d [file] [log] [blame]
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yumin Xiaab497452016-05-10 20:23:24 +08003 * Copyright (c) 2014-2016, Regents of the University of California,
Alexander Afanasyev8269a052015-02-09 16:25:36 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Alexander Afanasyev8269a052015-02-09 16:25:36 -080024 */
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060025
26#include "logger-factory.hpp"
Alexander Afanasyev6459e642016-09-12 04:07:33 +000027#include <ndn-cxx/util/logging.hpp>
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080028#include <boost/range/adaptor/map.hpp>
29
Alexander Afanasyev8269a052015-02-09 16:25:36 -080030#ifdef HAVE_CUSTOM_LOGGER
31#error "This file should not be compiled when custom logger is used"
32#endif
33
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060034namespace nfd {
35
Steve DiBenedetto6ad48ca2014-04-22 09:39:31 -060036NFD_LOG_INIT("LoggerFactory");
37
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060038LoggerFactory&
39LoggerFactory::getInstance()
40{
41 static LoggerFactory globalLoggerFactory;
42
43 return globalLoggerFactory;
44}
45
46LoggerFactory::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;
Yumin Xiaab497452016-05-10 20:23:24 +080056
Alexander Afanasyev6459e642016-09-12 04:07:33 +000057 // 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);
Yumin Xiaab497452016-05-10 20:23:24 +080060}
61
62LoggerFactory::~LoggerFactory()
63{
Alexander Afanasyev6459e642016-09-12 04:07:33 +000064 ndn::util::Logging::flush();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060065}
66
67void
68LoggerFactory::setConfigFile(ConfigFile& config)
69{
70 config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
71}
72
73LogLevel
74LoggerFactory::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);
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080084 if (levelIt != m_levelNames.end()) {
85 return levelIt->second;
86 }
87 try {
88 uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060089
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080090 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);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060094 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080095 }
96 catch (const boost::bad_lexical_cast& error) {
97 }
98
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -070099 BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600100}
101
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300102LogLevel
103LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
104{
105 std::string levelString;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800106 try {
107 levelString = item.get_value<std::string>();
108 }
109 catch (const boost::property_tree::ptree_error& error) {
110 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300111
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800112 if (levelString.empty()) {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700113 BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800114 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300115
116 return parseLevel(levelString);
117}
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600118
119void
120LoggerFactory::onConfig(const ConfigSection& section,
121 bool isDryRun,
122 const std::string& filename)
123{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000124 // 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 // }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600137
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800138 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);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300143 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800144 else {
145 setDefaultLevel(LOG_INFO);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600146 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800147 }
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 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600170}
171
172void
173LoggerFactory::setDefaultLevel(LogLevel level)
174{
175 // std::cerr << "changing to default_level " << level << std::endl;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800176 std::lock_guard<std::mutex> lock(m_loggersGuard);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600177
178 m_defaultLevel = level;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800179 for (auto&& logger : m_loggers) {
180 // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
181 logger.second.setLogLevel(m_defaultLevel);
182 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600183}
184
Yumin Xiaab497452016-05-10 20:23:24 +0800185void
186LoggerFactory::flushBackend()
187{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000188 ndn::util::Logging::flush();
Yumin Xiaab497452016-05-10 20:23:24 +0800189}
190
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600191Logger&
192LoggerFactory::create(const std::string& moduleName)
193{
194 return LoggerFactory::getInstance().createLogger(moduleName);
195}
196
197Logger&
198LoggerFactory::createLogger(const std::string& moduleName)
199{
200 // std::cerr << "creating logger for " << moduleName
201 // << " with level " << m_defaultLevel << std::endl;
202
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800203 std::lock_guard<std::mutex> lock(m_loggersGuard);
204
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600205 std::pair<LoggerMap::iterator, bool> loggerIt =
206 m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
207
208 return loggerIt.first->second;
209}
210
211std::list<std::string>
212LoggerFactory::getModules() const
213{
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800214 std::lock_guard<std::mutex> lock(m_loggersGuard);
215
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600216 std::list<std::string> modules;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800217 for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
218 modules.push_back(loggerName);
219 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600220
221 return modules;
222}
223
224} // namespace nfd