【问题标题】:Boost Log V2: setup log filter from configuration fileBoost Log V2:从配置文件设置日志过滤器
【发布时间】:2021-05-20 18:42:17
【问题描述】:

我只想设置一个 Boost Log V2 接收器 (Boost 1.75.0) 以从生成应用程序的日志记录中过滤掉几行。 目标是拥有一个仅包含这些行的日志文件(例如:登录的用户),而另一个接收器注销每条记录

我已尝试在配置文件中配置接收器的过滤器属性以匹配标记存在,如下所示:

[Sinks.FileSink]
Destination=TextFile
Filter="%USER%"
FileName="log.log"
MaxSize=10000000
Format="[%TimeStamp%] - %Message%"
Asynchronous=false
AutoFlush=true

%USER% 标记将是过滤条件,如果存在,则记录该行,否则不...

我尝试添加为 value 属性:

... << boost::log::add_value("USER", true) << "message..."

并在文件记录器之前注册它:

boost::log::core::get()->add_global_attribute("USER", boost::log::attributes::mutable_constant(true));
boost::log::init_from_stream(config);

它们都不起作用

对我来说,奇怪的行为是,如果我过滤严重性,过滤模式就会起作用,就像这样:Filter="%Severity%"

谁能帮我从应用程序中只过滤几行并将它们转发到文件中?

谢谢

更新:

想要展示我想要实现的目标的最小示例:

#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/attributes/mutable_constant.hpp>

int main(int argc, char *argv_char[]) {
std::stringstream config;
config << R"([Core])" << std::endl;
config << R"(DisableLogging=false)" << std::endl;
config << R"(Filter="%Severity% >= trace")" << std::endl;

config << R"([Sinks.Sink])" << std::endl;
config << R"(Destination=Console)" << std::endl;
//config << R"(Filter="%CMD% = \"YES\"")" << std::endl;
config << R"(Filter="%CMD% = \"NO\"")" << std::endl;
config << R"(FileName="commands.log")" << std::endl;
config << R"(Format="%Message%")" << std::endl;
config << R"(Asynchronous=false)" << std::endl;
config << R"(AutoFlush=true)" << std::endl;

boost::log::core::get()->add_global_attribute("CMD", boost::log::attributes::mutable_constant<std::string>("NO"));
boost::log::init_from_stream(config);

BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Visible message";

return 0;
}

如果我将过滤条件替换为 %CMD% = "YES",则输出中缺少所需的日志行

更新 2:

// Codes above didn't changed
boost::log::init_from_stream(config);

boost::log::sources::logger logger;
logger.add_attribute("CMD",   boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(logger) << "A log message from logger";

boost::log::sources::logger loggerScoped;
BOOST_LOG_SCOPED_LOGGER_ATTR(loggerScoped, "CMD", boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(loggerScoped) << "A log message from loggerScoped";


BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Visible message";

return 0;

【问题讨论】:

  • 顾名思义,add_global_attribute 添加了一个全局属性,因此除非您将其删除,否则它始终存在。 add_value 操纵器还添加了一个属性,但这是一个特定于记录器的属性,并且在过滤完成后。它复制了全局属性,因此没有效果。如果没有全局属性,则为 would not have worked for filtering
  • 至于为什么过滤器不能使用全局属性,我不知道。请展示一段重现问题的最小可编译代码。
  • 嗨@AndreySemashev,我已经更新了我的帖子,并添加了一个最小示例。谢谢

标签: c++ boost boost-log


【解决方案1】:

正如documentation 中所述,add_value 操纵器对过滤没有影响,因为它是在过滤完成后执行的。在您的代码示例中,您正在设置一个值为“NO”的全局字符串属性“CMD”,这就是过滤器正在测试的两个日志记录的内容。当您将过滤器更改为要求值为“YES”时,两条日志记录都会被禁止。

如果您想选择性地禁用某些日志记录,您应该使用其他方式注册属性,使其在过滤时生效。例如,您可以将属性添加到记录器(通过在记录器上调用add_attribute)并使用该记录器发出您想要抑制的日志记录。或者您可以使用scoped attributes 标记在给定代码区域中发出的日志记录。下面是一个更新的代码示例:

#include <string>
#include <sstream>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/sources/logger.hpp>

int main(int argc, char *argv_char[]) {
    std::stringstream config;
    config << R"([Core])" << std::endl;
    config << R"(DisableLogging=false)" << std::endl;
    //config << R"(Filter="%Severity% >= trace")" << std::endl;

    config << R"([Sinks.Sink])" << std::endl;
    config << R"(Destination=Console)" << std::endl;
    config << R"(Filter="%CMD% = \"YES\"")" << std::endl;
    config << R"(Format="%Message%")" << std::endl;
    config << R"(Asynchronous=false)" << std::endl;
    config << R"(AutoFlush=true)" << std::endl;

    boost::log::core::get()->add_global_attribute("CMD", boost::log::attributes::mutable_constant<std::string>("NO"));
    boost::log::init_from_stream(config);

    boost::log::sources::logger logger;
    logger.add_attribute("CMD",   boost::log::attributes::constant<std::string>("YES"));
    BOOST_LOG(logger) << "A log message from logger";

    {
        boost::log::sources::logger loggerScoped;
        BOOST_LOG_SCOPED_LOGGER_ATTR(loggerScoped, "CMD", boost::log::attributes::constant<std::string>("YES"));
        BOOST_LOG(loggerScoped) << "A log message from loggerScoped";
    }


    BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
    BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Still non-visible message";

    return 0;
}

【讨论】:

  • 我尝试使用新的记录器并添加属性或使用 BOOST_LOG_SCOPED_LOGGER_ATTR 宏但没有成功。我错过了什么?对不起...
  • @Moravas 我添加了一个工作代码示例。在您发布的代码示例中,您可能留下了全局过滤器“%Severity% >= trace”,它会丢弃没有严重级别的日志记录。而logger 是一个最基本的记录器,没有严重性级别。你可以改用severity_logger
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
  • 2017-08-21
  • 2014-02-01
  • 2018-05-05
  • 1970-01-01
  • 2015-10-07
相关资源
最近更新 更多