最近想整一个日志库,以前使用过log4cplus,看到了boost推出了1.54版本之后,就开始有了一个log库。这个log看了介绍,之后开始尝试去使用。主要的应用场景是让多个模块(so,dll)使用。场景是一个程序,多个模块,模块是单独的so,打印出来的日志,往同一个文件中输出。
最初的时候,编译的boost库是静态库,编译出来的,多是.a类型文件。当在一个日志模块中出示之后,到另一个模块中去使用,发现boost::log::core::get()获取出来的指针都不一样,但是看代码的时候,他明明说明是单例的,这让我困惑了很久。结果是明显的,boost::log::core::get()获取出来的指针不一样,在其他地方初始化的东西,肯定是没有效果的。是什么地方导致的,继续在代码中查找。看见了在在core.cpp中,core类使用implementation类,implementation继承lazy_singleton,这个类中,在获取单例的时候,使用一个很特殊的东西:__COUNTER__(windows)和__LINE__(LINUX),在不同的模块中,会是不同的值,生成不同的变量名,导致了boost::log::core::get()的值不一样。
活来查看boost的log文档,查找到一下内容:
If asynchronous logging is used in a multi-module application, one should decide carefully when to unload dynamically loaded modules that write logs. The library has many places where it may end up using resources that reside in the dynamically loaded module. Examples of such resources are virtual tables, string literals and functions. If any of these resources are still used by the library when the module in which they reside gets unloaded, the application will most likely crash. Strictly speaking, this problem exists with any sink type (and is not limited to sinks in the first place), but asynchronous sinks introduce an additional problem. One cannot tell which resources are used by the asynchronous sink because it works in a dedicated thread and uses buffered log records. There is no general solution for this issue. Users are advised to either avoid dynamic module unloading during the application‘s work time, or to avoid asynchronous logging. As an additional way to cope with the problem, one may try to shutdown all asynchronous sinks before unloading any modules, and after unloading re-create them. However, avoiding dynamic unloading is the only way to solve the problem completely.
大致说明了,在多模块的架构中,使用的时候,需要注意的地方。
以为多模块的事情解决了,准备使用配置文件,去加载log库,新问题出现了。看网上,大家都是新定义一个日志登记,之后,使用set_format去设置输出模式。但是在使用配置文件加载的使用(boost::log::init_from_stream),没法获取出sink方法(我个人也没有找到,如果有,请告诉我,谢谢),没有办法往日志中添加日志等级。后来改用log库自己的boost::log::trivial::severity_level,还是没有日志等级,这他妈神奇了!
经过查找,在stackoverflow中找到原因(经验:问题如果有,遇到的可能不是就自己,google还是有希望的),他们说这是一个bug(听到这句话,你也许会舒服一些)。
网址如下:http://stackoverflow.com/questions/18014335/boost-log-severity-logger-init-from-stream
解决的方式,就是重新定义format和filter,具体的函数如下:
boost::log::register_simple_formatter_factory<boost::log::trivial::severity_level, char>("Severity"); boost::log::register_simple_filter_factory<boost::log::trivial::severity_level, char>("Severity");
register_simple_formatter_factory 重新定义关于Severity的输出(out) (如果自定日志等级,需定义输入) register_simple_filter_factory 定义关于Serverity的过滤(filter)(如果自定日志等级,需定义输入,值比较方法)
如果使用自己新的日志登记,最好直接参考traivaila.hpp 和 traivail.cpp的实现。具体怎么实现,在boost-log.pdf的帮助文档中,有详细的描述。标题:
Extending the library
Extending library settings support
Adding support for user-defined types to the formatter parser
Adding support for user-defined types to the filter parser
作者:wcl_hjs!
大家共同交流!
boost-log-库 使用经历