Проверить фильтр boost :: log явно?
У меня есть тривиальный журнал:
BOOST_LOG_TRIVIAL(trace) << make_trace_record();
Теперь make_trace_record
- несколько дорогая функция для вызова (не спрашивайте, почему, это сложно). Я хочу называть это только в том случае, если журнал в настоящее время проходит фильтрацию. Как я могу это сделать? Я не вижу способа явно вызвать фильтр серьезности.
Ответы
Ответ 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
Для тех, кто задается вопросом, как это работает, взгляните на: Как работает "ленивая оценка" тривиальных регистраторов Boost Log?
Ответ 2
Acorn ответ правильно указывает, что макросы Boost.Log уже реализуют условное выполнение потокового выражения. Это поведение описано в учебнике.
Я добавлю, что вы можете создавать записи журнала вручную, избегая макросов. Пример приведен здесь:
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
Я бы сделал это с промежуточным классом, который операционный оператор лениво называет вашу функцию.
Что-то вроде этого:
#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(); });
}