26 #include <boost/log/attributes/function.hpp>    27 #include <boost/log/expressions.hpp>    28 #include <boost/log/expressions/attr.hpp>    29 #include <boost/log/expressions/formatters/date_time.hpp>    30 #include <boost/log/support/date_time.hpp>    31 #include <boost/range/adaptor/map.hpp>    32 #include <boost/range/algorithm/copy.hpp>    33 #include <boost/range/iterator_range.hpp>    43 #pragma clang diagnostic ignored "-Wundefined-func-template"    55   const auto sinceEpoch = system_clock::now().time_since_epoch();
    56   BOOST_ASSERT(sinceEpoch.count() >= 0);
    58   const auto usecs = 
std::abs(duration_cast<microseconds>(sinceEpoch).count());
    59   const auto usecsPerSec = microseconds::period::den;
    62   std::string buffer(10 + 1 + 6 + 1, 
'\0'); 
    63   BOOST_ASSERT_MSG(usecs / usecsPerSec <= 9999999999, 
"whole seconds cannot fit in 10 characters");
    65   static_assert(std::is_same<microseconds::rep, int_least64_t>::value,
    66                 "PRIdLEAST64 is incompatible with microseconds::rep");
    68   ::snprintf(&buffer.front(), buffer.size(), 
"%" PRIdLEAST64 
".%06" PRIdLEAST64,
    69              usecs / usecsPerSec, usecs % usecsPerSec);
    76 BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, 
