blob: 20578c33063b604a48d25de762e2c88546352b12 [file] [log] [blame]
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev8269a052015-02-09 16:25:36 -08003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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"
27
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;
56}
57
58void
59LoggerFactory::setConfigFile(ConfigFile& config)
60{
61 config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
62}
63
64LogLevel
65LoggerFactory::parseLevel(const std::string& level)
66{
67 std::string upperLevel = level;
68 boost::to_upper(upperLevel);
69
70 // std::cerr << "parsing level: " << upperLevel << std::endl;;
71 // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
72 // std::cerr << m_levelNames.begin()->first << std::endl;
73
74 LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080075 if (levelIt != m_levelNames.end()) {
76 return levelIt->second;
77 }
78 try {
79 uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060080
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080081 if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
82 levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
83 levelNo == LOG_ALL) {
84 return static_cast<LogLevel>(levelNo);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060085 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080086 }
87 catch (const boost::bad_lexical_cast& error) {
88 }
89
90 throw LoggerFactory::Error("Unsupported logging level \"" + level + "\"");
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060091}
92
Alexander Afanasyev5959b012014-06-02 19:18:12 +030093LogLevel
94LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
95{
96 std::string levelString;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -080097 try {
98 levelString = item.get_value<std::string>();
99 }
100 catch (const boost::property_tree::ptree_error& error) {
101 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300102
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800103 if (levelString.empty()) {
104 throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
105 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300106
107 return parseLevel(levelString);
108}
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600109
110void
111LoggerFactory::onConfig(const ConfigSection& section,
112 bool isDryRun,
113 const std::string& filename)
114{
115// log
116// {
117// ; default_level specifies the logging level for modules
118// ; that are not explicitly named. All debugging levels
119// ; listed above the selected value are enabled.
120//
121// default_level INFO
122//
123// ; You may also override the default for specific modules:
124//
125// FibManager DEBUG
126// Forwarder WARN
127// }
128
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800129 if (!isDryRun) {
130 ConfigSection::const_assoc_iterator item = section.find("default_level");
131 if (item != section.not_found()) {
132 LogLevel level = extractLevel(item->second, "default_level");
133 setDefaultLevel(level);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300134 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800135 else {
136 setDefaultLevel(LOG_INFO);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600137 }
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800138 }
139
140 for (const auto& i : section) {
141 LogLevel level = extractLevel(i.second, i.first);
142
143 if (i.first == "default_level") {
144 // do nothing
145 }
146 else {
147 std::unique_lock<std::mutex> lock(m_loggersGuard);
148 LoggerMap::iterator loggerIt = m_loggers.find(i.first);
149 if (loggerIt == m_loggers.end()) {
150 lock.unlock();
151 NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
152 i.first << "\" (module not found)");
153 }
154 else if (!isDryRun) {
155 loggerIt->second.setLogLevel(level);
156 lock.unlock();
157 NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
158 }
159 }
160 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600161}
162
163void
164LoggerFactory::setDefaultLevel(LogLevel level)
165{
166 // std::cerr << "changing to default_level " << level << std::endl;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800167 std::lock_guard<std::mutex> lock(m_loggersGuard);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600168
169 m_defaultLevel = level;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800170 for (auto&& logger : m_loggers) {
171 // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
172 logger.second.setLogLevel(m_defaultLevel);
173 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600174}
175
176Logger&
177LoggerFactory::create(const std::string& moduleName)
178{
179 return LoggerFactory::getInstance().createLogger(moduleName);
180}
181
182Logger&
183LoggerFactory::createLogger(const std::string& moduleName)
184{
185 // std::cerr << "creating logger for " << moduleName
186 // << " with level " << m_defaultLevel << std::endl;
187
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800188 std::lock_guard<std::mutex> lock(m_loggersGuard);
189
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600190 std::pair<LoggerMap::iterator, bool> loggerIt =
191 m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
192
193 return loggerIt.first->second;
194}
195
196std::list<std::string>
197LoggerFactory::getModules() const
198{
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800199 std::lock_guard<std::mutex> lock(m_loggersGuard);
200
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600201 std::list<std::string> modules;
Alexander Afanasyev6b34ab92015-02-11 21:22:46 -0800202 for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
203 modules.push_back(loggerName);
204 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600205
206 return modules;
207}
208
209} // namespace nfd