2013-04-05 10:29:46 +00:00
/*
* CLogger . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
# pragma once
class CGLogger ;
2013-04-05 21:27:24 +00:00
struct LogRecord ;
2013-04-05 10:29:46 +00:00
class ILogTarget ;
namespace ELogLevel
{
enum ELogLevel
{
NOT_SET = 0 ,
TRACE ,
DEBUG ,
INFO ,
WARN ,
ERROR
} ;
}
2013-04-09 14:31:36 +00:00
/// The class CLoggerDomain provides convenient access to super domains from a sub domain.
2013-04-05 10:29:46 +00:00
class DLL_LINKAGE CLoggerDomain
{
public :
2013-04-09 14:31:36 +00:00
/// Constructs a CLoggerDomain with the domain designated by name.
/// Sub-domains can be specified by separating domains by a dot, e.g. "ai.battle". The global domain is named "global".
explicit CLoggerDomain ( const std : : string & name ) ;
2013-04-06 18:34:06 +00:00
std : : string getName ( ) const ;
2013-04-05 10:29:46 +00:00
CLoggerDomain getParent ( ) const ;
bool isGlobalDomain ( ) const ;
static const std : : string DOMAIN_GLOBAL ;
private :
std : : string name ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CLoggerStream provides a stream-like way of logging messages.
2013-04-06 17:45:02 +00:00
class DLL_LINKAGE CLoggerStream
{
public :
CLoggerStream ( const CGLogger & logger , ELogLevel : : ELogLevel level ) ;
~ CLoggerStream ( ) ;
template < typename T >
CLoggerStream & operator < < ( const T & data )
{
if ( ! sbuffer ) sbuffer = new std : : stringstream ( ) ;
( * sbuffer ) < < data ;
return * this ;
}
private :
const CGLogger & logger ;
ELogLevel : : ELogLevel level ;
std : : stringstream * sbuffer ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CGLogger is used to log messages to certain targets of a specific domain/name.
/// Temporary name is CGLogger, should be renamed to CLogger after refactoring.
class DLL_LINKAGE CGLogger
2013-04-05 10:29:46 +00:00
{
public :
2013-04-06 18:34:06 +00:00
inline ELogLevel : : ELogLevel getLevel ( ) const ;
void setLevel ( ELogLevel : : ELogLevel level ) ;
const CLoggerDomain & getDomain ( ) const ;
2013-04-09 14:31:36 +00:00
/// Logger access methods
2013-04-05 10:29:46 +00:00
static CGLogger * getLogger ( const CLoggerDomain & domain ) ;
static CGLogger * getGlobalLogger ( ) ;
2013-04-09 14:31:36 +00:00
/// Log methods for various log levels
2013-04-05 10:29:46 +00:00
void trace ( const std : : string & message ) const ;
2013-04-06 17:45:02 +00:00
CLoggerStream traceStream ( ) const ;
2013-04-05 10:29:46 +00:00
void debug ( const std : : string & message ) const ;
2013-04-06 17:45:02 +00:00
CLoggerStream debugStream ( ) const ;
2013-04-05 10:29:46 +00:00
void info ( const std : : string & message ) const ;
2013-04-06 17:45:02 +00:00
CLoggerStream infoStream ( ) const ;
2013-04-05 10:29:46 +00:00
void warn ( const std : : string & message ) const ;
2013-04-06 17:45:02 +00:00
CLoggerStream warnStream ( ) const ;
2013-04-05 10:29:46 +00:00
void error ( const std : : string & message ) const ;
2013-04-06 17:45:02 +00:00
CLoggerStream errorStream ( ) const ;
inline void log ( ELogLevel : : ELogLevel level , const std : : string & message ) const ;
2013-04-09 14:31:36 +00:00
void addTarget ( unique_ptr < ILogTarget > & & target ) ;
void clearTargets ( ) ;
2013-04-05 10:29:46 +00:00
2013-04-10 16:28:14 +00:00
/// Returns true if a debug/trace log message will be logged, false if not.
/// Useful if performance is important and concatenating the log message is a expensive task.
bool isDebugEnabled ( ) const ;
bool isTraceEnabled ( ) const ;
2013-04-05 10:29:46 +00:00
private :
2013-04-06 18:34:06 +00:00
explicit CGLogger ( const CLoggerDomain & domain ) ;
2013-04-05 10:29:46 +00:00
CGLogger * getParent ( ) const ;
2013-04-09 14:31:36 +00:00
inline ELogLevel : : ELogLevel getEffectiveLevel ( ) const ; /// Returns the log level applied on this logger whether directly or indirectly.
2013-04-05 10:29:46 +00:00
inline void callTargets ( const LogRecord & record ) const ;
2013-04-06 18:34:06 +00:00
CLoggerDomain domain ;
2013-04-05 10:29:46 +00:00
CGLogger * parent ;
ELogLevel : : ELogLevel level ;
2013-04-09 14:31:36 +00:00
std : : list < unique_ptr < ILogTarget > > targets ;
mutable boost : : mutex mx ;
static boost : : recursive_mutex smx ;
2013-04-05 10:29:46 +00:00
} ;
2013-04-07 10:17:55 +00:00
2013-04-09 14:31:36 +00:00
extern DLL_LINKAGE CGLogger * logGlobal ;
extern DLL_LINKAGE CGLogger * logBonus ;
extern DLL_LINKAGE CGLogger * logNetwork ;
2013-04-10 16:28:14 +00:00
extern DLL_LINKAGE CGLogger * logAi ;
/// Macros for tracing the control flow of the application conveniently. If the TRACE_BEGIN macro is used it should be the first statement in the function, whereas
/// the TRACE_END should be last one before a return statement. Logging traces via this macro have almost no impact when the trace is disabled.
# define TRACE_BEGIN(logger) logger->traceStream() << boost::format("Entering %s.") % BOOST_CURRENT_FUNCTION;
# define TRACE_BEGIN_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) logger->traceStream() << boost::format("Entering %s: " + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params;
# define TRACE_END(logger) logger->traceStream() << boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION;
# define TRACE_END_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) logger->traceStream() << boost::format("Leaving %s: " + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params;
2013-04-09 14:31:36 +00:00
2013-04-07 10:17:55 +00:00
/* ---------------------------------------------------------------------------- */
/* Implementation/Detail classes, Private API */
/* ---------------------------------------------------------------------------- */
2013-04-09 14:31:36 +00:00
/// The class CLogManager is a global storage for logger objects.
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE CLogManager : public boost : : noncopyable
{
public :
2013-04-09 14:31:36 +00:00
static CLogManager & get ( ) ;
2013-04-07 10:17:55 +00:00
void addLogger ( CGLogger * logger ) ;
2013-04-09 14:31:36 +00:00
CGLogger * getLogger ( const CLoggerDomain & domain ) ; /// Returns a logger or nullptr if no one is registered for the given domain.
2013-04-07 10:17:55 +00:00
private :
CLogManager ( ) ;
2013-04-09 14:31:36 +00:00
~ CLogManager ( ) ;
2013-04-07 10:17:55 +00:00
std : : map < std : : string , CGLogger * > loggers ;
2013-04-09 14:31:36 +00:00
mutable boost : : mutex mx ;
static boost : : recursive_mutex smx ;
2013-04-07 10:17:55 +00:00
} ;
2013-04-09 14:31:36 +00:00
/// The struct LogRecord holds the log message and additional logging information.
2013-04-07 10:17:55 +00:00
struct DLL_LINKAGE LogRecord
{
LogRecord ( const CLoggerDomain & domain , ELogLevel : : ELogLevel level , const std : : string & message )
: domain ( domain ) , level ( level ) , message ( message ) , timeStamp ( boost : : posix_time : : second_clock : : local_time ( ) ) , threadId ( boost : : this_thread : : get_id ( ) )
{
}
CLoggerDomain domain ;
ELogLevel : : ELogLevel level ;
std : : string message ;
boost : : posix_time : : ptime timeStamp ;
boost : : thread : : id threadId ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CLogFormatter formats log records.
///
/// There are several pattern characters which can be used to format a log record:
/// %d = Date/Time
/// %l = Log level
/// %n = Logger name
/// %t = Thread ID
/// %m = Message
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE CLogFormatter
{
public :
CLogFormatter ( ) ;
CLogFormatter ( const std : : string & pattern ) ;
void setPattern ( const std : : string & pattern ) ;
const std : : string & getPattern ( ) const ;
std : : string format ( const LogRecord & record ) const ;
private :
std : : string pattern ;
} ;
2013-04-09 14:31:36 +00:00
/// The interface ILogTarget is used by all log target implementations. It holds
/// the abstract method write which sub-classes should implement.
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE ILogTarget : public boost : : noncopyable
{
public :
virtual ~ ILogTarget ( ) { } ;
virtual void write ( const LogRecord & record ) = 0 ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CColorMapping maps a logger name and a level to a specific color. Supports domain inheritance.
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE CColorMapping
{
public :
CColorMapping ( ) ;
void setColorFor ( const CLoggerDomain & domain , ELogLevel : : ELogLevel level , EConsoleTextColor : : EConsoleTextColor color ) ;
EConsoleTextColor : : EConsoleTextColor getColorFor ( const CLoggerDomain & domain , ELogLevel : : ELogLevel level ) const ;
private :
std : : map < std : : string , std : : map < ELogLevel : : ELogLevel , EConsoleTextColor : : EConsoleTextColor > > map ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CLogConsoleTarget is a logging target which writes message to the console.
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE CLogConsoleTarget : public ILogTarget
{
public :
explicit CLogConsoleTarget ( CConsoleHandler * console ) ;
bool isColoredOutputEnabled ( ) const ;
void setColoredOutputEnabled ( bool coloredOutputEnabled ) ;
ELogLevel : : ELogLevel getThreshold ( ) const ;
void setThreshold ( ELogLevel : : ELogLevel threshold ) ;
const CLogFormatter & getFormatter ( ) const ;
void setFormatter ( const CLogFormatter & formatter ) ;
const CColorMapping & getColorMapping ( ) const ;
void setColorMapping ( const CColorMapping & colorMapping ) ;
void write ( const LogRecord & record ) ;
private :
CConsoleHandler * console ;
ELogLevel : : ELogLevel threshold ;
bool coloredOutputEnabled ;
CLogFormatter formatter ;
CColorMapping colorMapping ;
mutable boost : : mutex mx ;
} ;
2013-04-09 14:31:36 +00:00
/// The class CLogFileTarget is a logging target which writes messages to a log file.
2013-04-07 10:17:55 +00:00
class DLL_LINKAGE CLogFileTarget : public ILogTarget
{
public :
2013-04-09 14:31:36 +00:00
/// Constructs a CLogFileTarget and opens the file designated by filePath. If the append parameter is true, the file will be appended to. Otherwise the file designated by filePath
/// will be truncated before being opened.
explicit CLogFileTarget ( const std : : string & filePath , bool append = true ) ;
2013-04-07 10:17:55 +00:00
~ CLogFileTarget ( ) ;
const CLogFormatter & getFormatter ( ) const ;
void setFormatter ( const CLogFormatter & formatter ) ;
void write ( const LogRecord & record ) ;
private :
std : : ofstream file ;
CLogFormatter formatter ;
mutable boost : : mutex mx ;
} ;