"Timestamp", std::string)
    94   auto destination = makeDefaultStreamDestination(shared_ptr<std::ostream>(&std::clog, [] (
auto) {}));
    95   this->setDestinationImpl(
std::move(destination));
    97   const char* environ = std::getenv(
"NDN_LOG");
    98   if (environ != 
nullptr) {
    99     this->setLevelImpl(environ);
   106 Logging::addLoggerImpl(
Logger& logger)
   108   std::lock_guard<std::mutex> lock(m_mutex);
   111   m_loggers.emplace(moduleName, &logger);
   113   logger.
setLevel(findLevel(moduleName));
   117 Logging::registerLoggerNameImpl(std::string name)
   119   std::lock_guard<std::mutex> lock(m_mutex);
   120   m_loggers.emplace(
std::move(name), 
nullptr);
   123 std::set<std::string>
   124 Logging::getLoggerNamesImpl()
 const   126   std::lock_guard<std::mutex> lock(m_mutex);
   128   std::set<std::string> loggerNames;
   129   boost::copy(m_loggers | boost::adaptors::map_keys, std::inserter(loggerNames, loggerNames.end()));
   134 Logging::findLevel(std::string mn)
 const   136   while (!mn.empty()) {
   137     auto it = m_enabledLevel.find(mn);
   138     if (it != m_enabledLevel.end()) {
   141     size_t pos = mn.find_last_of(
'.');
   142     if (pos < mn.size() - 1) {
   143       mn = mn.substr(0, pos + 1);
   145     else if (pos == mn.size() - 1) {
   147       pos = mn.find_last_of(
'.');
   148       if (pos != std::string::npos) {
   149         mn = mn.substr(0, pos + 1);
   160   auto it = m_enabledLevel.find(mn);
   164 #ifdef NDN_CXX_HAVE_TESTS   166 Logging::removeLogger(
Logger& logger)
   169   auto range = m_loggers.equal_range(moduleName);
   170   for (
auto i = range.first; i != range.second; ++i) {
   171     if (i->second == &logger) {
   178 #endif // NDN_CXX_HAVE_TESTS   181 Logging::setLevelImpl(
const std::string& prefix, 
LogLevel level)
   183   std::lock_guard<std::mutex> lock(m_mutex);
   185   if (prefix.empty() || prefix.back() == 
'*') {
   186     std::string p = prefix;
   191     for (
auto i = m_enabledLevel.begin(); i != m_enabledLevel.end();) {
   192       if (i->first.compare(0, p.size(), p) == 0) {
   193         i = m_enabledLevel.erase(i);
   199     m_enabledLevel[p] = level;
   201     for (
const auto& pair : m_loggers) {
   202       if (pair.first.compare(0, p.size(), p) == 0 && pair.second != 
nullptr) {
   203         pair.second->setLevel(level);
   208     m_enabledLevel[prefix] = level;
   209     auto range = boost::make_iterator_range(m_loggers.equal_range(prefix));
   210     for (
const auto& pair : range) {
   211       if (pair.second != 
nullptr) {
   212         pair.second->setLevel(level);
   219 Logging::setLevelImpl(
const std::string& config)
   221   std::stringstream ss(config);
   222   std::string configModule;
   223   while (std::getline(ss, configModule, 
':')) {
   224     size_t ind = configModule.find(
'=');
   225     if (ind == std::string::npos) {
   226       NDN_THROW(std::invalid_argument(
"malformed logging config: '=' is missing"));
   229     std::string moduleName = configModule.substr(0, ind);
   231     this->setLevelImpl(moduleName, level);
   235 #ifdef NDN_CXX_HAVE_TESTS   237 Logging::resetLevels()
   239   this->setLevelImpl(
"*", INITIAL_DEFAULT_LEVEL);
   240   m_enabledLevel.clear();
   242 #endif // NDN_CXX_HAVE_TESTS   247   auto destination = makeDefaultStreamDestination(shared_ptr<std::ostream>(&os, [] (
auto) {}));
   251 class TextOstreamBackend : 
public boost::log::sinks::text_ostream_backend
   254   TextOstreamBackend(std::shared_ptr<std::ostream> os)
   258     add_stream(boost::shared_ptr<std::ostream>(m_stdPtr.get(), [] (
auto) {}));
   264   std::shared_ptr<std::ostream> m_stdPtr;
   267 boost::shared_ptr<boost::log::sinks::sink>
   270   auto backend = boost::make_shared<TextOstreamBackend>(
std::move(os));
   271   auto destination = boost::make_shared<boost::log::sinks::asynchronous_sink<TextOstreamBackend>>(backend);
   273   namespace expr = boost::log::expressions;
   274   destination->set_formatter(expr::stream
   275                              << expr::attr<std::string>(log::timestamp.get_name())
   276                              << 
" " << std::setw(5) << expr::attr<LogLevel>(log::severity.get_name()) << 
": "   277                              << 
"[" << expr::attr<std::string>(log::module.get_name()) << 
"] "   283 Logging::setDestinationImpl(boost::shared_ptr<boost::log::sinks::sink> destination)
   285   std::lock_guard<std::mutex> lock(m_mutex);
   287   if (destination == m_destination) {
   291   if (m_destination != 
nullptr) {
   293     m_destination->flush();
   298   if (m_destination != 
nullptr) {
   303 #ifdef NDN_CXX_HAVE_TESTS   304 boost::shared_ptr<boost::log::sinks::sink>
   305 Logging::getDestination()
 const   307   return m_destination;
   311 Logging::setLevelImpl(
const std::unordered_map<std::string, LogLevel>& prefixRules)
   314   for (
const auto& rule : prefixRules) {
   315     setLevelImpl(rule.first, rule.second);
   319 const std::unordered_map<std::string, LogLevel>&
   320 Logging::getLevels()
 const   322   return m_enabledLevel;
   324 #endif // NDN_CXX_HAVE_TESTS   329   std::lock_guard<std::mutex> lock(m_mutex);
   331   if (m_destination != 
nullptr) {
   332     m_destination->flush();
 Controls the logging facility. 
constexpr duration< Rep, Period > abs(duration< Rep, Period > d)
LogLevel
Indicates the severity level of a log message. 
R & get(variant< T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 > &v, nonstd::in_place_t(&)(nonstd::detail::in_place_type_tag< R >)=nonstd::in_place_type< R >)
static std::string makeTimestamp()
LogLevel parseLogLevel(const std::string &s)
Parse LogLevel from a string. 
static boost::shared_ptr< boost::log::sinks::sink > makeDefaultStreamDestination(shared_ptr< std::ostream > os)
Create stream log destination using default formatting. 
static const LogLevel INITIAL_DEFAULT_LEVEL
const std::string & getModuleName() const
Represents a log module in the logging facility. 
static void setDestination(boost::shared_ptr< boost::log::sinks::sink > destination)
Set or replace log destination. 
void setLevel(LogLevel level)