您的位置:首页 > 其它

第二人生的源码分析(5)类Log的实现

2008-01-03 22:26 543 查看
类Log定义如下:
#001 class Log
#002 {
#003 public:
#004 static bool shouldLog(CallSite&);
#005 static std::ostringstream* out();
#006 static void flush(std::ostringstream*, const CallSite&);
#007 };
在类Log里的函数shouldLog是先获取全局的Log对象和全局设置参数,然后检查是否需要保存这条Log信息,同时把这条Log保存起来。它的代码如下:
#001 bool Log::shouldLog(CallSite& site)
#002 {
#003 LogLock lock;
#004 if (!lock.ok())
#005 {
#006 return false;
#007 }
#008
#009 Globals& g = Globals::get();
#010 Settings& s = Settings::get();
#011
#012 s.shouldLogCallCounter += 1;
#013
#014 std::string class_name = className(site.mClassInfo);
#015 std::string function_name = functionName(site.mFunction);
#016 if (site.mClassInfo != typeid(NoClassInfo))
#017 {
#018 function_name = class_name + "::" + function_name;
#019 }
#020
#021 ELevel compareLevel = s.defaultLevel;
#022
#023 checkLevelMap(s.functionLevelMap, function_name, compareLevel)
#024 || checkLevelMap(s.classLevelMap, class_name, compareLevel)
#025 || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel);
#026
#027 site.mCached = true;
#028 g.addCallSite(site);
#029 return site.mShouldLog = site.mLevel >= compareLevel;
#030 }

在类Log里的函数out是获取保存字符串的输出对象std::ostringstream,由它来格式化所有输出的字符串。它的代码如下:
#001 std::ostringstream* Log::out()
#002 {
#003 LogLock lock;
#004 if (lock.ok())
#005 {
#006 Globals& g = Globals::get();
#007
#008 if (!g.messageStreamInUse)
#009 {
#010 g.messageStreamInUse = true;
#011 return &g.messageStream;
#012 }
#013 }
#014
#015 return new std::ostringstream;
#016 }

在类Log里的函数flush是把保存在Log缓存里字符串输出到合适的地方,比如把一条Log输出到文件里。
#001 void Log::flush(std::ostringstream* out, const CallSite& site)
#002 {
#003 LogLock lock;
#004 if (!lock.ok())
#005 {
#006 return;
#007 }
#008
这里进行加锁操作。

#009 Globals& g = Globals::get();
#010 Settings& s = Settings::get();
#011
获取全局保存LOG的对象和LOG参数对象。

#012 std::string message = out->str();
#013 if (out == &g.messageStream)
#014 {
#015 g.messageStream.clear();
#016 g.messageStream.str("");
#017 g.messageStreamInUse = false;
#018 }
#019 else
#020 {
#021 delete out;
#022 }
#023
#024 if (site.mLevel == LEVEL_ERROR)
#025 {
#026 std::ostringstream fatalMessage;
#027 fatalMessage << abbreviateFile(site.mFile)
#028 << "(" << site.mLine << ") : error";
#029
#030 writeToRecorders(site.mLevel, fatalMessage.str());
#031 }
#032
写出错的LOG处理。

#033
#034 std::ostringstream prefix;
#035
#036 switch (site.mLevel)
#037 {
#038 case LEVEL_DEBUG: prefix << "DEBUG: "; break;
#039 case LEVEL_INFO: prefix << "INFO: "; break;
#040 case LEVEL_WARN: prefix << "WARNING: "; break;
#041 case LEVEL_ERROR: prefix << "ERROR: "; break;
#042 default: prefix << "XXX: "; break;
#043 };
#044
输出LOG的前缀提示。

#045 if (s.printLocation)
#046 {
#047 prefix << abbreviateFile(site.mFile)
#048 << "(" << site.mLine << ") : ";
#049 }
#050
#051 if (message.find(functionName(site.mFunction)) == std::string::npos)
#052 {
#053 #if LL_WINDOWS
#054 // DevStudio: __FUNCTION__ already includes the full class name
#055 #else
#056 if (site.mClassInfo != typeid(NoClassInfo))
#057 {
#058 prefix << className(site.mClassInfo) << "::";
#059 }
#060 #endif
#061 prefix << site.mFunction << ": ";
#062 }
#063
#064 prefix << message;
#065 message = prefix.str();
#066
#067 writeToRecorders(site.mLevel, message);
#068
写调试、提示、警告、错误的LOG到文件或者显示窗口。

#069 if (site.mLevel == LEVEL_ERROR && s.crashFunction)
#070 {
#071 s.crashFunction(message);
#072 }
#073 }
最后处理出错LOG的情况。
类Log通过上面三个函数来检查是否可以输出LOG,怎么样保存LOG信息,然后怎么样输出LOG到文件或者窗口里。到这里就分析完成类Log了,下面再来分析类CallSite的代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: