明确检查 boost::log 过滤器?

Check boost::log filter explicitly?

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

BOOST_LOG_TRIVIAL(trace) << make_trace_record();

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

我会用一个中间人 class 来做这件事,他的 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(); });
}

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

如果想知道它是如何工作的,请查看:

橡子 correctly points out that Boost.Log macros already implement conditional execution of the streaming expression. This behavior is documented in the 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));
}

如果日志消息格式很复杂并且不容易适合流表达式,这会很有用。