PixelLightAPI  .
Log.h
Go to the documentation of this file.
00001 /*********************************************************\
00002  *  File: Log.h                                          *
00003  *
00004  *  Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/)
00005  *
00006  *  This file is part of PixelLight.
00007  *
00008  *  PixelLight is free software: you can redistribute it and/or modify
00009  *  it under the terms of the GNU Lesser General Public License as published by
00010  *  the Free Software Foundation, either version 3 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  PixelLight is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  *  GNU Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public License
00019  *  along with PixelLight. If not, see <http://www.gnu.org/licenses/>.
00020 \*********************************************************/
00021 
00022 
00023 #ifndef __PLCORE_LOG_H__
00024 #define __PLCORE_LOG_H__
00025 #pragma once
00026 
00027 
00028 //[-------------------------------------------------------]
00029 //[ Includes                                              ]
00030 //[-------------------------------------------------------]
00031 #include "PLCore/Core/Singleton.h"
00032 #include "PLCore/Container/Queue.h"
00033 #include "PLCore/Base/Event/Event.h"
00034 
00035 
00036 //[-------------------------------------------------------]
00037 //[ Macro definitions                                     ]
00038 //[-------------------------------------------------------]
00039 /**
00040 *  @brief
00041 *    Log macro
00042 *
00043 *  @param[in] Level
00044 *    Log level
00045 *  @param[in] Text
00046 *    Text which should be written into the log
00047 */
00048 #define PL_LOG(Level, Text) { \
00049     if (PLCore::Log::HasInstance() && PLCore::Log::GetInstance()->GetLogLevel() >= PLCore::Log::Level) { \
00050         PLCore::Log::LogLevel nLogLevel = PLCore::Log::Level; /* Avoid 'expression is constant' warning */ \
00051         if (nLogLevel >= PLCore::Log::Debug) { \
00052             PLCore::String sLogString = Text; \
00053             PLCore::Log::GetInstance()->Output(PLCore::Log::Level, sLogString + PLCore::String::Format(", %s, %d, %s", __FILE__, __LINE__, __FUNCTION__)); \
00054         } else PLCore::Log::GetInstance()->Output(PLCore::Log::Level, Text); \
00055     } \
00056 }
00057 
00058 
00059 //[-------------------------------------------------------]
00060 //[ Namespace                                             ]
00061 //[-------------------------------------------------------]
00062 namespace PLCore {
00063 
00064 
00065 //[-------------------------------------------------------]
00066 //[ Forward declarations                                  ]
00067 //[-------------------------------------------------------]
00068 class LogFormatter;
00069 
00070 
00071 //[-------------------------------------------------------]
00072 //[ Classes                                               ]
00073 //[-------------------------------------------------------]
00074 /**
00075 *  @brief
00076 *    Log system class
00077 *
00078 *  @note
00079 *    - A configurable amount of messages is hold in a queue (the last n-messages)
00080 *    - When the queue is full a flush is done
00081 *    - A flush is also done if a specified log level is used in the output function (configurable)
00082 *    - A specified log level includes also all log levels with lower values
00083 *      e.g.: if the overall log level is set to info, log messages marked as
00084 *      warning, error or critical are written to the log, too
00085 *    - You can define as many debug log levels as you want
00086 *    - Implementation of the strategy design pattern, this class is the context
00087 */
00088 class Log : public Singleton<Log> {
00089 
00090 
00091     //[-------------------------------------------------------]
00092     //[ Friends                                               ]
00093     //[-------------------------------------------------------]
00094     friend class Singleton<Log>;
00095 
00096 
00097     //[-------------------------------------------------------]
00098     //[ Public definitions                                    ]
00099     //[-------------------------------------------------------]
00100     public:
00101         /**
00102         *  @brief
00103         *    Log levels
00104         *
00105         *  @remarks
00106         *    The log level 0 is reserved for messages which are generated from the
00107         *    log system itself.
00108         */
00109         enum LogLevel {
00110             Quiet = 1,  /**< No log outputs */
00111             Always,     /**< Should be used if the message should be logged always */
00112             Critical,   /**< Should be used if an critical error occurs */
00113             Error,      /**< Should be used if an error occurs */
00114             Warning,    /**< Should be used for warning texts */
00115             Info,       /**< Should be used for info texts */
00116             Debug       /**< Should be used for debug level texts */
00117         };
00118 
00119 
00120     //[-------------------------------------------------------]
00121     //[ Public events                                         ]
00122     //[-------------------------------------------------------]
00123     public:
00124         Event<> EventNewEntry;  /**< A new log entry had been added, use e.g. "GetLastMessages()" to access the latest messages */
00125 
00126 
00127     //[-------------------------------------------------------]
00128     //[ Public static PLCore::Singleton functions             ]
00129     //[-------------------------------------------------------]
00130     // This solution enhances the compatibility with legacy compilers like GCC 4.2.1 used on Mac OS X 10.6
00131     // -> The C++11 feature "extern template" (C++11, see e.g. http://www2.research.att.com/~bs/C++0xFAQ.html#extern-templates) can only be used on modern compilers like GCC 4.6
00132     // -> We can't break legacy compiler support, especially when only the singletons are responsible for the break
00133     // -> See PLCore::Singleton for more details about singletons
00134     public:
00135         static PLCORE_API Log *GetInstance();
00136         static PLCORE_API bool HasInstance();
00137 
00138 
00139     //[-------------------------------------------------------]
00140     //[ Public functions                                      ]
00141     //[-------------------------------------------------------]
00142     public:
00143         /**
00144         *  @brief
00145         *    Get verbose mode (write log entries to console)
00146         *
00147         *  @return
00148         *    'true' if the log is writing into the console, else 'false'
00149         *
00150         *  @note
00151         *    - In addition to using an optional log formatter, the log also writes into the console in verbose mode
00152         *    - The log does not need be to be opened to write into the console
00153         *    - Android: Messages are not written into the console, instead the Android in-kernel log buffer is used
00154         *              (use Androids "logcat" utility to access this system log)
00155         *    - By default the log does not write into the console
00156         */
00157         inline bool IsVerbose() const;
00158 
00159         /**
00160         *  @brief
00161         *    Set verbose mode (write log entries to console)
00162         *
00163         *  @param[in] bVerbose
00164         *    'true' if the log is writing into the console, else 'false'
00165         *  @param[in] bVerboseLogLevelPrefix
00166         *    Should the [LogLevel] prefix be shown?
00167         *
00168         *  @see
00169         *    - IsVerbose()
00170         */
00171         inline void SetVerbose(bool bVerbose, bool bVerboseLogLevelPrefix = true);
00172 
00173         /**
00174         *  @brief
00175         *    Open the log file by using a filename
00176         *
00177         *  @param[in] sFilename
00178         *    The log's filename, the log formatter is automatically created by using the filename extension
00179         *
00180         *  @return
00181         *    'true' if all went fine, else 'false' (maybe the log is already opened or the filename extension is not supported?)
00182         *
00183         *  @note
00184         *    - Supported log filename extensions: "txt" (LogFormatterText), "log" (LogFormatterText), "xml" (LogFormatterXml), "html" (LogFormatterHtml)
00185         */
00186         PLCORE_API bool Open(const String &sFilename);
00187 
00188         /**
00189         *  @brief
00190         *    Open the log file by using a filename and an explicit log formatter instance
00191         *
00192         *  @param[in] sFilename
00193         *    The log's filename
00194         *  @param[in] cLogFormatter
00195         *    Log formatter instance to be used, if this method returns successfully, the log takes over
00196         *    the control and is responsible for the destruction of the given instance
00197         *
00198         *  @return
00199         *    'true' if all went fine, else 'false' (maybe the log is already opened?)
00200         */
00201         PLCORE_API bool Open(const String &sFilename, LogFormatter &cLogFormatter);
00202 
00203         /**
00204         *  @brief
00205         *    Close log
00206         *
00207         *  @return
00208         *    'true' if all went fine, else 'false'
00209         */
00210         PLCORE_API bool Close();
00211 
00212         /**
00213         *  @brief
00214         *    Get log filename
00215         *
00216         *  @return
00217         *    The log filename
00218         */
00219         inline String GetFilename() const;
00220 
00221         /**
00222         *  @brief
00223         *    Write a string into the log
00224         *
00225         *  @param[in] nLogLevel
00226         *    Log level
00227         *  @param[in] sText
00228         *    Text which should be written into the log
00229         *
00230         *  @return
00231         *    'true' if all went fine, else 'false'
00232         *
00233         *  @remarks
00234         *    The text is written to the log only if the current
00235         *    log level is greater or equal to the specified value.
00236         */
00237         inline bool Output(uint8 nLogLevel, const String &sText);
00238 
00239         /**
00240         *  @brief
00241         *    Get current log level
00242         *
00243         *  @return
00244         *    The current log level
00245         */
00246         inline uint8 GetLogLevel() const;
00247 
00248         /**
00249         *  @brief
00250         *    Set current log level
00251         *
00252         *  @param[in] nLogLevel
00253         *    New current log level
00254         */
00255         inline void SetLogLevel(uint8 nLogLevel = Info);
00256 
00257         /**
00258         *  @brief
00259         *    Get log level for automatic flush
00260         *
00261         *  @return
00262         *    Log level for explicitly flush
00263         */
00264         inline uint8 GetFlushLogLevel() const;
00265 
00266         /**
00267         *  @brief
00268         *    Set log level for automatic flush
00269         *
00270         *  @param[in] nFlushLogLevel
00271         *    Log level for the explicitly flush
00272         */
00273         inline void SetFlushLogLevel(uint8 nFlushLogLevel = Error);
00274 
00275         /**
00276         *  @brief
00277         *    Flush output buffer to disk
00278         *
00279         *  @return
00280         *    'true' if all went fine, else 'false' (maybe there was nothing to flush?)
00281         *
00282         *  @note
00283         *    - Only call this function if really required!
00284         */
00285         inline bool Flush();
00286 
00287         /**
00288         *  @brief
00289         *    Get current amount of buffered log messages
00290         *
00291         *  @return
00292         *    Amount of buffered log messages
00293         */
00294         inline uint32 GetBufferCount() const;
00295 
00296         /**
00297         *  @brief
00298         *    Set how many log messages should be buffered in memory
00299         *
00300         *  @param[in] nBufferCount
00301         *    Number of messages to buffer
00302         *
00303         *  @note
00304         *    The nBufferCount-last log messages gets buffered
00305         */
00306         PLCORE_API void SetBufferCount(uint32 nBufferCount = 1000);
00307 
00308         /**
00309         *  @brief
00310         *    Get a copy of the queue which holds the last log messages
00311         *
00312         *  @return
00313         *    Queue of n-last log messages
00314         */
00315         inline const Queue<String> &GetLastMessages() const;
00316 
00317         /**
00318         *  @brief
00319         *    Get a string representation of the given log level
00320         *
00321         *  @param[in] nLogLevel
00322         *    Log level to return the string representation from
00323         *
00324         *  @return
00325         *    The string representation of the given log level
00326         */
00327         PLCORE_API String LogLevelToString(uint8 nLogLevel) const;
00328 
00329         /**
00330         *  @brief
00331         *    Get log formatter
00332         *
00333         *  @return
00334         *    The current log formatter object, can be a null pointer, do NOT delete the returned instance!
00335         */
00336         inline LogFormatter *GetLogFormatter() const;
00337 
00338 
00339     //[-------------------------------------------------------]
00340     //[ Private functions                                     ]
00341     //[-------------------------------------------------------]
00342     private:
00343         /**
00344         *  @brief
00345         *    Constructor
00346         */
00347         Log();
00348 
00349         /**
00350         *  @brief
00351         *    Copy constructor
00352         *
00353         *  @param[in] cSource
00354         *    Source to copy from
00355         */
00356         Log(const Log &cSource);
00357 
00358         /**
00359         *  @brief
00360         *    Destructor
00361         */
00362         virtual ~Log();
00363 
00364         /**
00365         *  @brief
00366         *    Copy operator
00367         *
00368         *  @param[in] cSource
00369         *    Source to copy from
00370         *
00371         *  @return
00372         *    Reference to this instance
00373         */
00374         Log &operator =(const Log &cSource);
00375 
00376         /**
00377         *  @brief
00378         *    Write a string into the log
00379         *
00380         *  @param[in] nLogLevel
00381         *    Log Level
00382         *  @param[in] sText
00383         *    Text which should be written into the log
00384         *
00385         *  @return
00386         *    'true' if all went fine, else 'false'
00387         */
00388         PLCORE_API bool Write(uint8 nLogLevel, const String &sText);
00389 
00390 
00391     //[-------------------------------------------------------]
00392     //[ Private data                                          ]
00393     //[-------------------------------------------------------]
00394     private:
00395         bool           m_bVerbose;                  /**< Write into the standard OS console? */
00396         bool           m_bVerboseLogLevelPrefix;    /**< Indicates if the [LogLevel] prefix should be shown within the standard OS console output */
00397         String         m_sFilename;                 /**< Filename */
00398         uint8          m_nLogLevel;                 /**< Current log level mode (see LogLevel) */
00399         uint8          m_nFlushLogLevel;            /**< If this log level is used the the flush is explicitly done */
00400         uint32         m_nFlushMessages;            /**< Holds the number of messages since the last flush */
00401         Queue<String>  m_qLastMessages;             /**< Holds the last log messages */
00402         uint32         m_nBufferedMessages;         /**< How much messages should be buffered */
00403         LogFormatter  *m_pLogFormatter;             /**< Holds an instance of a log formatter class, can be a null pointer */
00404 
00405 
00406 };
00407 
00408 
00409 //[-------------------------------------------------------]
00410 //[ Namespace                                             ]
00411 //[-------------------------------------------------------]
00412 } // PLCore
00413 
00414 
00415 //[-------------------------------------------------------]
00416 //[ Implementation                                        ]
00417 //[-------------------------------------------------------]
00418 #include "PLCore/Log/Log.inl"
00419 
00420 
00421 #endif // __PLCORE_LOG_H__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:08:56
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported