#include "Logger.hpp" #include "LogSink.hpp" #include "ConsoleLogSink.hpp" #include "FileLogSink.hpp" #include "SyslogLogSink.hpp" #ifdef _WIN32 #include "WinDbgLogSink.hpp" #endif #include #include using namespace std; LogStream::LogStream( Logger &logger, const LogLevel level ) : m_logger( logger ), m_level( level ) { } LogStream::~LogStream( ) { m_logger.log( m_level, str( ) ); } ostream &LogStream::get( ) { // transform the ostringstream to ostream, so the operator // << functions work a little bit more as expected (e.g. // for strings/char *) return static_cast( *this ); } class LoggerImpl { public: void addSink( LogSink *sink ); void removeSink( LogSink *sink ); void log( const LogLevel level, const std::string &msg ); static std::string toString( const LogLevel level ); static LogLevel fromString( const std::string &s ); void openConsoleLog( const LogLevel level ); void openFileLog( const LogLevel level, const std::string &filename ); void openSyslog( const LogLevel level, const string &ident, const string &facility ); void openWinDbgLog( const LogLevel level ); public: LoggerImpl( ); ~LoggerImpl( ); private: typedef std::list< LogSink * > SinkList; SinkList m_sinks; }; LoggerImpl::LoggerImpl( ) { } LoggerImpl::~LoggerImpl( ) { SinkList::const_iterator it, end = m_sinks.end( ); for( it = m_sinks.begin( ); it != end; it++ ) { delete (*it); } } void LoggerImpl::addSink( LogSink *sink ) { m_sinks.push_back( sink ); } void LoggerImpl::removeSink( LogSink *sink ) { SinkList::iterator it = find( m_sinks.begin( ), m_sinks.end( ), sink ); if( it != m_sinks.end( ) ) { m_sinks.erase( it ); } } void LoggerImpl::log( const LogLevel level, const string &msg ) { SinkList::const_iterator it, end = m_sinks.end( ); for( it = m_sinks.begin( ); it != end; it++ ) { (*it)->log( level, msg ); } } void LoggerImpl::openConsoleLog( const LogLevel level ) { addSink( new ConsoleLogSink( level ) ); } void LoggerImpl::openFileLog( const LogLevel level, const string &filename ) { addSink( new FileLogSink( level, filename ) ); } void LoggerImpl::openSyslog( const LogLevel level, const string &ident, const string &facility ) { addSink( new SyslogLogSink( level, ident, facility ) ); } void LoggerImpl::openWinDbgLog( const LogLevel level ) { #ifdef _WIN32 addSink( new WinDbgLogSink( level ) ); #else (void)level; LOG( logWARNING ) << "WinDbg logger is only available on Windows"; #endif } string Logger::toString( const LogLevel level ) { static const char* const buf[] = { "NONE", "FATAL", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4" }; return buf[level]; } LogLevel Logger::fromString( const string& level ) { if( level == "DEBUG4" ) return logDEBUG4; if( level == "DEBUG3" ) return logDEBUG3; if( level == "DEBUG2" ) return logDEBUG2; if( level == "DEBUG1") return logDEBUG1; if( level == "DEBUG") return logDEBUG; if( level == "INFO") return logINFO; if( level == "NOTICE" ) return logNOTICE; if( level == "WARNING" ) return logWARNING; if( level == "ERROR" ) return logERROR; if( level == "CRITICAL" ) return logCRITICAL; if( level == "FATAL" ) return logFATAL; if( level == "NONE" ) return logNONE; LOG( logWARNING ) << "Unknown log level '" << level << "'. Using INFO level as default."; return logINFO; } Logger::Logger( ) { m_impl.reset( new LoggerImpl( ) ); } Logger::~Logger( ) { } void Logger::addSink( LogSink *sink ) { m_impl->addSink( sink ); } void Logger::removeSink( LogSink *sink ) { m_impl->removeSink( sink ); } void Logger::log( const LogLevel level, const string &msg ) { m_impl->log( level, msg ); } void Logger::openConsoleLog( const LogLevel level ) { m_impl->openConsoleLog( level ); } void Logger::openFileLog( const LogLevel level, const std::string &filename ) { m_impl->openFileLog( level, filename ); } void Logger::openSyslog( const LogLevel level, const string &ident, const string &facility ) { m_impl->openSyslog( level, ident, facility ); } void Logger::openWinDbgLog( const LogLevel level ) { m_impl->openWinDbgLog( level ); }