In a real project, I need to log in different cpp or cc files, usually it is required in different threads.
In previous post, write log needs a logger object. We need the logger to be a global variable and thread-safe accessible in a real app.Official document is located at:http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/sources.html#log.detailed.sources.global_storage
Now I modified my demo code.
1. create a new file called logger.h, add just one line:
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::severity_logger_mt<sign_severity_level>)
2. in main.cc, include required header files, and use my_logger::get() to retrieve the reference of logger object.
#include <fstream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/thread.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/common.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
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<sinks::text_ostream_backend> text_sink;
boost::shared_ptr< text_sink > sink1 = boost::make_shared<text_sink>();
sink1->locked_backend()->add_stream(
boost::make_shared<std::ofstream>("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<sign_severity_level>("Severity")
% expr::attr<attrs::current_thread_id::value_type >("ThreadID")
% expr::smessage
);
logging::core::get()->add_sink(sink1);
sink1->set_filter(expr::attr<sign_severity_level>("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<sign_severity_level>("Severity")
% expr::smessage
);
logging::core::get()->add_sink(sink2);
sink2->set_filter(expr::attr<sign_severity_level>("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<sign_severity_level>& 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;
}
That's all.
Inside the macro, it defines a struct for you, also implements a get function. The singleton logger will be created at the first time you call get function.
Below is the code inside macros:
./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()
It generates the real C++ code below:
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<my_logger>::get();
}
};
inline my_logger::logger_type my_logger::construct_logger()
No comments:
Post a Comment