在真正的项目中,我需要在不同的cpp或者cc文件中写日志,通常在不同的线程中也需要这样做。
在前面的文章中,写日志需要一个logger对象。在一个真正的应用中,我需要这个logger成为全局变量,并且是可以线程安全的访问的。
官方文档在这里:http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/sources.html#log.detailed.sources.global_storage
现在我修改我的代码。
1. 创建一个logger.h文件,只有一行:
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::severity_logger_mt)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;
enum sign_severity_level {
trace,
debug,
info,
warning,
error,
fatal,
report
};
void InitLog() {
typedef sinks::synchronous_sink text_sink;
boost::shared_ptr< text_sink > sink1 = boost::make_shared();
sink1->locked_backend()->add_stream(
boost::make_shared("sign.log"));
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
);
logging::core::get()->add_sink(sink1);
sink1->set_filter(expr::attr("Severity") >= warning);
boost::shared_ptr< text_sink > sink2 = boost::make_shared< text_sink >();
sink2->locked_backend()->add_stream(
boost::make_shared< std::ofstream >("sign.csv"));
sink2->set_formatter (
expr::format("%1%,%2%,%3%")
% expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
% expr::attr("Severity")
% expr::smessage
);
logging::core::get()->add_sink(sink2);
sink2->set_filter(expr::attr("Severity") == report);
logging::add_common_attributes();
logging::core::get()->add_global_attribute("ThreadID", attrs::current_thread_id());
}
#include "logger.h"
int main(int, char*[]) {
InitLog();
src::severity_logger_mt& lg = my_logger::get();
BOOST_LOG_SEV(lg, trace) << "A trace severity message";
BOOST_LOG_SEV(lg, debug) << "A debug severity message";
BOOST_LOG_SEV(lg, info) << "An informational severity message";
BOOST_LOG_SEV(lg, warning) << "A warning severity message";
BOOST_LOG_SEV(lg, error) << "An error severity message";
BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
BOOST_LOG_SEV(lg, report) << "A report severity message";
return 0;
}
宏为我们定义了一个struct类型,也实现了get方法。作为singleton的logger会在第一次调用get方法时被创建出来。
下面是宏的代码:
./sources/global_logger_storage.hpp:185
//! The macro declares a global logger that will be default-constructed
#define BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
{\
return logger_type();\
}
//! The macro declares a global logger with a custom initialization
#define BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
inline BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)
//! The macro forward-declares a global logger with a custom initialization
#define BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
struct tag_name\
{\
typedef logger logger_type;\
enum registration_line_t { registration_line = __LINE__ };\
static const char* registration_file() { return __FILE__; }\
static logger_type construct_logger();\
static inline logger_type& get()\
{\
return ::boost::log::sources::aux::logger_singleton< tag_name >::get();\
}\
};
//! The macro defines a global logger initialization routine
#define BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
tag_name::logger_type tag_name::construct_logger()
它产生了下面真正的C++代码
struct my_logger
{
typedef src::logger_mt logger_type;
enum registration_line_t { registration_line = __LINE__ };
static const char* registration_file() { return __FILE__; }
static logger_type construct_logger();
static inline logger_type& get()
{
return ::boost::log::sources::aux::logger_singleton::get();
}
};
inline my_logger::logger_type my_logger::construct_logger()