1C++实现简易log日志系统1.log日志的作用在软件开发周期中,不管是前台还是后台,系统一般会采用一个持久化的日志系统来记录运行情况。在代码中嵌入log代码信息,主要记录下列信息:(1)记录系统运行异常信息。(2)记录系统运行状态信息。(3)记录系统运行性能指标。通过对上述信息分析和诊断,我们能采取正确的手段来提高系统质量和系统性能。由此可见log日志在系统中的重要地位和存在的必要性。2.log日志的类型与级别2.1日志的类型主要分三大类:安全类信息:记录系统边界交互行为和信息;业务类信息:记录系统内部业务处理行为和信息;性能类信息:记录系统硬件对业务处理的支撑能力。2.2日志的类型一般分五级:ERROR(错误):此信息输出后,主体系统核心模块不能正常工作,需要修复才能正常工作。WARN(警告):此信息输出后,系统一般模块存在问题,不影响系统运行。INFO(通知):此信息输出后,主要是记录系统运行状态等关联信息。DEBUG(调试):最细粒度的输出,除却上面各种情况后,你希望输出的相关信息,都可以在这里输出。TRACE(跟踪):最细粒度的输出,除却上面各种情况后,你希望输出的相关信息,都可以在这里输出。在本文实现的简单日志系统中不包括DEBUG和TRACE。DEBUG在编码过程中进行,TRACE不太需要。2.3常见的开源log工具C/C++实现的开源log常见有:C++版的log4j的log4cplus、快速的C++日志库——spdlog、纯C日志函数库——zlog、C++日志框架——GoogleGlog等。其中开源log工具log4cplus在项目中的使用较为常见,具体用法和源码请参考网络的资源,不再赘述。3.自实现log工具主要针对ERROR(错误)、WARN(警告)和INFO(通知)这三种日志类型实现了如下的C++简易log工具。由源文件(logger.cpp)和头文件(logger.h)组成。源码如下。logger.h文件:/**\logger.h*\brief日记模块2*/#ifndef__logger__#define__logger__#includeiostream#includeiomanip#includefstream#includestring#includecstdlib#includestdint.h//////\brief日志文件的类型///typedefenumlog_rank{INFO,WARNING,ERROR,FATAL}log_rank_t;//////\brief初始化日志文件///\paraminfo_log_filename信息文件的名字///\paramwarn_log_filename警告文件的名字///\paramerror_log_filename错误文件的名字voidinitLogger(conststd::string&info_log_filename,conststd::string&warn_log_filename,conststd::string&error_log_filename);//////\brief日志系统类///classLogger{friendvoidinitLogger(conststd::string&info_log_filename,conststd::string&warn_log_filename,conststd::string&erro_log_filename);public://构造函数Logger(log_rank_tlog_rank):m_log_rank(log_rank){};~Logger();3//////\brief写入日志信息之前先写入的源代码文件名,行号,函数名///\paramlog_rank日志的等级///\paramline日志发生的行号///\paramfunction日志发生的函数staticstd::ostream&start(log_rank_tlog_rank,constint32line,conststd::string&function);private://////\brief根据等级获取相应的日志输出流///staticstd::ostream&getStream(log_rank_tlog_rank);staticstd::ofstreamm_info_log_file;///信息日子的输出流staticstd::ofstreamm_warn_log_file;///警告信息的输出流staticstd::ofstreamm_error_log_file;///错误信息的输出流log_rank_tm_log_rank;///日志的信息的等级};//////\brief根据不同等级进行用不同的输出流进行读写///#defineLOG(log_rank)\Logger(log_rank).start(log_rank,__LINE__,__FUNCTION__)//////\brief利用日记进行检查的各种宏///#defineCHECK(a)\if(!(a)){\LOG(ERROR)CHECKfailedendl\#a=(a)endl;\abort();\}\#defineCHECK_NOTNULL(a)\if(NULL==(a)){\LOG(ERROR)CHECK_NOTNULLfailed\#a==NULLendl;\abort();\}4#defineCHECK_NULL(a)\if(NULL!=(a)){\LOG(ERROR)CHECK_NULLfailedendl\#a!=NULLendl;\abort();\}#defineCHECK_EQ(a,b)\if(!((a)==(b))){\LOG(ERROR)CHECK_EQfailedendl\#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_NE(a,b)\if(!((a)!=(b))){\LOG(ERROR)CHECK_NEfailedendl\#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_LT(a,b)\if(!((a)(b))){\LOG(ERROR)CHECK_LTfailed\#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_GT(a,b)\if(!((a)(b))){\LOG(ERROR)CHECK_GTfailedendl\#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_LE(a,b)\if(!((a)=(b))){\LOG(ERROR)CHECK_LEfailedendl\5#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_GE(a,b)\if(!((a)=(b))){\LOG(ERROR)CHECK_GEfailedendl\#a=(a)endl\#b=(b)endl;\abort();\}#defineCHECK_DOUBLE_EQ(a,b)\do{\CHECK_LE((a),(b)+0.000000000000001L);\CHECK_GE((a),(b)-0.000000000000001L);\}while(0)#endiflogger.cpp文件源码:#includelogger.h#includecstdlib#includectimestd::ofstreamLogger::m_error_log_file;std::ofstreamLogger::m_info_log_file;std::ofstreamLogger::m_warn_log_file;voidinitLogger(conststd::string&info_log_filename,conststd::string&warn_log_filename,conststd::string&error_log_filename){Logger::m_info_log_file.open(info_log_filename.c_str());Logger::m_warn_log_file.open(warn_log_filename.c_str());Logger::m_error_log_file.open(error_log_filename.c_str());}std::ostream&Logger::getStream(log_rank_tlog_rank){return(INFO==log_rank)?(m_info_log_file.is_open()?m_info_log_file:std::cout):(WARNING==log_rank?(m_warn_log_file.is_open()?m_warn_log_file:std::cerr):6(m_error_log_file.is_open()?m_error_log_file:std::cerr));}std::ostream&Logger::start(log_rank_tlog_rank,constint32line,conststd::string&function){time_ttm;time(&tm);chartime_string[128];ctime_r(&tm,time_string);returngetStream(log_rank)time_stringfunction(function)linelinestd::flush;}Logger::~Logger(){getStream(m_log_rank)std::endlstd::flush;if(FATAL==m_log_rank){m_info_log_file.close();m_info_log_file.close();m_info_log_file.close();abort();}}使用方法如下:第一步,通过给定三个日志文件的路径,调用初始化函数initLogger进行日志文件的创建。第二步,在需要插入日志的地方调用LOG(TYPE)”yourinfo”;即可。yourinfo表示你要输入到日志文件中的信息。以WARN日志为例,输出的信息大致如下:SunJul509:49:482015function(getNextTask)line75notasktoberunSunJul509:49:532015function(getNextTask)line75notasktoberunSunJul509:49:582015function(getNextTask)line75notasktoberunSunJul509:50:032015function(getNextTask)line75notasktoberun