【问题标题】:Check boost::log filter explicitly?明确检查 boost::log 过滤器?
【发布时间】:2018-05-15 06:58:46
【问题描述】:

我有一些琐碎的日志记录:

BOOST_LOG_TRIVIAL(trace) << make_trace_record();

现在make_trace_record 是一个调用起来有点昂贵的函数(不要问为什么,它很复杂)。我只想在日志当前通过过滤时调用它。我怎样才能做到这一点?我没有看到显式调用严重性过滤器的方法。

【问题讨论】:

    标签: c++ c++11 boost boost-log


    【解决方案1】:

    Boost.Log 过滤器;因此,如果严重性不够高,make_trace_record() 将不会被调用。

    为了设置普通记录器的严重性过滤器,调用:

    boost::log::core::get()->set_filter(
        boost::log::trivial::severity >= boost::log::trivial::...
    );
    

    例如,下面的例子输出1,表明expensive()只被调用了一次:

    Live On Coliru

    #include <iostream>
    
    #include <boost/log/expressions.hpp>
    #include <boost/log/trivial.hpp>
    
    int count = 0;
    
    int expensive()
    {
        return ++count;
    }
    
    int main()
    {
        boost::log::core::get()->set_filter(
            boost::log::trivial::severity >= boost::log::trivial::warning
        );
    
        BOOST_LOG_TRIVIAL(error) << expensive();
        BOOST_LOG_TRIVIAL(info) << expensive();
    
        std::cout << count << '\n';
    
        return 0;
    }
    

    打印:

    [2018-05-21 14:33:47.327507] [0x00007eff37aa1740] [error]   1
    1
    

    对于那些想知道它是如何工作的人,请查看:How does the "lazy evaluation" of Boost Log's trivial loggers work?

    【讨论】:

    • 这令人印象深刻。出乎意料 :) 现在我想把它放到github.com/andreasfertig/cppinsights 来了解如何
    • 哇,这确实出乎意料。它之所以有效,是因为 BOOST_LOG_TRIVIAL() 不会扩展为表达式,而是扩展为部分 if 语句。
    • @n.m.:实际上,它扩展为for 循环,但实际上,诀窍是相同的(请参阅我发布的链接问题)。
    【解决方案2】:

    Acorn 的 answer 正确指出 Boost.Log 宏已经实现了流表达式的条件执行。此行为记录在 Tutorial 中。

    我会补充一点,您可以手动生成日志记录,避免使用宏。举个例子here:

    logging::record rec = lg.open_record();
    if (rec)
    {
        logging::record_ostream strm(rec);
        strm << "Hello, World!";
        strm.flush();
        lg.push_record(boost::move(rec));
    }
    

    如果日志消息的格式很复杂并且不能轻松地放入流式表达式中,这会很有用。

    【讨论】:

      【解决方案3】:

      我会使用 ostream 运算符懒惰地调用您的函数的中间类来执行此操作。

      类似这样的:

      #include <type_traits>
      #include <utility>
      #include <ostream>
      #include <iostream>
      
      
      namespace detail
      {
          // an ostreamable object that will stream out the result of a unary function object call
          template<class F>
          struct lazy_generator
          {
              void write(std::ostream& os) const
              {
                  os << generator_();
              }
      
              friend std::ostream& operator<<(std::ostream& os, lazy_generator const& tr)
              {
                  tr.write(os);
                  return os;
              }
      
              F generator_;
          };
      }
      
      // construct a lazy_generator
      template<class F>
      auto lazy_trace(F&& f)
      {
          return detail::lazy_generator<std::decay_t<F>>({std::forward<F>(f)});
      }
      
      // test
      int main()
      {
          extern std::string make_trace_record();
      
          // function pointer
          std::clog << lazy_trace(&make_trace_record);
      
          // function object
          std::clog << lazy_trace([](){ return make_trace_record(); });
      }
      

      【讨论】:

      • 我已经考虑过这个,但它看起来有点矫枉过正,幸运的是它不需要。由于(不健全但有效)升压宏,评估已经短路。请参阅其他答案。
      猜你喜欢
      • 2014-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多