我一直在研究Boost.Log一段时间,我相信现在是我将代码库从log4cxx转换为Boost.Log的时候了.我相信Boost.Log的设计和实现将显着改善我的代码维护和使用.我知道Boost.Log FAQ有一个页面说
对于分层记录器,当前库设计中不需要此功能.它在log4j中提供的主要好处之一是确定日志记录最终的appender(接收器,就此库而言).该库通过过滤实现相同的结果.
我理解概念等价而不是试图将Boost.Log变成log4j/log4cxx.相反,我的问题是:如何使用Boost.Log来获得与我目前在log4cxx中使用的功能相同的功能?特别是,我想为日志源或通道层次结构中的特定节点设置严重性阈值和接收器.例如,我有按日期组织的日志源,libA.moduleB.componentC.logD
其中层次结构中的级别由点分隔.
.使用log4cxx,可以使用libA
更具体的记录器设置INFO 的总阈值,libA.moduleB
阈值为DEBUG.
libA.threshold=INFO libA.moduleB.threshold=DEBUG
类似地,可以将接收器附加到层次结构中的任意节点.
我相信使用Boost.Log可以实现类似的功能,但我需要有关如何实际实现此功能的帮助/指导.另外,我确信其他想要从其他框架过渡到Boost.Log的人会有同样的问题.
我真诚地感谢您的评论.
在Boost.Log接收器(写入日志文件的对象)和记录器(应用程序通过其发出日志记录的对象)未直接连接,并且任何接收器可能从任何记录器接收日志消息.为了使某些记录器中的记录仅出现在特定的接收器中,您必须在接收器中安排过滤器,以便为不应接收它们并为其他接收器传递的接收器抑制不必要的记录.为了区分不同记录器的记录,记录器必须为它们制作的每个记录添加不同的属性.通常,这是通过通道实现的- 记录器将附加Channel属性,该属性可用于识别过滤器,格式化程序或接收器中的记录器.通道可以与其他属性组合,例如严重性级别.必须注意的是,通道和严重性级别是正交的,并且任何通道都可以具有任何级别的记录.在过滤器中分别分析不同属性的值.
因此,例如,如果您希望将通道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");
请参阅有关定义属性关键字和便捷设置功能的文档.现在,您可以为每个通道创建记录器,并且日志记录将通过过滤器路由到接收器.
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"),则设置上述过滤器可能会很困难.如果您需要不同渠道的不同严重性级别,事情将变得更加复杂.
如果通道层次结构对您不重要,则可以使用严重性阈值过滤器使过滤器配置更容易.使用该过滤器,您可以为每个相应的通道设置最低严重性级别.如果您想在子通道中继承严重性阈值,那么您唯一的方法就是编写自己的过滤器; 图书馆不提供开箱即用的功能.
有多种方法可以创建过滤器,但它归结为编写一个接受日志记录中的属性值的函数,true
如果此记录通过过滤器false
则返回.也许,在显示的最简单的方法教程,看到的例子phoenix::bind
来自Boost.Phoenix.
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
是用于存储两个日志文件不同渠道的严重程度阈值的数据结构.