类
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
的代码。
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow