WLogger.h

00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WLOGGER_H
00026 #define WLOGGER_H
00027 
00028 #include <ostream>
00029 #include <sstream>
00030 #include <string>
00031 #include <vector>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 #include <boost/signals2/signal.hpp>
00035 
00036 #include "WLogEntry.h"
00037 #include "WLogStream.h"
00038 #include "WStringUtils.h"
00039 #include "WSharedSequenceContainer.h"
00040 #include "WExportCommon.h"
00041 
00042 /**
00043  * This class defines the interface for adding logs and managing several output streams for them. The actual log entry is in \ref WLogEntry and
00044  * the output is done in \ref WLogStream.
00045  */
00046 class OWCOMMON_EXPORT WLogger       // NOLINT
00047 {
00048 public:
00049     /**
00050      * Create the first and only instance of the logger as it is a singleton.
00051      *
00052      * \param output the output stream to use
00053      * \param level the default log level
00054      */
00055     static void startup( std::ostream& output = std::cout, LogLevel level = LL_DEBUG );  // NOLINT - we need this non-const ref here
00056 
00057     /**
00058      * Destructor.
00059      */
00060     virtual ~WLogger();
00061 
00062     /**
00063      * Returns pointer to the currently running logger instance.
00064      *
00065      * \return pointer to logger instance.
00066      */
00067     static WLogger* getLogger();
00068 
00069     /**
00070      * Adds a new stream to the logger. This is useful to register file streams or uncolored GUI based outputs.
00071      * \note It is not intended to allow getting streams or modifying them except you are the owner/creator.
00072      *
00073      * \param s the stream to add.
00074      */
00075     void addStream( WLogStream::SharedPtr s );
00076 
00077     /**
00078      * Set the default format used for log entries.
00079      *
00080      * \param format the format string. See WLogEntry for details.
00081      */
00082     void setDefaultFormat( std::string format );
00083 
00084     /**
00085      * Set the default log-level used for log entries in default console-output
00086      *
00087      * \param level the log-level
00088      */
00089     void setDefaultLogLevel( const LogLevel& level );
00090 
00091     /**
00092      * Gets the default format used for log entries. This actually returns the format of the first log stream.
00093      *
00094      * \return format string. See WLogEntry for details.
00095      */
00096     std::string getDefaultFormat();
00097 
00098     /**
00099      * Appends a log message to the logging queue.
00100      * \param message the log entry
00101      * \param source indicates where this entry comes from
00102      * \param level The logging level of the current message
00103      */
00104     void addLogMessage( std::string message, std::string source = "", LogLevel level = LL_DEBUG );
00105 
00106     /**
00107      * Types of signals supported by the logger
00108      */
00109     typedef enum
00110     {
00111         AddLog = 0 //!< for added logs
00112     }
00113     LogEvent;
00114 
00115     /**
00116      * The type for all callbacks which get a log entry as parameter.
00117      */
00118     typedef boost::function< void ( WLogEntry& ) > LogEntryCallback;
00119 
00120     /**
00121      * Subscribe to the specified signal.
00122      *
00123      * \note If you want to listen to incoming log entries, you can also utilize the WLogStream class.
00124      *
00125      * \param event the kind of signal the callback should be used for.
00126      * \param callback the callback.
00127      *
00128      * \return the connection object. Disconnect it explicitly!
00129      */
00130     boost::signals2::connection subscribeSignal( LogEvent event, LogEntryCallback callback );
00131 
00132 protected:
00133 
00134 private:
00135     /**
00136      * Constructor. The logger is created using the static method startup.
00137      *
00138      * \param output the stream where to print log messages to
00139      * \param level logging level, i.e. verboseness
00140      */
00141     WLogger( std::ostream& output, LogLevel level );  // NOLINT - we need this non-const ref here
00142 
00143     /**
00144      * We do not want a copy constructor, so we define it private.
00145      */
00146     WLogger( const WLogger& );
00147 
00148     /**
00149      * The output stream list type.
00150      */
00151     typedef WSharedSequenceContainer< std::vector< WLogStream::SharedPtr > > Outputs;
00152 
00153     /**
00154      * The list of outputs to print the messages to.
00155      */
00156     Outputs m_outputs;
00157 
00158     /**
00159      * Signal called whenever a new log message arrives.
00160      */
00161     boost::signals2::signal< void( WLogEntry& ) > m_addLogSignal;
00162 };
00163 
00164 /**
00165  * This namespace collects several convenient access points such as wlog::err
00166  * for logging with streams to our WLogger.
00167  */
00168 namespace wlog
00169 {
00170     /**
00171      * Resource class for streamed logging.
00172      */
00173     class OWCOMMON_EXPORT WStreamedLogger // NOLINT
00174     {
00175     public:
00176         /**
00177          * Creates new streamed logger instance. Logging is deferred until
00178          * destruction of this instance.
00179          *
00180          * \param source Source from which the log message originates
00181          * \param level The LogLevel of the message
00182          */
00183         WStreamedLogger( const std::string& source, LogLevel level );
00184 
00185         /**
00186          * Appends something loggable (to std::string castable) to the log.
00187          *
00188          * \param loggable Token that should be streamed into the Logger
00189          * \return The streamed logger for further use
00190          */
00191         template< typename T > WStreamedLogger operator<<( const T& loggable );
00192 
00193         // Doxygen should ignore the TypeDef below which are just an alias for std::endl etc.
00194         // \cond Suppress_Doxygen
00195         typedef std::basic_ostream< char, std::char_traits< char > > OutStreamType;
00196         typedef OutStreamType& ( *StreamManipulatorFunctor )( OutStreamType& );
00197         // \endcond
00198 
00199         /**
00200          * This is totally crazy man! Don't get dizzy on that, watch out and
00201          * ask a C++ guru next to your side, which is probably named Christian
00202          * or have a look on that: http://stackoverflow.com/questions/1134388/stdendl-is-of-unknown-type-when-overloading-operator
00203          *
00204          * Allow std::endl to be streamed into log messages.
00205          *
00206          * \param manip Function pointer e.g. std::endl, std::flush, std::ends
00207          * \return The streamed logger for further use
00208          */
00209         WStreamedLogger operator<<( StreamManipulatorFunctor manip );
00210 
00211     protected:
00212     private:
00213         /**
00214          * Actually implementing the streaming functionality.
00215          */
00216         class Buffer
00217         {
00218         public: // NOLINT inner classes may have also lables
00219             /**
00220              * Constructs a new stream for logging.
00221              *
00222              * \param source String identifying the source of the message
00223              * \param level LogLevel of the message
00224              */
00225             Buffer( const std::string& source, LogLevel level );
00226 
00227             /**
00228              * Commits the logging expression to our WLogger
00229              */
00230             virtual ~Buffer();
00231 
00232             std::ostringstream m_logString; //!< queuing up parts of the log message
00233             LogLevel m_level; //!< Default logging level for this stream
00234             std::string m_source; //!< The source of the logging message
00235         };
00236 
00237         /**
00238          * Forbid assignment
00239          *
00240          * \param rhs The instance which SHOULD be copied over
00241          * \return A reference to the variable for which assignment was INTENDED.
00242          */
00243         WStreamedLogger& operator=( const WStreamedLogger& rhs );
00244 
00245         boost::shared_ptr< Buffer > m_buffer; //!< Collects the message parts.
00246     };
00247 
00248     inline WStreamedLogger::WStreamedLogger( const std::string& source, LogLevel level )
00249         : m_buffer( new Buffer( source, level ) )
00250     {
00251     }
00252 
00253     template< typename T > inline WStreamedLogger WStreamedLogger::operator<<( const T& loggable )
00254     {
00255         using string_utils::operator<<; // in case we want to log arrays or vectors
00256         m_buffer->m_logString << loggable;
00257         return *this;
00258     }
00259 
00260     inline WStreamedLogger WStreamedLogger::operator<<( StreamManipulatorFunctor manip )
00261     {
00262         manip( m_buffer->m_logString );
00263         return *this;
00264     }
00265 
00266     inline WStreamedLogger::Buffer::Buffer( const std::string& source, LogLevel level )
00267         : m_logString(),
00268         m_level( level ),
00269         m_source( source )
00270     {
00271     }
00272 
00273     /**
00274      * Convenient function for logging messages to our WLogger but not for
00275      * public use outside of this module.
00276      *
00277      * \param source Indicate the source where this log message origins.
00278      * \param level The LogLevel of this message
00279      * \return The logger created using the functions parameters
00280      */
00281     inline WStreamedLogger _wlog( const std::string& source, LogLevel level )
00282     {
00283         return WStreamedLogger( source, level );
00284     }
00285 
00286     /**
00287      * Logging an error message.
00288      *
00289      * \param source Indicate the source where this log message origins.
00290      * \return The logger with the error message.
00291      */
00292     inline WStreamedLogger error( const std::string& source )
00293     {
00294         return _wlog( source, LL_ERROR );
00295     }
00296 
00297     /**
00298      * Logging a warning message.
00299      *
00300      * \param source Indicate the source where this log message origins.
00301      * \return The logger with the warning message.
00302      */
00303     inline WStreamedLogger warn( const std::string& source )
00304     {
00305         return _wlog( source, LL_WARNING );
00306     }
00307 
00308     /**
00309      * Logging an information message.
00310      *
00311      * \param source Indicate the source where this log message origins.
00312      * \return The logger with the warning message.
00313      */
00314     inline WStreamedLogger info( const std::string& source )
00315     {
00316         return _wlog( source, LL_INFO );
00317     }
00318 
00319     /**
00320      * Logging a debug message.
00321      *
00322      * \param source Indicate the source where this log message origins.
00323      * \return The logger with the debug message.
00324      */
00325     inline WStreamedLogger debug( const std::string& source )
00326     {
00327         return _wlog( source, LL_DEBUG );
00328     }
00329 } // end of namespace log
00330 
00331 #endif  // WLOGGER_H
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends