在运行时条件下构建 boost::log::formatter

Building boost::log::formatter on runtime condition

我想有条件地构建 boost::log::formatter,但是,格式化程序对象的行为似乎不像 'normal values'。

例如:

auto sink = boost::log::add_console_log(std::clog);

auto format =
    expr::stream << expr::format_date_time(timestamp, "%Y-%m-%d %H:%M:%S.%f");

boost::log::formatter formatter = format;

if (condition) {

    auto t = "msg=" << expr::smessage;

    formatter <<= t;
}

sink->set_formatter(formatter);

但是,operator<<=(甚至 operator=)似乎没有修改格式化程序对象,这让我感到非常惊讶!

这样做的正确方法是什么?

格式化流表达式构造一个函数对象,当日志记录格式化为字符串时将执行该函数对象。函数对象类型是最终的,因为您不能通过向它添加新的格式化语句来修改它。事实上,任何流式处理语句都有效地创建了一个不同类型的新格式化程序函数对象。 boost::log::formatter 只是一个封装格式化程序函数对象的类型擦除助手,类似于 std::function 封装您分配给它的 lambda 函数。

如果你想修改格式化程序,你必须创建一个新的格式化程序,它的左边是原来的格式化程序,右边是添加的流语句。然后可以将这个新的格式化程序分配给 boost::log::formatter.

auto sink = boost::log::add_console_log(std::clog);

boost::log::formatter formatter;

auto common_format =
    expr::stream << expr::format_date_time(timestamp, "%Y-%m-%d %H:%M:%S.%f");

if (condition) {
    auto format = common_format << "msg=" << expr::smessage;
    formatter = format;
} else {
    formatter = common_format;
}

sink->set_formatter(formatter);

请注意,这仅适用于流式表达式。这不适用于基于 boost::log::expressions::format.

的 Boost.Format-style 格式化程序

另请注意,condition 将被评估一次 - 当格式化程序被 构造时 ,而不是当它被 执行时 格式化日志记录。如果您想在执行格式化程序时测试条件,那么您应该查看 conditional formatters.