日志系统对于消息记录和Debug都非常重要, 这里对Ogre的日志系统做简要分析, Ogre的日志系统不是很复杂, 实现了一个基本的日志系统.
大致的类图如下:
Log类 : 日志系统的核心类, 用来实现日志的记录, 其具体是以std::ofstream来实现日志的存储, 可以设置是否记录时间, 也可以为Log类添加LogListener来对日志进行用户级的处理. 要实现自己对日志的处理, 需要用户实现LogListener接口, 并实现messageLogged函数. 例如, 获取当前系统的日志内容,并在自定义的控件内显示当前日志内容.
LogListener类 : 用户对日志的监听接口, 实现此接口并注册给Log类, 例如在TankWarEditor中需时刻获取日志内容, 每当记录新的信息时在控件内显示.一个Log可注册多个LogListener.
10 |
class TankWarLog : public Ogre::LogListener |
16 |
void addLogWidget(LogDockWidget* textEdit); |
19 |
void messageLogged( const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName); |
22 |
LOGINFO getLogType( const Ogre::String &msg); |
24 |
LogDockWidget *mLogWidget; |
25 |
std::stringstream mBack; |
34 |
TankWarLog::TankWarLog() : mLogWidget(0) |
38 |
void TankWarLog::addLogWidget(LogDockWidget* textEdit) |
40 |
mLogWidget = textEdit; |
41 |
mLogWidget->logMessage(mBack.str(), LOG_NORMAL, true ); |
46 |
void TankWarLog::messageLogged( const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName) |
48 |
std::string m = message.c_str(); |
50 |
mLogWidget->logMessage(m); |
52 |
mBack << formatLog(m) << std::endl; |
59 |
mDefaultLog = new TankWarLog(); |
60 |
Ogre::LogManager *logManager = new Ogre::LogManager(); |
61 |
Ogre::Log * log = logManager->createLog( "TankWarEditor.log" , true , true ); |
62 |
log ->addListener(mDefaultLog); |
63 |
mRoot = new Ogre::Root; |
Log::Stream类 : Log的内部类, 重载了<<输出流, 可以方便的对对象进行输出, 内部使用sstringstream对新日志内容进行缓存, 当Log::Stream对象被销毁或者调用<<Log::Stream::Flush时刷新到到文本.
1 |
Ogre::Log * log = Ogre::LogManager::getSingletonPtr()->getDefaultLog(); |
2 |
Ogre::Log::Stream stream = log ->stream(); |
3 |
stream<< "this is a log demo1" << std::endl; |
4 |
stream<< "this is a log demo2" << std::endl; |
5 |
stream<< "this is a log demo3" << std::endl; |
6 |
stream<<Ogre::Log::Stream::Flush(); |
LogManager类 : 日志管理器, 用来统管系统内所有日志对象, 在Ogre::Root创建时会检查LogManager, 如果没有创建, 则会新建一个全局LogManager(实现Singleton接口), 并自动生成一个默认的Log对象,所以如果需要自行控制Log,例如重定向日志输出, 我们需要在Ogre::Root对象声称之前自行创建LogManager, 创建一个Log对象,并为其注册LogListener的实现.如上面的实现.
2 |
mDefaultLog = new TankWarLog(); |
3 |
Ogre::LogManager *logManager = new Ogre::LogManager(); |
4 |
Ogre::Log * log = logManager->createLog( "TankWarEditor.log" , true , true ); |
5 |
log ->addListener(mDefaultLog); |
6 |
mRoot = new Ogre::Root; |
Exception 类 : Ogre异常类基类, 我们发现每当有异常发生时其详细内容会记录到Log文件, 其实Exception类的构造函数会调用LogManager获取默认的Log并对错误进行记录.
01 |
Exception::Exception( int num, const String& desc, const String& src, const char * typ, const char * fil, long lin) : |
10 |
if (LogManager::getSingletonPtr()){ |
11 |
LogManager::getSingleton().logMessage( this ->getFullDescription(), LML_CRITICAL, true );} |