1
0
forked from 0ad/0ad
0ad/source/network/NetLog.h
2007-10-21 09:40:06 +00:00

662 lines
15 KiB
C++

/**
*-----------------------------------------------------------------------------
* FILE : NetLog.h
* PROJECT : 0 A.D.
* DESCRIPTION : Network subsystem logging classes declarations
*-----------------------------------------------------------------------------
*/
#ifndef NETLOG_H
#define NETLOG_H
// INCLUDES
#include "ps/Pyrogenesis.h"
#include "ps/ThreadUtil.h"
#include "ps/CStr.h"
#include "lib/timer.h"
#include <list>
#include <vector>
#include <fstream>
// DECLARATIONS
typedef enum
{
LOG_LEVEL_ALL = 0x0000, // Lowest level possible
LOG_LEVEL_DEBUG = 0x0001, // Informational events for app debugging
LOG_LEVEL_INFO = 0x0002, // Useful for highlighting app progress
LOG_LEVEL_WARN = 0x0004, // Potentially dangerous situations
LOG_LEVEL_ERROR = 0x0008, // Error events but the app can continue
LOG_LEVEL_FATAL = 0x0010, // Very severe errors, the app aborts
LOG_LEVEL_OFF = 0xFFFF, // The highest level possible
} LogLevel;
class CNetLogger;
class CNetLogSink;
typedef std::list< CNetLogger* > LoggerList;
typedef std::vector< CNetLogSink* > SinkList;
/*
CLASS : CNetLogEvent
DESCRIPTION : CNetLogEvent represents an object passed between
different network logging components when a decision
for logging is made
NOTES :
*/
class CNetLogEvent
{
public:
CNetLogEvent(
LogLevel level,
const CStr& message,
const CStr& loggerName );
~CNetLogEvent( void );
/**
* Returns the level of the event
*
* @return Event level;
*/
inline LogLevel GetLevel( void ) const { return m_Level; }
/**
* Returns the time of the event
*
* @return Event time
*/
inline Timer GetTimeStamp( void ) const { return m_TimeStamp; }
/**
* Returns the name of the logger which logged the event
*
* @return Logger name
*/
inline const CStr& GetLoggerName( void ) const { return m_LoggerName; }
/**
* Returns the message used when the event was initialized
*
* @return Event message
*/
inline const CStr& GetMessage( void ) const { return m_Message; }
protected:
private:
// Not implemented
CNetLogEvent( const CNetLogEvent& );
CNetLogEvent& operator=( CNetLogEvent& );
LogLevel m_Level; // Current level
CStr m_LoggerName; // Logger which processed the event
CStr m_Message; // Application message for the event
Timer m_TimeStamp; // Event logging time
};
/*
CLASS : CNetLogSink
DESCRIPTION : CNetLogSink is the basic interface for events logging
NOTES :
*/
class CNetLogSink
{
public:
CNetLogSink( );
virtual ~CNetLogSink( );
/**
* Set the name of the sink
*
* @param name New sink name
*/
void SetName( const CStr& name );
/**
* Retrieves the name of the sink
*
* @return Sink name
*/
inline const CStr& GetName( void ) const { return m_Name; }
/**
* Set the level of the sink
*
* @param level New sink level
*/
void SetLevel( LogLevel level );
/**
* Retrieves the current level of the sink
*
* @return Sink current level
*/
inline LogLevel GetLevel( void ) const { return m_Level; }
/**
* Retrieves the header text
*
* @return The header text
*/
inline const CStr& GetHeader( void ) const { return m_Header; }
/**
* Set header text which will be logged before an event logging
*
* @param header New header text
*/
void SetHeader( const CStr& header );
/**
* Retrieves the footer text
*
* @return The footer text
*/
inline const CStr& GetFooter( void ) const { return m_Footer; }
/**
* Set footer text which will be logged after an event logging
*
* @param footer New footer text
*/
void SetFooter( const CStr& footer );
/**
* Activates the sink
*/
void Activate( void );
/**
* Closes the sink and release any resources
*/
void Close( void );
/**
* Check if the level of the event is greater than or equal to sink level
* and if it succeeds it performs the actual logging of the event.
*
* @param event Event to log
*/
void DoSink( const CNetLogEvent& event );
/**
* For each event from the passed array, check if its level is greater than
* or equal to sink level and performs the logging for it.
*
* @param pEvents List of events to log
* @param eventCount The number of events in pEvents list
*/
void DoBulkSink( const CNetLogEvent* pEvents, uint eventCount );
/**
* Check if the sink can log the specified event
*
* @param event Event to check
* @return true if the event can be logged,
* false otherwise
*/
virtual bool TestEvent( const CNetLogEvent& event );
protected:
/**
* Activates the sink object
*/
virtual void OnActivate( void );
/**
* Writes a header into the sink
*/
virtual void WriteHeader( void );
/**
* Writes a footer into the sink
*/
virtual void WriteFooter( void );
/**
* Writes a string message to the logging output
*
* @param message The message to log
*/
virtual void Write( const CStr& message ) = 0;
/**
* Writes a single character to the logging output
*
* @param c The character to log
*/
virtual void Write( char c ) = 0;
/**
* This is called by Close method. It can be overriden by specialized sinks
* if any resources needs to be released on close.
*/
virtual void OnClose( void );
/**
* This method is called by DoSink and DoBulkSink and it must be
* implemented by specialized sinks to perform actual logging
*
* @param event Event to log
*/
virtual void Sink( const CNetLogEvent& event ) = 0;
LogLevel m_Level; // Current level
CMutex m_Mutex; // Multithreading synchronization object
CStr m_Header; // Header text
CStr m_Footer; // Footer text
CStr m_Name; // Sink name
bool m_Closed; // Indicates whether the sink is closed
bool m_Active; // Indicates whether the sink is active
private:
// Not implemented
CNetLogSink( const CNetLogSink& );
CNetLogSink& operator=( const CNetLogSink& );
};
/*
CLASS : CNetLogFileSink
DESCRIPTION : Log network events to a file
NOTES :
*/
class CNetLogFileSink : public CNetLogSink
{
public:
CNetLogFileSink( void );
CNetLogFileSink( const CStr& filename );
CNetLogFileSink( const CStr& filename, bool append );
~CNetLogFileSink( void );
protected:
/**
* Activates the sink object and opens the file specified in constructor
*/
virtual void OnActivate( void );
/**
* Closes the log file
*/
virtual void OnClose( void );
/**
* Writes the event to the log file if opened
*
* @param event Event to log
*/
virtual void Sink( const CNetLogEvent& event );
/**
* Writes the message passed as parameter to file
*
* @param message The message to log
*/
virtual void Write( const CStr& message );
/**
* Writes the character passed as parameter to file
*
* @param c The character to log
*/
virtual void Write( char c );
private:
// Not implemented
CNetLogFileSink( const CNetLogFileSink& );
CNetLogFileSink& operator=( const CNetLogFileSink& );
/**
* Open the file where logging goes. The header text will be written each
* time the file is opened. If append parameter is true, then the file may
* contain the header many times.
*
* @param filename The path to the log file
* @param append Indicates whether logging should append to
* the file or truncate the file
*/
void OpenFile( const CStr& fileName, bool append );
/**
* Close the previously opened file. The footer text will be written each time
* the file is closed. If the file was opened for appending, the footer might
* appera many times.
*/
void CloseFile( void );
std::ofstream m_File; // The log file handle
CStr m_FileName; // The name of the log file
bool m_Append; // Logging should append to file
};
/*
CLASS : CNetLogConsoleSink
DESCRIPTION : Log network events to the game console
NOTES :
*/
class CNetLogConsoleSink : public CNetLogSink
{
public:
CNetLogConsoleSink( void );
~CNetLogConsoleSink( void );
protected:
/**
* Activates the sink object and the game console
*/
virtual void OnActivate( void );
/**
* Toggle off game console
*/
virtual void OnClose( void );
/**
* Writes the event to the game console if active
*
* @param event Event to log
*/
virtual void Sink( const CNetLogEvent& event );
/**
* Writes the message passed as parameter to game console
*
* @param message The message to log
*/
virtual void Write( const CStr& message );
/**
* Writes the character passed as parameter to game console
*
* @param c The character to log
*/
virtual void Write( char c );
private:
// Not implemented
CNetLogConsoleSink( const CNetLogConsoleSink& );
CNetLogConsoleSink& operator=( const CNetLogConsoleSink& );
};
/*
CLASS : CNetLogger
DESCRIPTION : CNetLogger serves for logging messages for network subsytem.
It contains methods for logging at different levels.
NOTES : CNetLogManager is used to obtain an instance of a logger.
*/
class CNetLogger
{
public:
CNetLogger( const CStr& name );
virtual ~CNetLogger( void );
bool IsDebugEnabled ( void ) const;
bool IsInfoEnabled ( void ) const;
bool IsWarnEnabled ( void ) const;
bool IsErrorEnabled ( void ) const;
bool IsFatalEnabled ( void ) const;
void Debug ( const CStr& message );
void Warn ( const CStr& message );
void Info ( const CStr& message );
void Error ( const CStr& message );
void Fatal ( const CStr& message );
void DebugFormat ( const char* pFormat, ... );
void WarnFormat ( const char* pFormat, ... );
void InfoFormat ( const char* pFormat, ... );
void ErrorFormat ( const char* pFormat, ... );
void FatalFormat ( const char* pFormat, ... );
/**
* Retrieves the name of the logger
*
* @return Logger name
*/
const CStr& GetName( void ) const { return m_Name; }
/**
* Retrieves the level of the logger
*
* @return Logger level
*/
LogLevel GetLevel( void ) const { return m_Level; }
/**
* Set the level for the logger
*
* @param level New logger level
*/
void SetLevel( LogLevel level );
/**
* Attaches a new sink to the list of sinks. The sink will be activated.
*
* @param pSink The sink to add
*/
void AddSink( CNetLogSink* pSink );
/**
* Removes the specified sink from the list of attached sinks. The sink
* will not be closed.
*
* @param pSink The sink to remove
* @return The removed sink or NULL if not found
*/
CNetLogSink* RemoveSink( CNetLogSink* pSink );
/**
* Remove the named sink passed as parameter. The sink will not be closed.
*
* @param name The name of sink to remove
* @return The removed sink or NULL if not found
*/
CNetLogSink* RemoveSink( const CStr& name );
/**
* Removes all attached sinks
*
*/
void RemoveAllSinks( void );
/**
* Retrieve the number of attached sinks
*
* @return The number of sink objects
*/
uint GetSinkCount( void );
/**
* Retrieves the sink by its index
*
* @param index The index of the sink
* @return NULL if index is out of boundaries or
* the sink at the specified index
*/
CNetLogSink* GetSink( uint index );
/**
* Retrieves a sink by its name
*
* @param name The name of the sink
* @return NULL if the sink does not exists or
* the sink with the specified name
*/
CNetLogSink* GetSink( const CStr& name );
/**
* Helper function used to retrieve local date time in a string
*/
static void GetStringDateTime( CStr& str );
/**
* Helper function used to retrieve local time in a string
*/
static void GetStringTime( CStr& str );
/**
* Helper function used to retrieve the current timestamp in a string
*/
static void GetStringTimeStamp( CStr& str );
protected:
private:
// Not implemented
CNetLogger( const CNetLogger& );
CNetLogger& operator=( const CNetLogger& );
/**
* Dispatch the event passed as parameter to all sinks
*
* @param event The event to log
*/
void CallSinks( const CNetLogEvent& event );
CMutex m_Mutex; // Multithread synchronization object
SinkList m_Sinks; // Holds the list of sink objects
LogLevel m_Level; // Logger level
CStr m_Name; // Logger name
};
/*
CLASS : CNetLogManager
DESCRIPTION : CNetLogManager serves clients requesting log instances
NOTES : The GetLogger method can be used to retrieve a log
*/
class CNetLogManager
{
public:
/**
* Shutdown the log manager, closes all sinks in the loggers.
*
*/
static void Shutdown( void );
/**
* Retrieves a named logger. If the logger does not exist, it is created.
*
* @param name Logger name
* @return A logger object
*/
static CNetLogger* GetLogger( const CStr& name );
/**
* Return the list of all defined loggers.
*
* @return The list of all loggers
*/
static const LoggerList& GetAllLoggers( void );
private:
// Not implemented
CNetLogManager( void );
~CNetLogManager( void );
CNetLogManager( const CNetLogManager& );
CNetLogManager& operator=( const CNetLogManager& );
static LoggerList m_Loggers; // Holds the list of loggers
};
// TODO: Replace with better access to log manager
#define START_LOGGER( sinkName, sinkType )\
CNetLogger *pLogger = CNetLogManager::GetLogger( "net.log" );\
if ( pLogger )\
{\
CNetLogSink* pSink = pLogger->GetSink( sinkName );\
if ( !pSink )\
{\
pSink = new sinkType();\
if ( pSink )\
{\
CStr startTime;\
CNetLogger::GetStringDateTime( startTime );\
CStr header = "***************************************************\n";\
header += "LOG STARTED: ";\
header += startTime;\
header += "\n";\
header += "Timestamps are in seconds since engine startup\n";\
pSink->SetHeader( header );\
pSink->SetName( sinkName );\
if ( strcmp(sinkName, "sink.console") == 0 )\
pSink->SetLevel( LOG_LEVEL_ERROR );\
else\
pSink->SetLevel( LOG_LEVEL_INFO );\
pLogger->AddSink( pSink );\
}\
}
#define END_LOGGER\
}
#define NET_LOG( parameter )\
{\
START_LOGGER( "sink.file", CNetLogFileSink )\
pLogger->Info( parameter );\
END_LOGGER\
}\
{\
START_LOGGER( "sink.console", CNetLogConsoleSink )\
pLogger->Info( parameter );\
END_LOGGER\
}
#define NET_LOG2( format, parameter )\
{\
START_LOGGER( "sink.file", CNetLogFileSink )\
pLogger->InfoFormat( format, parameter );\
END_LOGGER\
}\
{\
START_LOGGER( "sink.console", CNetLogConsoleSink )\
pLogger->InfoFormat( format, parameter );\
END_LOGGER\
}
#define NET_LOG3( format, parameter1, parameter2 )\
{\
START_LOGGER( "sink.file", CNetLogFileSink )\
pLogger->InfoFormat( format, parameter1, parameter2 );\
END_LOGGER\
}\
{\
START_LOGGER( "sink.console", CNetLogConsoleSink )\
pLogger->InfoFormat( format, parameter1, parameter2 );\
END_LOGGER\
}
#define NET_LOG4( format, parameter1, parameter2, parameter3 )\
{\
START_LOGGER( "sink.file", CNetLogFileSink )\
pLogger->InfoFormat( format, parameter1, parameter2, parameter3 );\
END_LOGGER\
}\
{\
START_LOGGER( "sink.console", CNetLogConsoleSink )\
pLogger->InfoFormat( format, parameter1, parameter2, parameter3 );\
END_LOGGER\
}
#endif // NETLOG_H