#include "Logger.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace fs = boost::filesystem; namespace logging = boost::log; namespace srcs = logging::sources; namespace sinks = logging::sinks; namespace keywords = logging::keywords; namespace expr = logging::expressions; namespace attrs = logging::attributes; namespace ptime = boost::posix_time; BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS (sys, srcs::severity_channel_logger_mt, (keywords::channel = "SYSLOG")); BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS (data, srcs::severity_channel_logger_mt, (keywords::channel = "DATALOG")); namespace Logger { namespace { // Custom formatter factory to add TimeStamp format support in config ini file. // Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format. class TimeStampFormatterFactory : public logging::basic_formatter_factory { public: formatter_type create_formatter (logging::attribute_name const& name, args_map const& args) { args_map::const_iterator it = args.find ("format"); if (it != args.end ()) { return expr::stream << expr::format_date_time ( expr::attr (name), it->second ); } else { return expr::stream << expr::attr (name); } } }; // Custom formatter factory to add Uptime format support in config ini file. // Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format. // attrs::timer value type is ptime::time_duration class UptimeFormatterFactory : public logging::basic_formatter_factory { public: formatter_type create_formatter (logging::attribute_name const& name, args_map const& args) { args_map::const_iterator it = args.find ("format"); if (it != args.end ()) { return expr::stream << expr::format_date_time ( expr::attr (name), it->second ); } else { return expr::stream << expr::attr (name); } } }; class CommonInitialization { public: CommonInitialization () { // Add attributes: LineID, TimeStamp, ProcessID, ThreadID, and Uptime auto core = logging::core::get (); core->add_global_attribute ("LineID", attrs::counter (1)); core->add_global_attribute ("TimeStamp", attrs::utc_clock ()); core->add_global_attribute ("ProcessID", attrs::current_process_id ()); core->add_global_attribute ("ThreadID", attrs::current_thread_id ()); core->add_global_attribute ("Uptime", attrs::timer ()); // Allows %Severity% to be used in ini config file for property Filter. logging::register_simple_filter_factory ("Severity"); // Allows %Severity% to be used in ini config file for property Format. logging::register_simple_formatter_factory ("Severity"); // Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format. logging::register_formatter_factory ("TimeStamp", boost::make_shared ()); // Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format. logging::register_formatter_factory ("Uptime", boost::make_shared ()); } ~CommonInitialization () { } }; } void init () { CommonInitialization ci; } void init_from_config (std::wistream& stream) { CommonInitialization ci; try { // Still can throw even with the exception suppressor above. logging::init_from_stream (stream); } catch (std::exception& e) { std::string err = "Caught exception initializing boost logging: "; err += e.what (); // Since we cannot be sure of boost log state, output to cerr and cout. std::cerr << "ERROR: " << err << std::endl; LOG_ERROR (err); throw; } } void disable () { logging::core::get ()->set_logging_enabled (false); } void add_datafile_log (std::wstring const& log_file_name) { // Create a text file sink boost::shared_ptr backend ( new sinks::wtext_ostream_backend() ); backend->add_stream (boost::shared_ptr (new fs::wofstream (log_file_name))); // Flush after each log record backend->auto_flush (true); // Create a sink for the backend typedef sinks::synchronous_sink sink_t; boost::shared_ptr sink (new sink_t (backend)); // The log output formatter sink->set_formatter (expr::format (L"[%1%][%2%] %3%") % expr::attr ("TimeStamp") % logging::trivial::severity % expr::message ); // Filter by severity and by DATALOG channel sink->set_filter (logging::trivial::severity >= logging::trivial::info && expr::attr ("Channel") == "DATALOG"); // Add it to the core logging::core::get ()->add_sink (sink); } }