WLogger.h 10.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

#ifndef WLOGGER_H
#define WLOGGER_H

#include <queue>
29
#include <sstream>
30
#include <string>
31 32 33
#include <vector>

#include <boost/shared_ptr.hpp>
schurade's avatar
schurade committed
34
#include <boost/thread/locks.hpp>
35 36
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
37 38

#include "WLogEntry.h"
39
#include "WStringUtils.h"
40
#include "WThreadedRunner.h"
41
#include "WExportCommon.h"
42 43

/**
44
 * Does actual logging of WLogEntries down to stdout or something similar.
45
 */
46
class EXPORT_OWCOMMON_DLL WLogger: public WThreadedRunner
47 48 49 50
{
public:
    /**
     * Constructor
51 52
     * \param fileName the log will be stored in this file
     * \param level logging level, i.e. verboseness
53
     */
schurade's avatar
schurade committed
54
    WLogger( std::string fileName = "walnut.log", LogLevel level = LL_DEBUG );
55 56 57 58 59 60

    /**
     * Destructor.
     */
    virtual ~WLogger();

61
    /**
62
     * Returns pointer to the currently running logger instance.
63 64 65 66 67
     *
     * \return pointer to logger instance.
     */
    static WLogger* getLogger();

68
    /**
69
     * Sets the global log level
70
     * \param level the new global logging level
71 72 73 74
     */
    void setLogLevel( LogLevel level );

    /**
75
     * Sets the log level for stdout.
76
     * \param level the new logging level for stdout
77 78 79 80
     */
    void setSTDOUTLevel( LogLevel level );

    /**
81
     * Sets the log level for stderr.
82
     * \param level the new logging level for stderr
83 84 85 86
     */
    void setSTDERRLevel( LogLevel level );

    /**
87
     * Sets the log level for the given log file.
88
     * \param level the new level for logging to file
89 90 91 92
     */
    void setLogFileLevel( LogLevel level );

    /**
93 94
     * Specifies the path for logging to this file and checks if the path
     * exists by an assertion.
95
     * \param fileName the name and path of the file to be used for logging.
96 97 98
     */
    void setLogFileName( std::string fileName );

99 100
    /**
     * Set whether to use colors or not. Note: this is only useful on Linux systems currently.
101
     *
102 103 104 105 106 107
     * \param colors true if colors should be used.
     */
    void setColored( bool colors );

    /**
     * Getter determining whether to use colors or not.
108
     *
109 110 111 112
     * \return true if colors should be used.
     */
    bool isColored();

113 114
    /**
     * Set the default format used for log entries.
115
     *
116 117 118 119 120 121
     * \param format the format string. See WLogEntry for details.
     */
    void setDefaultFormat( std::string format );

    /**
     * Gets the default format used for log entries.
122
     *
123 124 125 126
     * \return format string. See WLogEntry for details.
     */
    std::string getDefaultFormat();

127 128
    /**
     * Set the default format used for log entries in log files.
129
     *
130 131 132 133 134 135
     * \param format the format string. See WLogEntry for details.
     */
    void setDefaultFileFormat( std::string format );

    /**
     * Gets the default format used for log entries in log files.
136
     *
137 138 139
     * \return format string. See WLogEntry for details.
     */
    std::string getDefaultFileFormat();
140

141
    /**
142
     * Appends a log message to the logging queue.
143 144 145
     * \param message the log entry
     * \param source indicates where this entry comes from
     * \param level The logging level of the current message
146 147 148 149
     */
    void addLogMessage( std::string message, std::string source = "", LogLevel level = LL_DEBUG );

    /**
150 151
     * Locks this logging instance for threadsafeness and prints the
     * items of the queue.
152 153 154
     */
    void processQueue();

schurade's avatar
schurade committed
155 156 157 158 159
    /**
     * Entry point after loading the module. Runs in separate thread.
     */
    virtual void threadMain();

160
protected:
schurade's avatar
schurade committed
161 162

private:
163 164 165
    /**
     * We do not want a copy constructor, so we define it private.
     */
166
    WLogger( const WLogger& );
167

168
    /**
169 170
     * The actual level of logging so messages with a lower level will be
     * discarded.
171 172 173 174
     */
    LogLevel m_LogLevel;

    /**
175
     * LogLevel for stdout
176 177 178 179
     */
    LogLevel m_STDOUTLevel;

    /**
180
     * LogLevel for stderr
181 182 183 184
     */
    LogLevel m_STDERRLevel;

    /**
185
     * LogLevel for the given log file
186 187 188 189
     */
    LogLevel m_LogFileLevel;

    /**
190
     * Filename of the log file
191 192 193 194
     */
    std::string m_LogFileName;

    /**
195
     * Storage for all WLogEntries that were given to our logging instance
196 197 198 199
     */
    std::vector< WLogEntry > m_SessionLog;

    /**
200
     * Queue for storing pending WLogEntries.
201 202 203 204
     */
    std::queue< WLogEntry > m_LogQueue;

    /**
205
     * Mutex for doing locking due to thread-safety.
206
     */
schurade's avatar
schurade committed
207
    boost::mutex m_QueueMutex;
208 209 210 211 212

    /**
     * Flag determining whether log entries can be colored or not.
     */
    bool m_colored;
213 214 215 216 217

    /**
     * The default format used for new log entries.
     */
    std::string m_defaultFormat;
218 219 220 221 222

    /**
     * The default format used for new log entries in files.
     */
    std::string m_defaultFileFormat;
223 224
};

