PixelLightAPI
.
|
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__
|