Thursday 26 December 2013

use boost log step 8

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:

Followers

Contributors