在 Boost.Log 中,接收器(写入日志文件的对象)和记录器(应用程序发出日志记录的对象)没有直接连接,任何接收器都可以从任何记录器接收日志消息。为了使来自某些记录器的记录仅出现在特定的接收器中,您必须在接收器中安排过滤器,以便为不应该接收它们的接收器抑制不必要的记录并传递给其他接收器。为了区分来自不同记录器的记录,记录器必须为他们所做的每条记录添加不同的属性。通常这是通过channels 实现的 - 记录器将附加一个通道属性,该属性可用于识别过滤器、格式化程序或接收器中的记录器。频道可以是combined 以及其他属性,例如严重性级别。必须注意的是,通道和严重级别是正交的,任何通道都可能有任何级别的记录。在过滤器中分别分析不同属性的值。
因此,例如,如果您希望将通道 A 的记录写入文件 A.log,并将通道 B 的记录写入文件 B.log,则必须创建两个接收器 - 每个文件一个,并设置它们的过滤器相应地。
BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_channel, "Channel", std::string)
logging::add_file_log(
keywords::file_name = "A.log",
keywords::filter = a_channel == "A");
logging::add_file_log(
keywords::file_name = "B.log",
keywords::filter = a_channel == "B");
请参阅有关 defining attribute keywords 和 convenience setup functions 的文档。现在您可以为每个通道创建记录器,并且日志记录将通过过滤器路由到接收器。
typedef src::severity_channel_logger< severity_level, std::string > logger_type;
logger_type lg_a(keywords::channel = "A");
logger_type lg_b(keywords::channel = "B");
BOOST_LOG_SEV(lg_a, info) << "Hello, A.log!";
BOOST_LOG_SEV(lg_b, info) << "Hello, B.log!";
您可以为单个通道拥有任意数量的记录器 - 来自每个通道的消息将被定向到单个接收器。
但是,这里有两个问题。首先,图书馆不了解通道的性质,并认为它只是一个不透明的值。它不了解频道层次结构,因此“A”和“A.bb”被认为是不同且不相关的频道。其次,如果您希望将多个通道写入单个文件(如“A”和“A.bb”),则设置上述过滤器可能会很困难。如果您希望不同渠道的严重程度不同,事情会变得更加复杂。
如果通道层次结构对您来说不是很重要,您可以使用severity threshold filter 简化过滤器配置。使用该过滤器,您可以为每个相应的通道设置最低严重性级别。如果您想在子通道中继承严重性阈值,那么您唯一的方法就是编写自己的过滤器;该库不提供开箱即用的功能。
有多种方法可以创建过滤器,但归结为编写一个函数,该函数接受来自日志记录的属性值,如果此记录通过过滤器,则返回 true,否则返回 false。也许,最简单的方法是在Tutorial 中显示,参见Boost.Phoenix 中的phoenix::bind 示例。
bool my_filter(
logging::value_ref< severity_level, tag::a_severity > const& level,
logging::value_ref< std::string, tag::a_channel > const& channel,
channel_hierarchy const& thresholds)
{
// See if the log record has the severity level and the channel attributes
if (!level || !channel)
return false;
std::string const& chan = channel.get();
// Parse the channel string, look for it in the hierarchy
// and find out the severity threshold for this channel
severity_level threshold = thresholds.find(chan);
return level.get() >= threshold;
}
现在设置接收器将像这样更改以使用您的新过滤器:
logging::add_file_log(
keywords::file_name = "A.log",
keywords::filter = phoenix::bind(&my_filter, a_severity.or_none(), a_channel.or_none(), hierarchy_A));
logging::add_file_log(
keywords::file_name = "B.log",
keywords::filter = phoenix::bind(&my_filter, a_severity.or_none(), a_channel.or_none(), hierarchy_B));
这里的hierarchy_A 和hierarchy_B 是您的数据结构,用于存储两个日志文件的不同通道的严重性阈值。