225 226 227 228 229 230 231
/**
 * This namespace collects several convinient access points such as wlog::err
 * for logging with streams to our WLogger.
 */
namespace wlog
{
    /**
232
     * Resource class for streamed logging.
233
     */
234 235 236 237 238 239 240 241 242 243 244
    class WStreamedLogger
    {
    public:
        /**
         * Creates new streamed logger instance. Logging is deferred until
         * destruction of this instance.
         *
         * \param source Source from which the log message originates
         * \param level The LogLevel of the message
         */
        WStreamedLogger( const std::string& source, LogLevel level );
245

246 247 248 249 250 251 252
        /**
         * Appends something loggable (to std::string castable) to the log.
         *
         * \param loggable Token that should be streamed into the Logger
         * \return The streamed logger for further use
         */
        template< typename T > WStreamedLogger operator<<( const T& loggable );
253

254 255 256 257 258
        // Doxygen should ignore the TypeDef below which are just an alias for std::endl etc.
        // \cond
        typedef std::basic_ostream< char, std::char_traits< char > > OutStreamType;
        typedef OutStreamType& ( *StreamManipulatorFunctor )( OutStreamType& );
        // \endcond
259 260


261
        /**
262
         * This is totally crazy man! Don't get dizzy on that, watch out and
263 264 265 266
         * ask a C++ guru next to your side, which is probably named Christian
         * or have a look on that: http://stackoverflow.com/questions/1134388/stdendl-is-of-unknown-type-when-overloading-operator
         *
         * Allow std::endl to be streamed into log messages.
267
         *
268 269
         * \param manip Function pointer e.g. std::endl, std::flush, std::ends
         * \return The streamed logger for further use
270
         */
271
        WStreamedLogger operator<<( StreamManipulatorFunctor manip );
272

273 274
    protected:
    private:
275
        /**
276
         * Actually implementing the streaming functionality.
277
         */
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
        class Buffer
        {
        public: // NOLINT inner classes may have also lables
            /**
             * Constructs a new stream for logging.
             *
             * \param source String identifying the source of the message
             * \param level LogLevel of the message
             */
            Buffer( const std::string& source, LogLevel level );

            /**
             * Commits the logging expression to our WLogger
             */
            virtual ~Buffer();

            std::ostringstream m_logString; //!< queuing up parts of the log message
            LogLevel m_level; //!< Default logging level for this stream
            std::string m_source; //!< The source of the logging message
        };
298

299 300 301 302 303 304
        /**
         * Forbid assignment
         *
         * \param rhs The instance which SHOULD be copied over
         */
        WStreamedLogger& operator=( const WStreamedLogger& rhs );
305

306 307
        boost::shared_ptr< Buffer > m_buffer; //!< Collects the message parts.
    };
308

309 310 311 312
    inline WStreamedLogger::WStreamedLogger( const std::string& source, LogLevel level )
        : m_buffer( new Buffer( source, level ) )
    {
    }
313

314 315
    template< typename T > inline WStreamedLogger WStreamedLogger::operator<<( const T& loggable )
    {
316
        using string_utils::operator<<; // incase we want to log arrays or vectors
317 318 319
        m_buffer->m_logString << loggable;
        return *this;
    }
320

321 322 323 324 325
    inline WStreamedLogger WStreamedLogger::operator<<( StreamManipulatorFunctor manip )
    {
        manip( m_buffer->m_logString );
        return *this;
    }
326

327 328 329 330
    inline WStreamedLogger::Buffer::~Buffer()
    {
        WLogger::getLogger()->addLogMessage( m_logString.str(), m_source, m_level );
    }
331

332 333 334 335 336 337
    inline WStreamedLogger::Buffer::Buffer( const std::string& source, LogLevel level )
        : m_logString(),
        m_level( level ),
        m_source( source )
    {
    }
338

339 340 341 342 343 344 345 346 347 348 349
    /**
     * Convinient function for logging messages to our WLogger but not for
     * public use outside of this module.
     *
     * \param source Indicate the source where this log message origins.
     * \param level The LogLevel of this message
     */
    inline WStreamedLogger _wlog( const std::string& source, LogLevel level )
    {
        return WStreamedLogger( source, level );
    }
350

351 352 353 354 355 356 357 358 359
    /**
     * Logging an error message.
     *
     * \param source Indicate the source where this log message origins.
     */
    inline WStreamedLogger error( const std::string& source )
    {
        return _wlog( source, LL_ERROR );
    }
360

361 362 363 364 365 366 367 368 369
    /**
     * Loggin a warning message.
     *
     * \param source Indicate the source where this log message origins.
     */
    inline WStreamedLogger warn( const std::string& source )
    {
        return _wlog( source, LL_WARNING );
    }
370

371 372 373 374 375 376 377 378 379
    /**
     * Loggin an information message.
     *
     * \param source Indicate the source where this log message origins.
     */
    inline WStreamedLogger info( const std::string& source )
    {
        return _wlog( source, LL_INFO );
    }
380

381 382 383 384 385 386 387 388 389
    /**
     * Loggin a debug message.
     *
     * \param source Indicate the source where this log message origins.
     */
    inline WStreamedLogger debug( const std::string& source )
    {
        return _wlog( source, LL_DEBUG );
    }
390 391
} // end of namespace log

392
#endif  // WLOGGER_H