标签: ogrelogogre日志系统it |
分类: 游戏编程 |
日志管理
日志(Log)——用来记录Ogre系统初始化、运行、结束以及调试西悉尼,使用日志便于我们调试程序。
A.Log类:
代表用于记录信息的日志。Log类的一个对象对应于一个日志文件。
其中有提供了想日志文件写入信息的函数logMessage:
Void logMessage(const String &message,LogMessageLevel lml=LML_NORMAL,bool maskDebug=false)
Message: 存储要写入的信息
lml: 指定传入信息的级别,用来衡量一条信息的重要程度,其类型LogMessageLevel有如下的定义:
num LogMessageLevel //----------------------------------日志信息的重要程度
{
LML_TRIVIAL = 1, 重要程度一般
LML_NORMAL = 2, 重要程度稍高
LML_CRITICAL = 3 最重要
};
maskDebug: 是否输出编译信息
为了判断一条信息的重要性,从而决定是否将该信息写入日志文件,我们不光要衡量信息的重要程度,还应该同时考虑日志文件的重要程度,Log类提供了一个函数setLogDetail来设置日志文件的重要程度,定义如下:
Void setLogDetail(LoggingLevel ll)
ll:用来指定该日志文件的级别,来衡量日志文件的重要程度,其参数类型有如下的定义
enum LoggingLevel //---------------------------------日志的重要程度
{
LL_LOW = 1,
LL_NORMAL = 2,
LL_BOREME = 3
};
#ifndef __Log_H__
#define __Log_H__
#include "OgrePrerequisites.h"
#include "OgreString.h"
namespace Ogre {
// LogMessageLevel + LoggingLevel > OGRE_LOG_THRESHOLD = message logged //当日志级别+日志细节>临界值 -》日志需要记录
#define OGRE_LOG_THRESHOLD 4 //-------------------------------------------Ogre 日志文件的临界值
enum LoggingLevel //---------------------------------日志的重要程度
{
LL_LOW = 1,
LL_NORMAL = 2,
LL_BOREME = 3
};
enum LogMessageLevel //----------------------------------日志信息重要程度
{
LML_TRIVIAL = 1,
LML_NORMAL = 2,
LML_CRITICAL = 3
};
class LogListener //-------------------------------每个日志Log都可以有多个Listener ,因为其保留了listener指针,通过addListener方法可以向log增加监听
{
public:
virtual ~LogListener() {}
virtual void messageLogged( const String& message, LogMessageLevel lml, bool maskDebug,const String &logName ) = 0;
};
class _OgreExport Log : public LogAlloc
{
protected:
std::ofstream mfpLog; //-----------------------------log流定义
LoggingLevel mLogLevel;//------------------------------日志细节层次
bool mDebugOut;//------------------------------是否输出编译信息
bool mSuppressFile;//--------------------------文件是否隐藏
bool mTimeStamp;//-----------------------------时间戳
String mLogName;//-------------------------------日志名
typedef vector<LogListener*>::type mtLogListener;
mtLogListener mListeners;//------------------------------保存了日志监听器的指针,从而可以通过日志名称来调用不同的监听器
public:
class Stream;//用于控制日志输出的流,在构造函数中初始化
OGRE_AUTO_MUTEX // public to allow external locking
Log( const String& name, bool debugOutput = true, bool suppressFileOutput = false);
~Log();
/// Return the name of the log
const String& getName() const { return mLogName; }
/// Get whether debug output is enabled for this log
bool isDebugOutputEnabled() const { return mDebugOut; }
/// Get whether file output is suppressed for this log
bool isFileOutputSuppressed() const { return mSuppressFile; }
/// Get whether time stamps are printed for this log
bool isTimeStampEnabled() const { return mTimeStamp; }
void logMessage( const String& message, LogMessageLevel lml = LML_NORMAL, bool maskDebug =false );
Stream stream(LogMessageLevel lml = LML_NORMAL, bool maskDebug = false);
void setDebugOutputEnabled(bool debugOutput);
void setLogDetail(LoggingLevel ll);
void setTimeStampEnabled(bool timeStamp);
LoggingLevel getLogDetail() const { return mLogLevel; }
void addListener(LogListener* listener);
void removeListener(LogListener* listener);
class _OgrePrivate Stream //-----------------------用于输出日志Log的文件信息的流定义
{
protected:
Log* mTarget; //-------------------------------目标Log
LogMessageLevel mLevel;//------------------------Log重要等级
bool mMaskDebug; //------------------------------是否要输出日志编译信息
typedef StringUtil::StrStreamType BaseStream; //-用于控制输出的
BaseStream mCache;
public:
/// Simple type to indicate a flush of the stream to the log
struct Flush {};
Stream(Log* target, LogMessageLevel lml, bool maskDebug)
:mTarget(target), mLevel(lml), mMaskDebug(maskDebug)
{
}
// copy constructor
Stream(const Stream& rhs)
: mTarget(rhs.mTarget), mLevel(rhs.mLevel), mMaskDebug(rhs.mMaskDebug)
{
// explicit copy of stream required, gcc doesn't like implicit
mCache.str(rhs.mCache.str());
}
~Stream()
{
// flush on destroy
if (mCache.tellp() > 0)
{
mTarget->logMessage(mCache.str(), mLevel, mMaskDebug);
}
}
template <typename T> //--------------------操作符重载,使得能够以流的方式读取日志文件信息
Stream& operator<< (const T& v)
{
mCache << v;
return *this;
}
Stream& operator<< (const Flush& v)
{
(void)v;
mTarget->logMessage(mCache.str(), mLevel, mMaskDebug);
mCache.str(StringUtil::BLANK);
return *this;
}
};
};
}
#endif
B. LogMessage类
管理所有的Log类的对象,也就是挂历所有的日志文件,并且负责向日志文件中输出信息。LogManager类提供了创建Log对象的成员函数createLog.
不要用Log类直接创建对象,而是要用LogManager的createLog函数来创建Log对象,因为izhe保证了:LogManager维护所有的Log对象,通过LogManager可以方便地进行查找操作createLog 定义如下:
Log* createLog( const String& name, bool defaultLog = false, bool
debuggerOutput = true );
参数name是String类型的,它指定所创建日志文件的文件名,如Ogre.log。
参数defaultLog是布尔类型的,如果为true,则把当前创建的日志文件设置为
LogManager默认的日志文件。调用LogManager的接口函数都对此文件生效。
参数debuggerOutput是布尔类型的,如果为true,则不只向日志文件中输出信息,还向调试窗口中输出信息。
#ifndef __LogManager_H__
#define __LogManager_H__
#include "OgrePrerequisites.h"
#include "OgreLog.h"
#include "OgreSingleton.h"
#include "OgreString.h"
namespace Ogre
{
class _OgreExport LogManager : public Singleton<LogManager>, public LogAlloc //-----------------------管理所有Log类的对象,也就是挂历所有的日志文件,并且负责向日志文件中输出信息
{
protected:
typedef map<String, Log*>::type LogList;
/// A list of all the logs the manager can access
LogList mLogs;
/// The default log to which output is done
Log* mDefaultLog;
public:
OGRE_AUTO_MUTEX // public to allow external locking
LogManager();
~LogManager();
Log* createLog( const String& name, bool defaultLog = false, bool debuggerOutput = true,
bool suppressFileOutput = false);//---------------------------------------LogMessage最重要的函数之一
Log* getLog( const String& name); //---------------------------------------Name指定了要查找的日志文件名
Log* getDefaultLog(); //--------------------------------------------返回默认的Log对象
void destroyLog(const String& name);
void destroyLog(Log* log);
Log* setDefaultLog(Log* newLog);
void logMessage( const String& message, LogMessageLevel lml = LML_NORMAL,//-----向默认的日志文件中写入信息(写入一条信息)
bool maskDebug = false);
void logMessage( LogMessageLevel lml, const String& message, ------------向默认的日志文件中写入接受的多条信息
bool maskDebug = false) { logMessage(message, lml, maskDebug); }
Log::Stream stream(LogMessageLevel lml = LML_NORMAL, //
bool maskDebug = false);
void setLogDetail(LoggingLevel ll);
static LogManager& getSingleton(void);
static LogManager* getSingletonPtr(void);
};
}
#endif
重载ExampleApplication中的createScene函数,在函数内创建一个名为Test.log的日志文件,并向该文件中写入一段信息。
部分代码
void createScene(void)
{
Log *p_Log=LogManager::getSingleton().createLogr("test.log");
p_Log->logMessage("I write a message to test.log");
}
在createScene函数中,首先调用LogManager的createLog成员函数来创建一个名为test.log的日志文件,并用p_Log保存此日志文件的指针。然后,我们同通过Log的成员函数logMessage向test.log中写入一句话,