如何使用 Boost 日志为每个日志源设置严重级别?

How can I set a severity level per log source with Boost log?

我是 Boost Log 的新手,在做一些非常简单的事情时遇到了麻烦。 我正在尝试创建一个记录器并为其分配一个级别(例如警告、信息、跟踪等),并过滤掉(出于性能原因)发送到该记录器的任何日志,其中分配给的级别较低记录器,在日志核心级别,而不是在接收器级别。 例如(伪代码):

logger lg;
lg.setLevel(Warn);
BOOST_LOG_TRIVIAL(trace) << "A trace severity message"; // Will be filtered
BOOST_LOG_TRIVIAL(warn) << "A warning severity message"; // Won't be filtered

我很确定这可以通过 Boost Log 实现,但由于某些原因我无法做到这一点。

谢谢,

奥马尔。

我建议你使用 this link 作为参考...

下面是我的一小段代码。在这个小片段中,我使用了同步后端,但您可以自由使用异步后端。

log.hpp

#pragma once

#include <boost/log/common.hpp>
#include <boost/log/sources/severity_logger.hpp>

enum class LogSeverity {
    trace, debug, info, warning, error, fatal
};

extern boost::log::sources::severity_logger<LogSeverity> g_logger;

void log_set_filter(LogSeverity level);
void init_logger();

#define LOG_TRACE   BOOST_LOG_SEV(g_logger, LogSeverity::trace)
#define LOG_DEBUG   BOOST_LOG_SEV(g_logger, LogSeverity::debug)
#define LOG_INFO    BOOST_LOG_SEV(g_logger, LogSeverity::info)
#define LOG_WARNING BOOST_LOG_SEV(g_logger, LogSeverity::warning)
#define LOG_ERROR   BOOST_LOG_SEV(g_logger, LogSeverity::error)
#define LOG_FATAL   BOOST_LOG_SEV(g_logger, LogSeverity::fatal)

log.cpp

#include "bumper-common/log.hpp"
#include <boost/log/common.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/core/null_deleter.hpp>
#include <iomanip>
#include <iostream>

using namespace boost::log;

using LogTextSink = sinks::synchronous_sink<sinks::text_ostream_backend>;

LogSeverity g_logLevel = LogSeverity::info;
sources::severity_logger<LogSeverity> g_logger;

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", LogSeverity)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(log_thread_id, "ThreadID", attributes::current_thread_id::value_type)

std::ostream& operator<< (std::ostream& strm, LogSeverity level)
{
    static const std::array<std::string, 6> strings
    {
        std::string{"trace"},
        std::string{"debug"},
        std::string{"info"},
        std::string{"warn"},
        std::string{"error"},
        std::string{"fatal"}
    };

    strm << strings[static_cast< std::size_t >(level)];

    return strm;
}

void init_logger()
{
    boost::shared_ptr<std::ostream> stream{&std::cout,
        boost::null_deleter{}};

    auto loggerSink = boost::make_shared<LogTextSink>();

    add_common_attributes();

    loggerSink->locked_backend()->add_stream(stream);
    loggerSink->locked_backend()->auto_flush(true);

    loggerSink->set_filter(severity >= g_logLevel);

    loggerSink->set_formatter( expressions::stream
        << "[" << expressions::format_date_time(timestamp, "%H:%M:%S.%f") << "] ["
        << std::setw(5) << std::left << severity << "] ["
        << log_thread_id << "] "
        << expressions::smessage
    );

    boost::log::core::get()->add_sink(loggerSink);
}

void log_set_filter(LogSeverity level)
{
    g_logLevel = level;
}

希望对您有所帮助。这个图书馆让我很烦恼。所以我强烈建议您阅读我之前发布的文档。

Boost.Log 中没有记录器(源)级别的过滤器。您可以全局(在日志核心中)或每个接收器设置过滤器,所有源的日志记录将被统一处理。

您可以使用 channels 通过为每个记录器分配一个通道并根据通道和严重级别进行过滤来实现您想要的行为。

BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", LogSeverity)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_channel, "Channel", std::string)

typedef sources::severity_channel_logger< LogSeverity, std::string > logger_type;

logger_type lg_a(keywords::channel = "A");
logger_type lg_b(keywords::channel = "B");

core::get()->set_filter
(
    (a_channel == "A" && a_severity >= LogSeverity::info) ||
    (a_channel == "B" && a_severity >= LogSeverity::warning)
);

该库还提供了 a specialized filter 可用于简化此操作。

auto min_severity = expressions::channel_severity_filter(a_channel, a_severity);
min_severity["A"] = LogSeverity::info;
min_severity["B"] = LogSeverity::warning;

core::get()->set_filter(min_severity);

请注意,您实际上并不仅限于每个通道只有一个记录器 - 您可以创建多个记录器,每个记录器的日志记录将以相同的方式处理。