PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: Log.h * 00003 * 00004 * Copyright (C) 2002-2011 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/String/String.h" 00033 #include "PLCore/Container/Queue.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 static PLCore::Singleton functions ] 00122 //[-------------------------------------------------------] 00123 // This solution enhances the compatibility with legacy compilers like GCC 4.2.1 used on Mac OS X 10.6 00124 // -> 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 00125 // -> We can't break legacy compiler support, especially when only the singletons are responsible for the break 00126 // -> See PLCore::Singleton for more details about singletons 00127 public: 00128 static PLCORE_API Log *GetInstance(); 00129 static PLCORE_API bool HasInstance(); 00130 00131 00132 //[-------------------------------------------------------] 00133 //[ Public functions ] 00134 //[-------------------------------------------------------] 00135 public: 00136 /** 00137 * @brief 00138 * Get verbose mode (write log entries to console) 00139 * 00140 * @return 00141 * 'true' if the log is writing into the console, else 'false' 00142 * 00143 * @note 00144 * - In addition to using an optional log formatter, the log also writes into the console in verbose mode 00145 * - The log does not need be to be opened to write into the console 00146 * - Android: Messages are not written into the console, instead the Android in-kernel log buffer is used 00147 * (use Androids "logcat" utility to access this system log) 00148 * - By default the log does not write into the console 00149 */ 00150 inline bool IsVerbose() const; 00151 00152 /** 00153 * @brief 00154 * Set verbose mode (write log entries to console) 00155 * 00156 * @param[in] bVerbose 00157 * 'true' if the log is writing into the console, else 'false' 00158 * @param[in] bVerboseLogLevelPrefix 00159 * Should the [LogLevel] prefix be shown? 00160 * 00161 * @see 00162 * - IsVerbose() 00163 */ 00164 inline void SetVerbose(bool bVerbose, bool bVerboseLogLevelPrefix = true); 00165 00166 /** 00167 * @brief 00168 * Open the log file by using a filename 00169 * 00170 * @param[in] sFilename 00171 * The log's filename, the log formatter is automatically created by using the filename extension 00172 * 00173 * @return 00174 * 'true' if all went fine, else 'false' (maybe the log is already opened or the filename extension is not supported?) 00175 * 00176 * @note 00177 * - Supported log filename extensions: "txt" (LogFormatterText), "log" (LogFormatterText), "xml" (LogFormatterXml), "html" (LogFormatterHtml) 00178 */ 00179 PLCORE_API bool Open(const String &sFilename); 00180 00181 /** 00182 * @brief 00183 * Open the log file by using a filename and an explicit log formatter instance 00184 * 00185 * @param[in] sFilename 00186 * The log's filename 00187 * @param[in] cLogFormatter 00188 * Log formatter instance to be used, if this method returns successfully, the log takes over 00189 * the control and is responsible for the destruction of the given instance 00190 * 00191 * @return 00192 * 'true' if all went fine, else 'false' (maybe the log is already opened?) 00193 */ 00194 PLCORE_API bool Open(const String &sFilename, LogFormatter &cLogFormatter); 00195 00196 /** 00197 * @brief 00198 * Close log 00199 * 00200 * @return 00201 * 'true' if all went fine, else 'false' 00202 */ 00203 PLCORE_API bool Close(); 00204 00205 /** 00206 * @brief 00207 * Get log filename 00208 * 00209 * @return 00210 * The log filename 00211 */ 00212 inline String GetFilename() const; 00213 00214 /** 00215 * @brief 00216 * Write a string into the log 00217 * 00218 * @param[in] nLogLevel 00219 * Log level 00220 * @param[in] sText 00221 * Text which should be written into the log 00222 * 00223 * @return 00224 * 'true' if all went fine, else 'false' 00225 * 00226 * @remarks 00227 * The text is written to the log only if the current 00228 * log level is greater or equal to the specified value. 00229 */ 00230 inline bool Output(uint8 nLogLevel, const String &sText); 00231 00232 /** 00233 * @brief 00234 * Get current log level 00235 * 00236 * @return 00237 * The current log level 00238 */ 00239 inline uint8 GetLogLevel() const; 00240 00241 /** 00242 * @brief 00243 * Set current log level 00244 * 00245 * @param[in] nLogLevel 00246 * New current log level 00247 */ 00248 inline void SetLogLevel(uint8 nLogLevel = Info); 00249 00250 /** 00251 * @brief 00252 * Get log level for automatic flush 00253 * 00254 * @return 00255 * Log level for explicitly flush 00256 */ 00257 inline uint8 GetFlushLogLevel() const; 00258 00259 /** 00260 * @brief 00261 * Set log level for automatic flush 00262 * 00263 * @param[in] nFlushLogLevel 00264 * Log level for the explicitly flush 00265 */ 00266 inline void SetFlushLogLevel(uint8 nFlushLogLevel = Error); 00267 00268 /** 00269 * @brief 00270 * Flush output buffer to disk 00271 * 00272 * @return 00273 * 'true' if all went fine, else 'false' (maybe there was nothing to flush?) 00274 * 00275 * @note 00276 * - Only call this function if really required! 00277 */ 00278 inline bool Flush(); 00279 00280 /** 00281 * @brief 00282 * Get current amount of buffered log messages 00283 * 00284 * @return 00285 * Amount of buffered log messages 00286 */ 00287 inline uint32 GetBufferCount() const; 00288 00289 /** 00290 * @brief 00291 * Set how many log messages should be buffered in memory 00292 * 00293 * @param[in] nBufferCount 00294 * Number of messages to buffer 00295 * 00296 * @note 00297 * The nBufferCount-last log messages gets buffered 00298 */ 00299 PLCORE_API void SetBufferCount(uint32 nBufferCount = 10); 00300 00301 /** 00302 * @brief 00303 * Get a copy of the queue which holds the last log messages 00304 * 00305 * @return 00306 * Queue of n-last log messages 00307 */ 00308 inline const Queue<String> &GetLastMessages() const; 00309 00310 /** 00311 * @brief 00312 * Get a string representation of the given log level 00313 * 00314 * @param[in] nLogLevel 00315 * Log level to return the string representation from 00316 * 00317 * @return 00318 * The string representation of the given log level 00319 */ 00320 PLCORE_API String LogLevelToString(uint8 nLogLevel) const; 00321 00322 /** 00323 * @brief 00324 * Get log formatter 00325 * 00326 * @return 00327 * The current log formatter object, can be a null pointer, do NOT delete the returned instance! 00328 */ 00329 inline LogFormatter *GetLogFormatter() const; 00330 00331 00332 //[-------------------------------------------------------] 00333 //[ Private functions ] 00334 //[-------------------------------------------------------] 00335 private: 00336 /** 00337 * @brief 00338 * Constructor 00339 */ 00340 Log(); 00341 00342 /** 00343 * @brief 00344 * Copy constructor 00345 * 00346 * @param[in] cSource 00347 * Source to copy from 00348 */ 00349 Log(const Log &cSource); 00350 00351 /** 00352 * @brief 00353 * Destructor 00354 */ 00355 virtual ~Log(); 00356 00357 /** 00358 * @brief 00359 * Copy operator 00360 * 00361 * @param[in] cSource 00362 * Source to copy from 00363 * 00364 * @return 00365 * Reference to this instance 00366 */ 00367 Log &operator =(const Log &cSource); 00368 00369 /** 00370 * @brief 00371 * Write a string into the log 00372 * 00373 * @param[in] nLogLevel 00374 * Log Level 00375 * @param[in] sText 00376 * Text which should be written into the log 00377 * 00378 * @return 00379 * 'true' if all went fine, else 'false' 00380 */ 00381 PLCORE_API bool Write(uint8 nLogLevel, const String &sText); 00382 00383 00384 //[-------------------------------------------------------] 00385 //[ Private data ] 00386 //[-------------------------------------------------------] 00387 private: 00388 bool m_bVerbose; /**< Write into the standard OS console? */ 00389 bool m_bVerboseLogLevelPrefix; /**< Indicates if the [LogLevel] prefix should be shown within the standard OS console output */ 00390 String m_sFilename; /**< Filename */ 00391 uint8 m_nLogLevel; /**< Current log level mode (see LogLevel) */ 00392 uint8 m_nFlushLogLevel; /**< If this log level is used the the flush is explicitly done */ 00393 uint32 m_nFlushMessages; /**< Holds the number of messages since the last flush */ 00394 Queue<String> m_qLastMessages; /**< Holds the last log messages */ 00395 uint32 m_nBufferedMessages; /**< How much messages should be buffered */ 00396 LogFormatter *m_pLogFormatter; /**< Holds an instance of a log formatter class, can be a null pointer */ 00397 00398 00399 }; 00400 00401 00402 //[-------------------------------------------------------] 00403 //[ Namespace ] 00404 //[-------------------------------------------------------] 00405 } // PLCore 00406 00407 00408 //[-------------------------------------------------------] 00409 //[ Implementation ] 00410 //[-------------------------------------------------------] 00411 #include "PLCore/Log/Log.inl" 00412 00413 00414 #endif // __PLCORE_LOG_H__
|