blob: 215b0874be55c977f04581aadeae654848e8ec50 [file] [log] [blame]
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa997d292017-08-24 20:16:59 -04002/*
3 * Copyright (c) 2014-2017, 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
Davide Pesaventoa997d292017-08-24 20:16:59 -040033#include <iostream>
34
Alexander Afanasyev8269a052015-02-09 16:25:36 -080035#ifdef HAVE_CUSTOM_LOGGER
36#error "This file should not be compiled when custom logger is used"
37#endif
38
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060039namespace nfd {
40
Steve DiBenedetto6ad48ca2014-04-22 09:39:31 -060041NFD_LOG_INIT("LoggerFactory");
42
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060043LoggerFactory&
44LoggerFactory::getInstance()
45{
46 static LoggerFactory globalLoggerFactory;
47
48 return globalLoggerFactory;
49}
50
51LoggerFactory::LoggerFactory()
52 : m_defaultLevel(LOG_INFO)
53{
54 m_levelNames["NONE"] = LOG_NONE;
55 m_levelNames["ERROR"] = LOG_ERROR;
56 m_levelNames["WARN"] = LOG_WARN;
57 m_levelNames["INFO"] = LOG_INFO;
58 m_levelNames["DEBUG"] = LOG_DEBUG;
59 m_levelNames["TRACE"] = LOG_TRACE;
60 m_levelNames["ALL"] = LOG_ALL;
Yumin Xiaab497452016-05-10 20:23:24 +080061
Alexander Afanasyev6459e642016-09-12 04:07:33 +000062 // Let ndn-cxx logging facility initialize Boost.Log backend,
63 // so that only one sink is attached to Boost.Log core.
64 ndn::util::Logging::setDestination(std::clog);
Yumin Xiaab497452016-05-10 20:23:24 +080065}
66
67LoggerFactory::~LoggerFactory()
68{
Alexander Afanasyev6459e642016-09-12 04:07:33 +000069 ndn::util::Logging::flush();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060070}
71
72void
73LoggerFactory::setConfigFile(ConfigFile& config)
74{
75 config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
76}
77
78LogLevel
79LoggerFactory::parseLevel(const std::string& level)
80{
Davide Pesavento89567d32016-11-19 16:39:45 +010081 std::string upperLevel = boost::to_upper_copy(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060082
83 // std::cerr << "parsing level: " << upperLevel << std::endl;;
84 // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
85 // std::cerr << m_levelNames.begin()->first << std::endl;
86
87 LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080088 if (levelIt != m_levelNames.end()) {
89 return levelIt->second;
90 }
91 try {
92 uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060093
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080094 if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
95 levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
96 levelNo == LOG_ALL) {
97 return static_cast<LogLevel>(levelNo);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060098 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080099 }
100 catch (const boost::bad_lexical_cast& error) {
101 }
102
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700103 BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600104}
105
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300106LogLevel
107LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
108{
109 std::string levelString;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800110 try {
111 levelString = item.get_value<std::string>();
112 }
113 catch (const boost::property_tree::ptree_error& error) {
114 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300115
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800116 if (levelString.empty()) {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700117 BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800118 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300119
120 return parseLevel(levelString);
121}
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600122
123void
124LoggerFactory::onConfig(const ConfigSection& section,
125 bool isDryRun,
126 const std::string& filename)
127{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000128 // log
129 // {
130 // ; default_level specifies the logging level for modules
131 // ; that are not explicitly named. All debugging levels
132 // ; listed above the selected value are enabled.
133 //
134 // default_level INFO
135 //
136 // ; You may also override the default for specific modules:
137 //
138 // FibManager DEBUG
139 // Forwarder WARN
140 // }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600141
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800142 if (!isDryRun) {
143 ConfigSection::const_assoc_iterator item = section.find("default_level");
144 if (item != section.not_found()) {
145 LogLevel level = extractLevel(item->second, "default_level");
146 setDefaultLevel(level);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300147 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800148 else {
149 setDefaultLevel(LOG_INFO);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600150 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800151 }
152
153 for (const auto& i : section) {
154 LogLevel level = extractLevel(i.second, i.first);
155
156 if (i.first == "default_level") {
157 // do nothing
158 }
159 else {
160 std::unique_lock<std::mutex> lock(m_loggersGuard);
161 LoggerMap::iterator loggerIt = m_loggers.find(i.first);
162 if (loggerIt == m_loggers.end()) {
163 lock.unlock();
164 NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
165 i.first << "\" (module not found)");
166 }
167 else if (!isDryRun) {
168 loggerIt->second.setLogLevel(level);
169 lock.unlock();
170 NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
171 }
172 }
173 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600174}
175
176void
177LoggerFactory::setDefaultLevel(LogLevel level)
178{
179 // std::cerr << "changing to default_level " << level << std::endl;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800180 std::lock_guard<std::mutex> lock(m_loggersGuard);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600181
182 m_defaultLevel = level;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800183 for (auto&& logger : m_loggers) {
184 // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
185 logger.second.setLogLevel(m_defaultLevel);
186 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600187}
188
Yumin Xiaab497452016-05-10 20:23:24 +0800189void
190LoggerFactory::flushBackend()
191{
Alexander Afanasyev6459e642016-09-12 04:07:33 +0000192 ndn::util::Logging::flush();
Yumin Xiaab497452016-05-10 20:23:24 +0800193}
194
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600195Logger&
196LoggerFactory::create(const std::string& moduleName)
197{
198 return LoggerFactory::getInstance().createLogger(moduleName);
199}
200
201Logger&
202LoggerFactory::createLogger(const std::string& moduleName)
203{
204 // std::cerr << "creating logger for " << moduleName
205 // << " with level " << m_defaultLevel << std::endl;
206
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800207 std::lock_guard<std::mutex> lock(m_loggersGuard);
208
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600209 std::pair<LoggerMap::iterator, bool> loggerIt =
210 m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
211
212 return loggerIt.first->second;
213}
214
215std::list<std::string>
216LoggerFactory::getModules() const
217{
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800218 std::lock_guard<std::mutex> lock(m_loggersGuard);
219
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600220 std::list<std::string> modules;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800221 for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
222 modules.push_back(loggerName);
223 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600224
225 return modules;
226}
227
228} // namespace nfd