前面做了不少boost log的例子,现在来总结一下,下面是boost log库的架构图:
下面总结一下和这个架构相关的知识:
1. 如何获得Logging core
#include
...
boost::shared_ptr core = logging::core::get();
2. 如何安装Sink对象
一个core可以安装多个Sink,下面的代码假定已经有了两个Sink对象,将其安装到core中
core->add_sink(sink1); ... core->add_sink(sink2);
3. 如何创建一个Sink对象
需要先创建一个backend对象,然后在创建sink对象的时候,将backend对象传递给它。
typedef sinks::synchronous_sink TextSink;
// init sink1
boost::shared_ptr backend1 = boost::make_shared(
keywords::file_name = "sign_%Y-%m-%d_%H-%M-%S.%N.log",
keywords::rotation_size = 10 * 1024 * 1024,
keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
keywords::min_free_space = 30 * 1024 * 1024);
boost::shared_ptr sink1(new TextSink(backend1));
4. 如何创建一个backend对象
指定frontend类型
前面的代码中已经演示,注意backend的类型需要制定一个frontend类型作为其模板类。因此,当创建一个backend对象的时候,已经确定了frontend。
这个frontend模板可以用synchronous_sink类,也可以用asynchronous_sink, 后者不会阻塞调用程序,会额外的创建线程去处理log,不过会慢点,内存消耗大点。一般都推荐先用后者。
用keywords构造参数
这里看到一个概念:keywords. 在boost/log/keywords/目录下27个hpp文件:
auto_flush.hpp facility.hpp ident.hpp log_source.hpp open_mode.hpp rotation_size.hpp target.hpp
channel.hpp file_name.hpp ip_version.hpp max_size.hpp order.hpp scan_method.hpp time_based_rotation.hpp
delimiter.hpp filter.hpp iteration.hpp message_file.hpp ordering_window.hpp severity.hpp use_impl.hpp
depth.hpp format.hpp log_name.hpp min_free_space.hpp registration.hpp start_thread.hpp
keywords是boost库的基本概念,设计到一个宏BOOST_PARAMETER_KEYWORD,定义在boost/parameter/keywords.hpp文件中, 主要作用就是在指定的namespace中创建一个singleton的对象。所以上面的几行keywords:: 代码就是给keywords namespace下面的几个singleton对象file_name, rotation, time_based_rotation和min_free_space赋值。关键是要看看下面这个类的构造函数如何使用这些keywords.
sinks::text_file_backend
参考文档:
http://boost-log.sourceforge.net/libs/log/doc/html/log/detailed/sink_backends.html
http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/boost/log/sinks/text_file_backend.html
注意,text_file_backend的构造函数语法上支持变参,但是语义上只支持有限的keywords:
template< typename ArgsT >
void construct(ArgsT const& args)
{
construct(
filesystem::path(args[keywords::file_name | filesystem::path()]),
args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)],
args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()],
args[keywords::time_based_rotation | time_based_rotation_predicate()],
args[keywords::auto_flush | false]);
}
文档中也的确如此描述。但是在text_file_backend.hpp文件中发现还是有关于min_free_space的代码:
namespace aux {
//! Creates and returns a file collector with the specified parameters
BOOST_LOG_API shared_ptr< collector > make_collector(
filesystem::path const& target_dir,
uintmax_t max_size,
uintmax_t min_free_space
);
template< typename ArgsT >
inline shared_ptr< collector > make_collector(ArgsT const& args)
{
return aux::make_collector(
filesystem::path(args[keywords::target]),
args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()],
args[keywords::min_free_space | static_cast< uintmax_t >(0)]);
}
} // namespace aux
所以估计还是可以使用target, max_size 和 min_free_space这些keywords. 以后试了就知道了。
5. 如何在sink中指定格式
下面到了指定日志格式,这个需要在sink中指定,比如:
sink1->set_formatter ( expr::format("[%1%]<%2%>(%3%): %4%") % expr::format_date_time< boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S") % expr::attr("Severity") % expr::attr("ThreadID") % expr::smessage );这里的关键是理解expr::format. 文档在这里: http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/expressions.html#log.detailed.expressions.formatters
我使用的是Boost::Format风格。