25 #include <boost/log/expressions.hpp> 26 #include <boost/range/adaptor/map.hpp> 27 #include <boost/range/algorithm/copy.hpp> 28 #include <boost/range/iterator_range.hpp> 36 #pragma clang diagnostic ignored "-Wundefined-func-template" 55 this->setDestinationImpl(shared_ptr<std::ostream>(&std::clog, bind([]{})));
57 const char* environ = std::getenv(
"NDN_LOG");
58 if (environ !=
nullptr) {
59 this->setLevelImpl(environ);
64 Logging::addLoggerImpl(
Logger& logger)
66 std::lock_guard<std::mutex> lock(m_mutex);
69 m_loggers.emplace(moduleName, &logger);
71 LogLevel level = findLevel(moduleName);
76 Logging::getLoggerNamesImpl()
const 78 std::lock_guard<std::mutex> lock(m_mutex);
80 std::set<std::string> loggerNames;
81 boost::copy(m_loggers | boost::adaptors::map_keys, std::inserter(loggerNames, loggerNames.end()));
86 Logging::findLevel(
const std::string& moduleName)
const 88 std::string mn = moduleName;
90 auto it = m_enabledLevel.find(mn);
91 if (it != m_enabledLevel.end()) {
94 size_t pos = mn.find_last_of(
'.');
95 if (pos < mn.size() - 1) {
96 mn = mn.substr(0, pos + 1);
98 else if (pos == mn.size() - 1) {
100 pos = mn.find_last_of(
'.');
101 if (pos != std::string::npos) {
102 mn = mn.substr(0, pos + 1);
112 auto it = m_enabledLevel.find(mn);
113 if (it != m_enabledLevel.end()) {
121 #ifdef NDN_CXX_HAVE_TESTS 123 Logging::removeLogger(
Logger& logger)
126 auto range = m_loggers.equal_range(moduleName);
127 for (
auto i = range.first; i != range.second; ++i) {
128 if (i->second == &logger) {
135 #endif // NDN_CXX_HAVE_TESTS 138 Logging::setLevelImpl(
const std::string& prefix,
LogLevel level)
140 std::lock_guard<std::mutex> lock(m_mutex);
142 if (prefix.empty() || prefix.back() ==
'*') {
143 std::string p = prefix;
148 for (
auto i = m_enabledLevel.begin(); i != m_enabledLevel.end();) {
149 if (i->first.compare(0, p.size(), p) == 0) {
150 i = m_enabledLevel.erase(i);
156 m_enabledLevel[p] = level;
158 for (
auto&& it : m_loggers) {
159 if (it.first.compare(0, p.size(), p) == 0) {
160 it.second->setLevel(level);
165 m_enabledLevel[prefix] = level;
166 auto range = boost::make_iterator_range(m_loggers.equal_range(prefix));
167 for (
auto&& it : range) {
168 it.second->setLevel(level);
174 Logging::setLevelImpl(
const std::string& config)
176 std::stringstream ss(config);
177 std::string configModule;
178 while (std::getline(ss, configModule,
':')) {
179 size_t ind = configModule.find(
'=');
180 if (ind == std::string::npos) {
181 BOOST_THROW_EXCEPTION(std::invalid_argument(
"malformed logging config: '=' is missing"));
184 std::string moduleName = configModule.substr(0, ind);
186 this->setLevelImpl(moduleName, level);
190 #ifdef NDN_CXX_HAVE_TESTS 192 Logging::resetLevels()
194 this->setLevelImpl(
"*", INITIAL_DEFAULT_LEVEL);
195 m_enabledLevel.clear();
197 #endif // NDN_CXX_HAVE_TESTS 206 Logging::setDestinationImpl(shared_ptr<std::ostream> os)
208 std::lock_guard<std::mutex> lock(m_mutex);
210 m_destination = std::move(os);
212 auto backend = boost::make_shared<boost::log::sinks::text_ostream_backend>();
213 backend->auto_flush(
true);
214 backend->add_stream(boost::shared_ptr<std::ostream>(m_destination.get(), bind([]{})));
216 if (m_sink !=
nullptr) {
217 boost::log::core::get()->remove_sink(m_sink);
222 m_sink = boost::make_shared<Sink>(backend);
223 m_sink->set_formatter(boost::log::expressions::stream << boost::log::expressions::message);
224 boost::log::core::get()->add_sink(m_sink);
227 #ifdef NDN_CXX_HAVE_TESTS 228 shared_ptr<std::ostream>
229 Logging::getDestination()
const 231 return m_destination;
235 Logging::setLevelImpl(
const std::unordered_map<std::string, LogLevel>& prefixRules)
238 for (
const auto& rule : prefixRules) {
239 setLevelImpl(rule.first, rule.second);
243 const std::unordered_map<std::string, LogLevel>&
244 Logging::getLevels()
const 246 return m_enabledLevel;
248 #endif // NDN_CXX_HAVE_TESTS controls the logging facility
Copyright (c) 2013-2017 Regents of the University of California.
static void setDestination(shared_ptr< std::ostream > os)
set log destination
LogLevel
indicates the severity level of a log message
LogLevel parseLogLevel(const std::string &s)
parse LogLevel from string
static const LogLevel INITIAL_DEFAULT_LEVEL
represents a logger in logging facility
const std::string & getModuleName() const
void setLevel(LogLevel level)