blob: 3c419f168ddee4afecae52a4c24f394e8ce44267 [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"
Davide Pesavento89567d32016-11-19 16:39:45 +010027
Alexander Afanasyev6459e642016-09-12 04:07:33 +000028#include <ndn-cxx/util/logging.hpp>
Davide Pesavento89567d32016-11-19 16:39:45 +010029
30#include <boost/algorithm/string/case_conv.hpp>
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080031#include <boost/range/adaptor/map.hpp>
32
Alexander Afanasyev8269a052015-02-09 16:25:36 -080033#ifdef HAVE_CUSTOM_LOGGER
34#error "This file should not be compiled when custom logger is used"
35#endif
36
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060037namespace nfd {
38
Steve DiBenedetto6ad48ca2014-04-22 09:39:31 -060039NFD_LOG_INIT("LoggerFactory");
40
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060041LoggerFactory&
42LoggerFactory::getInstance()
43{
44 static LoggerFactory globalLoggerFactory;
45
46 return globalLoggerFactory;
47}
48
49LoggerFactory::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;
Yumin Xiaab497452016-05-10 20:23:24 +080059
Alexander Afanasyev6459e642016-09-12 04:07:33 +000060 // 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);
Yumin Xiaab497452016-05-10 20:23:24 +080063}
64
65LoggerFactory::~LoggerFactory()
66{
Alexander Afanasyev6459e642016-09-12 04:07:33 +000067 ndn::util::Logging::flush();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060068}
69
70void
71LoggerFactory::setConfigFile(ConfigFile& config)
72{
73 config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
74}
75
76LogLevel
77LoggerFactory::parseLevel(const std::string& level)
78{
Davide Pesavento89567d32016-11-19 16:39:45 +010079 std::string upperLevel = boost::to_upper_copy(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060080
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);
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080086 if (levelIt != m_levelNames.end()) {
87 return levelIt->second;
88 }
89 try {
90 uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060091
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080092 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);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060096 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080097 }
98 catch (const boost::bad_lexical_cast& error) {
99 }
100
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700101 BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600102}
103
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300104LogLevel
105LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
106{
107 std::string levelString;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800108 try {
109 levelString = item.get_value<std::string>();
110 }
111 catch (const boost::property_tree::ptree_error& error) {
112 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300113
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800114 if (levelString.empty()) {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700115 BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800116 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300117
118 return parseLevel(levelString);
119}
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600120
121void
122LoggerFactory::onConfig(const ConfigSection& section,
123 bool isDryRun,
124 const std::string& filename)
125{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000126 // 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 // }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600139
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800140 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);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300145 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800146 else {
147 setDefaultLevel(LOG_INFO);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600148 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800149 }
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 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600172}
173
174void
175LoggerFactory::setDefaultLevel(LogLevel level)
176{
177 // std::cerr << "changing to default_level " << level << std::endl;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800178 std::lock_guard<std::mutex> lock(m_loggersGuard);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600179
180 m_defaultLevel = level;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800181 for (auto&& logger : m_loggers) {
182 // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
183 logger.second.setLogLevel(m_defaultLevel);
184 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600185}
186
Yumin Xiaab497452016-05-10 20:23:24 +0800187void
188LoggerFactory::flushBackend()
189{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000190 ndn::util::Logging::flush();
Yumin Xiaab497452016-05-10 20:23:24 +0800191}
192
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600193Logger&
194LoggerFactory::create(const std::string& moduleName)
195{
196 return LoggerFactory::getInstance().createLogger(moduleName);
197}
198
199Logger&
200LoggerFactory::createLogger(const std::string& moduleName)
201{
202 // std::cerr << "creating logger for " << moduleName
203 // << " with level " << m_defaultLevel << std::endl;
204
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800205 std::lock_guard<std::mutex> lock(m_loggersGuard);
206
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600207 std::pair<LoggerMap::iterator, bool> loggerIt =
208 m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
209
210 return loggerIt.first->second;
211}
212
213std::list<std::string>
214LoggerFactory::getModules() const
215{
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800216 std::lock_guard<std::mutex> lock(m_loggersGuard);
217
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600218 std::list<std::string> modules;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800219 for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
220 modules.push_back(loggerName);
221 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600222
223 return modules;
224}
225
226} // namespace nfd