如何为提升日志设置文本过滤器?

How to set a text filter for boost log?

从具有单个日志文件的日志设置开始,应添加第二个日志文件,其中仅包含消息中具有特定文本的行。

示例:

在单个日志文件中:

在第二个日志文件中,只应包含用户 b 的消息:

创建日志记录的代码不受影响,示例:
BOOST_LOG_TRIVIAL(debug) << "user " << user << " logged in";

我正在寻找一种解决方案,可以过滤日志中的消息 class。
我已经开始工作了,但是我没有成功地使用参数进行工作。

        // Main logging file
        g_file_sink = logging::add_file_log
        (
            keywords::file_name = "General.%3N",
            keywords::format = "[%TimeStamp%] [%Severity%] %Message%",
            keywords::open_mode = (std::ios::out | std::ios::app),
            keywords::auto_flush = true,
            keywords::rotation_size = 1024,
        );

        // Second logging file

        std::string text = "user a";

        // define the filter
        logging::filter flt =
            []
            (std::string text)
            {
                std::stringstream ss;
                ss << expr::smessage;
                std::string message = ss.str();
                return (message.find(text) == std::string::npos);
            };


        g_file1_sink = logging::add_file_log
        (
            keywords::file_name = test + ".%3N",
            keywords::format = "[%TimeStamp%] [%Severity%] %Message%",
            keywords::open_mode = (std::ios::out | std::ios::app),
            keywords::auto_flush = true,
            keywords::filter = flt,
            keywords::rotation_size = 1024,
        );

                // Main filter
        logging::core::get()->set_filter
        (
            logging::trivial::severity >= logging::trivial::warning
        );

        logging::add_common_attributes();

当我对“文本”进行硬编码时

        // define the filter
        logging::filter flt =
            []
            ()
            {
                std::stringstream ss;
                ss << expr::smessage;
                std::string message = ss.str();
                return (message.find("user a") == std::string::npos);
            };

一切正常,我一添加变量文本,就在界面上遇到编译器错误。

有没有办法不用改调用码?

您不能将过滤器应用于日志记录消息文本,因为消息文本是在过滤完成后组成的。这是有意为之的,因为这样可以避免在无论如何要丢弃日志记录的情况下编写文本。

如果要过滤属于特定用户的日志记录,方法是使用属性。例如,您可以将用户名放在常量属性中,然后对该属性应用过滤器。根据您的代码设计,该属性可以添加到记录器或当前线程(例如,当 user-specific activity 被限制在一组固定的线程中时)。如果 user-specific activity 仅在给定范围内执行,您也可以使用 scoped attributes

// Define attribute keyword
BOOST_LOG_ATTRIBUTE_KEYWORD(a_username, "Username", std::string)

void init_logging()
{
    // Main logging file
    g_file_sink = logging::add_file_log
    (
        keywords::file_name = "General.%3N",
        keywords::format = "[%TimeStamp%] [%Severity%] %Message%",
        keywords::open_mode = (std::ios::out | std::ios::app),
        keywords::auto_flush = true,
        keywords::rotation_size = 1024
    );

    // Second logging file
    g_file1_sink = logging::add_file_log
    (
        keywords::file_name = "A.%3N",
        keywords::filter = a_username == "A",
        keywords::format = "[%TimeStamp%] [%Severity%] %Message%",
        keywords::open_mode = (std::ios::out | std::ios::app),
        keywords::auto_flush = true,
        keywords::rotation_size = 1024
    );

    // Main filter
    logging::core::get()->set_filter
    (
        logging::trivial::severity >= logging::trivial::warning
    );

    logging::add_common_attributes();
}

int main()
{
    init_logging();

    // Create a logger that will emit log records not related to any specific user
    boost::log::severity_logger< boost::log::trivial::severity_level > lg;
    BOOST_LOG_SEV(lg, boost::log::trivial::warning)
        << "Log record with no username";

    // Create a logger that will emit log records pertaining to user A
    boost::log::severity_logger< boost::log::trivial::severity_level > lg_a;
    lg_a.add_attribute(a_username.get_name(),
        boost::log::attributes::make_constant(std::string("A")));

    BOOST_LOG_SEV(lg_a, boost::log::trivial::warning)
        << "Log record related to user A";
}

请注意,您也可以在格式化程序中使用属性。这样您就可以在输出中标记与给定用户关联的所有记录。