OpenWalnut  1.4.0
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 
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 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      * Remove the given stream.
00079      *
00080      * \param s the stream to remove
00081      */
00082     void removeStream( WLogStream::SharedPtr s );
00083 
00084     /**
00085      * Set the default format used for log entries.
00086      *
00087      * \param format the format string. See WLogEntry for details.
00088      */
00089     void setDefaultFormat( std::string format );
00090 
00091     /**
00092      * Set the default log-level used for log entries in default console-output
00093      *
00094      * \param level the log-level
00095      */
00096     void setDefaultLogLevel( const LogLevel& level );
00097 
00098     /**
00099      * Gets the default format used for log entries. This actually returns the format of the first log stream.
00100      *
00101      * \return format string. See WLogEntry for details.
00102      */
00103     std::string getDefaultFormat();
00104 
00105     /**
00106      * Appends a log message to the logging queue.
00107      * \param message the log entry
00108      * \param source indicates where this entry comes from
00109      * \param level The logging level of the current message
00110      */
00111     void addLogMessage( std::string message, std::string source = "", LogLevel level = LL_DEBUG );
00112 
00113     /**
00114      * Types of signals supported by the logger
00115      */
00116     typedef enum
00117     {
00118         AddLog = 0 //!< for added logs
00119     }
00120     LogEvent;
00121 
00122     /**
00123      * The type for all callbacks which get a log entry as parameter.
00124      */
00125     typedef boost::function< void ( WLogEntry& ) > LogEntryCallback;
00126 
00127     /**
00128      * Subscribe to the specified signal.
00129      *
00130      * \note If you want to listen to incoming log entries, you can also utilize the WLogStream class.
00131      *
00132      * \param event the kind of signal the callback should be used for.
00133      * \param callback the callback.
00134      *
00135      * \return the connection object. Disconnect it explicitly!
00136      */
00137     boost::signals2::connection subscribeSignal( LogEvent event, LogEntryCallback callback );
00138 
00139 protected:
00140 private:
00141     /**
00142      * Constructor. The logger is created using the static method startup.
00143      *
00144      * \param output the stream where to print log messages to
00145      * \param level logging level, i.e. verboseness
00146      */
00147     WLogger( std::ostream& output, LogLevel level );  // NOLINT - we need this non-const ref here
00148 
00149     /**
00150      * We do not want a copy constructor, so we define it private.
00151      */
00152     WLogger( const WLogger& );
00153 
00154     /**
00155      * The output stream list type.
00156      */
00157     typedef WSharedSequenceContainer< std::vector< WLogStream::SharedPtr > > Outputs;
00158 
00159     /**
00160      * The list of outputs to print the messages to.
00161      */
00162     Outputs m_outputs;
00163 
00164     /**
00165      * Signal called whenever a new log message arrives.
00166      */
00167     boost::signals2::signal< void( WLogEntry& ) > m_addLogSignal;
00168 };
00169 
00170 /**
00171  * This namespace collects several convenient access points such as wlog::err
00172  * for logging with streams to our WLogger.
00173  */
00174 namespace wlog
00175 {
00176     /**
00177      * Resource class for streamed logging.
00178      */
00179     class WStreamedLogger // NOLINT
00180     {
00181     public:
00182         /**
00183          * Creates new streamed logger instance. Logging is deferred until
00184          * destruction of this instance.
00185          *
00186          * \param source Source from which the log message originates
00187          * \param level The LogLevel of the message
00188          */
00189         WStreamedLogger( const std::string& source, LogLevel level );
00190 
00191         /**
00192          * Appends something loggable (to std::string castable) to the log.
00193          *
00194          * \param loggable Token that should be streamed into the Logger
00195          * \return The streamed logger for further use
00196          */
00197         template< typename T > WStreamedLogger operator<<( const T& loggable );
00198 
00199         // Doxygen should ignore the TypeDef below which are just an alias for std::endl etc.
00200         // \cond Suppress_Doxygen
00201         typedef std::basic_ostream< char, std::char_traits< char > > OutStreamType;
00202         typedef OutStreamType& ( *StreamManipulatorFunctor )( OutStreamType& );
00203         // \endcond
00204 
00205         /**
00206          * This is totally crazy man! Don't get dizzy on that, watch out and
00207          * ask a C++ guru next to your side, which is probably named Christian
00208          * or have a look on that: http://stackoverflow.com/questions/1134388/stdendl-is-of-unknown-type-when-overloading-operator
00209          *
00210          * Allow std::endl to be streamed into log messages.
00211          *
00212          * \param manip Function pointer e.g. std::endl, std::flush, std::ends
00213          * \return The streamed logger for further use
00214          */
00215         WStreamedLogger operator<<( StreamManipulatorFunctor manip );
00216 
00217     protected:
00218     private:
00219         /**
00220          * Actually implementing the streaming functionality.
00221          */
00222         class Buffer
00223         {
00224         public: // NOLINT inner classes may have also lables
00225             /**
00226              * Constructs a new stream for logging.
00227              *
00228              * \param source String identifying the source of the message
00229              * \param level LogLevel of the message
00230              */
00231             Buffer( const std::string& source, LogLevel level );
00232 
00233             /**
00234              * Commits the logging expression to our WLogger
00235              */
00236             virtual ~Buffer();
00237 
00238             std::ostringstream m_logString; //!< queuing up parts of the log message
00239             LogLevel m_level; //!< Default logging level for this stream
00240             std::string m_source; //!< The source of the logging message
00241         };
00242 
00243         /**
00244          * Forbid assignment
00245          *
00246          * \param rhs The instance which SHOULD be copied over
00247          * \return A reference to the variable for which assignment was INTENDED.
00248          */
00249         WStreamedLogger& operator=( const WStreamedLogger& rhs );
00250 
00251         boost::shared_ptr< Buffer > m_buffer; //!< Collects the message parts.
00252     };
00253 
00254     inline WStreamedLogger::WStreamedLogger( const std::string& source, LogLevel level )
00255         : m_buffer( new Buffer( source, level ) )
00256     {
00257     }
00258 
00259     template< typename T > inline WStreamedLogger WStreamedLogger::operator<<( const T& loggable )
00260     {
00261         using string_utils::operator<<; // in case we want to log arrays or vectors
00262         m_buffer->m_logString << loggable;
00263         return *this;
00264     }
00265 
00266     inline WStreamedLogger WStreamedLogger::operator<<( StreamManipulatorFunctor manip )
00267     {
00268         manip( m_buffer->m_logString );
00269         return *this;
00270     }
00271 
00272     inline WStreamedLogger::Buffer::Buffer( const std::string& source, LogLevel level )
00273         : m_logString(),
00274         m_level( level ),
00275         m_source( source )
00276     {
00277     }
00278 
00279     /**
00280      * Convenient function for logging messages to our WLogger but not for
00281      * public use outside of this module.
00282      *
00283      * \param source Indicate the source where this log message origins.
00284      * \param level The LogLevel of this message
00285      * \return The logger created using the functions parameters
00286      */
00287     inline WStreamedLogger _wlog( const std::string& source, LogLevel level )
00288     {
00289         return WStreamedLogger( source, level );
00290     }
00291 
00292     /**
00293      * Logging an error message.
00294      *
00295      * \param source Indicate the source where this log message origins.
00296      * \return The logger with the error message.
00297      */
00298     inline WStreamedLogger error( const std::string& source )
00299     {
00300         return _wlog( source, LL_ERROR );
00301     }
00302 
00303     /**
00304      * Logging a warning message.
00305      *
00306      * \param source Indicate the source where this log message origins.
00307      * \return The logger with the warning message.
00308      */
00309     inline WStreamedLogger warn( const std::string& source )
00310     {
00311         return _wlog( source, LL_WARNING );
00312     }
00313 
00314     /**
00315      * Logging an information message.
00316      *
00317      * \param source Indicate the source where this log message origins.
00318      * \return The logger with the warning message.
00319      */
00320     inline WStreamedLogger info( const std::string& source )
00321     {
00322         return _wlog( source, LL_INFO );
00323     }
00324 
00325     /**
00326      * Logging a debug message.
00327      *
00328      * \param source Indicate the source where this log message origins.
00329      * \return The logger with the debug message.
00330      */
00331     inline WStreamedLogger debug( const std::string& source )
00332     {
00333         return _wlog( source, LL_DEBUG );
00334     }
00335 } // end of namespace log
00336 
00337 #endif  // WLOGGER_H