// %pacpus:license{ // This file is part of the PACPUS framework distributed under the // CECILL-C License, Version 1.0. // %pacpus:license} /// @version $Id: Log.cpp 76 2013-01-10 17:05:10Z kurdejma $ #include #ifdef PACPUS_USE_LOG #include #include #include #include #include #include #include #include #include #include #if BOOST_VERSION >= 105500 // header exists from 1.55 # include #else # include #endif #include #include // could use Boost.Predef with Boost >= 1.55 #if defined(WIN32) || defined(_WINDOWS) # define PACPUS_OS_WINDOWS 1 #elif defined(__unix) || defined(__unix__) # define PACPUS_OS_UNIX 1 # if defined(__linux) || defined(__linux__) # define PACPUS_OS_LINUX 1 # endif #elif defined(__APPLE__) || defined(__MACH__) || defined(Macintosh) || defined(macintosh) # define PACPUS_OS_MACOS 1 #else // unknown system #endif #if PACPUS_LOG_COLORED_OUTPUT && PACPUS_OS_WINDOWS # include #endif template< typename CharT, typename TraitsT > std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, QString const& s) { strm << s.toStdString(); return strm; } // explicit instantiation template PACPUSLIB_API std::basic_ostream& operator<< (std::basic_ostream& strm, QString const& s); namespace pacpus { BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", ::pacpus::SeverityLevel) enum Color { COLOR_DEFAULT, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; //Color getColor(boost::log::trivial::severity_type const& sev) //{ // using namespace boost::log::trivial; // if (sev >= error) { // return COLOR_RED; // } else if (sev == warning) { // return COLOR_YELLOW; // } else if (sev == info) { // return COLOR_GREEN; // } else { // return COLOR_DEFAULT; // } //} #if PACPUS_OS_WINDOWS //&& !PACPUS_OS_WINDOWS_MOBILE // Returns the character attribute for the given color. WORD getColorAttribute(Color color) { switch (color) { case COLOR_BLACK: return 0; case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; case COLOR_BLUE: return FOREGROUND_BLUE; case COLOR_MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE; case COLOR_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE; case COLOR_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; default: return 0; } } #else /// @returns the ANSI color code for the given color. COLOR_DEFAULT is /// an invalid input. const char* getAnsiColorCode(Color color) { const char* kEscapeSequence = "\033["; // const char* kBackground = ""; const char* kFontRegular = "0;"; // const char* kFontBold = "1;"; // const char* kFontWeak = "2;"; // const char* kFontStrong = "3;"; // const char* kFontUnderline = "4;"; std::stringstream ss; ss << kEscapeSequence << kFontRegular; switch (color) { case COLOR_BLACK: ss << "30"; break; case COLOR_RED: ss << "31"; break; case COLOR_GREEN: ss << "32"; break; case COLOR_YELLOW: ss << "33"; break; case COLOR_BLUE: ss << "34"; break; case COLOR_MAGENTA: ss << "35"; break; case COLOR_CYAN: ss << "36"; break; case COLOR_WHITE: ss << "37"; break; default: return ""; }; const char* kPostfix = "m"; ss << kPostfix; return ss.str().c_str(); } const char* getAnsiColorCodeRestoreDefault() { return "\033[0m"; } #endif // PACPUS_OS_WINDOWS && !PACPUS_OS_WINDOWS_MOBILE void init_log_factories() { boost::log::register_simple_formatter_factory< QString, char >("QString"); } static int niftyCounter; LogConfigurator::LogConfigurator() { if (0 == niftyCounter++) { LOG_INFO("LogConfigurator constructor"); init_log_factories(); } } LogConfigurator::~LogConfigurator() { if (0 == --niftyCounter) { // clean up LOG_INFO("LogConfigurator destructor"); } } void LogConfigurator::configureLoggerWithFile(const char* logFileName) { using namespace boost; namespace logging = boost::log; namespace sinks = boost::log::sinks; namespace src = boost::log::sources; namespace expr = boost::log::expressions; namespace attrs = boost::log::attributes; namespace keywords = boost::log::keywords; logging::add_common_attributes(); logging::core::get()->add_global_attribute( "ProcessID", attrs::current_process_id()); logging::core::get()->add_global_attribute( "ThreadID", attrs::current_thread_id()); //logging::core::get()->add_global_attribute( // "Scope", // attrs::named_scope()); logging::core::get()->set_filter ( #ifdef NDEBUG // release severity >= debug #else // debug severity >= trace #endif ); //////////////////////////////////////////////////////////////////////////////// // FILE logging::add_file_log ( keywords::file_name = logFileName, keywords::rotation_size = 10 * 1024 * 1024, keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), //keywords::format = "%LineID% [%TimeStamp%]: %Message%" keywords::format = ( expr::stream << std::setfill('0') << std::setw(6) << expr::attr< unsigned int >("LineID") //<< " [" << expr::format_date_time< posix_time::ptime >("TimeStamp", date_time::iso_extended_format) << "]" << " [" << expr::format_date_time< posix_time::ptime >("TimeStamp", "%Y-%m-%d %T.%f") << "]" //<< " [" << std::setw(20) << expr::attr("Scope") << ">" << " <" << severity << ">" << " <" << expr::attr< attrs::current_process_id::value_type >("ProcessID") << ":" << expr::attr< attrs::current_thread_id::value_type >("ThreadID") << ">" << " " << expr::smessage ) ); //////////////////////////////////////////////////////////////////////////////// // CONSOLE #if PACPUS_LOG_COLORED_OUTPUT Color color = COLOR_GREEN;// = getColor(expr::attr(logging::trivial::severity.get_name())); #endif #if BOOST_VERSION >= 105500 #else using logging::empty_deleter; #endif // Create a backend and attach a couple of streams to it boost::shared_ptr< sinks::text_ostream_backend > backend = make_shared< sinks::text_ostream_backend >(); backend->add_stream( shared_ptr< std::ostream >(&std::clog, empty_deleter()) ); // Enable auto-flushing after each log record written backend->auto_flush(true); // Wrap it into the frontend and register in the core. // The backend requires synchronization in the frontend. typedef sinks::synchronous_sink< sinks::text_ostream_backend > sink_t; shared_ptr< sink_t > sink(new sink_t(backend)); sink->set_filter ( severity >= info ); sink->set_formatter ( expr::stream #if PACPUS_LOG_COLORED_OUTPUT && PACPUS_OS_LINUX // << getAnsiColorCode(color) #endif << std::setfill('0') << std::setw(6) << expr::attr< unsigned int >("LineID") //<< " [" << expr::format_date_time< posix_time::ptime >("TimeStamp", date_time::iso_extended_format) << "] " << " [" << expr::format_date_time< posix_time::ptime >("TimeStamp", "%Y-%m-%d %T.%f") << "] " //<< " [" << std::setw(20) << expr::attr("Scope") << ">" << "<" << severity << ">" << " " << expr::smessage #if PACPUS_LOG_COLORED_OUTPUT && PACPUS_OS_LINUX << getAnsiColorCodeRestoreDefault() // Resets the terminal to default. #endif ); logging::core::get()->add_sink(sink); LOG_INFO("logger initialised"); } } // namespace pacpus #else // PACPUS_USE_LOG namespace pacpus { LogConfigurator::LogConfigurator() {} LogConfigurator::~LogConfigurator() {} void LogConfigurator::configureLoggerWithFile(const char* /*configFilename*/) {} } // namespace pacpus #endif // PACPUS_USE_LOG