标签:
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 日记模块 */ #ifndef __logger__ #define __logger__ #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <cstdlib> #include <stdint.h> /// /// \brief 日志文件的类型 /// typedef enum log_rank { INFO, WARNING, ERROR, FATAL }log_rank_t; /// /// \brief 初始化日志文件 /// \param info_log_filename 信息文件的名字 /// \param warn_log_filename 警告文件的名字 /// \param error_log_filename 错误文件的名字 void initLogger(const std::string&info_log_filename, const std::string&warn_log_filename, const std::string&error_log_filename); /// /// \brief 日志系统类 /// class Logger { friend void initLogger(const std::string& info_log_filename, conststd::string& warn_log_filename, conststd::string& erro_log_filename); public: //构造函数 Logger(log_rank_t log_rank) : m_log_rank(log_rank) {}; ~Logger(); /// /// \brief 写入日志信息之前先写入的源代码文件名, 行号, 函数名 /// \param log_rank 日志的等级 /// \param line 日志发生的行号 /// \param function 日志发生的函数 static std::ostream& start(log_rank_t log_rank, const int32line, conststd::string& function); private: /// /// \brief 根据等级获取相应的日志输出流 /// static std::ostream& getStream(log_rank_t log_rank); static std::ofstream m_info_log_file; ///< 信息日子的输出流 static std::ofstream m_warn_log_file; ///< 警告信息的输出流 static std::ofstream m_error_log_file; ///< 错误信息的输出流 log_rank_t m_log_rank; ///< 日志的信息的等级 }; /// /// \brief 根据不同等级进行用不同的输出流进行读写 /// #define LOG(log_rank) Logger(log_rank).start(log_rank, __LINE__,__FUNCTION__) /// /// \brief 利用日记进行检查的各种宏 /// #define CHECK(a) if(!(a)) { LOG(ERROR) << " CHECK failed " << endl << #a << "= " << (a) << endl; abort(); } #define CHECK_NOTNULL(a) if( NULL == (a)) { LOG(ERROR) << " CHECK_NOTNULL failed " << #a << "== NULL " << endl; abort(); } #define CHECK_NULL(a) if( NULL != (a)) { LOG(ERROR) << " CHECK_NULL failed " << endl << #a << "!= NULL " << endl; abort(); } #define CHECK_EQ(a, b) if(!((a) == (b))) { LOG(ERROR) << " CHECK_EQ failed " << endl << #a << "= " << (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_NE(a, b) if(!((a) != (b))) { LOG(ERROR) << " CHECK_NE failed " << endl << #a << "= " << (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_LT(a, b) if(!((a) < (b))) { LOG(ERROR) << " CHECK_LT failed " << #a << "= " << (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_GT(a, b) if(!((a) > (b))) { LOG(ERROR) << " CHECK_GT failed " << endl << #a <<" = " << (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_LE(a, b) if(!((a) <= (b))) { LOG(ERROR) << " CHECK_LE failed " << endl << #a << "= " << (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_GE(a, b) if(!((a) >= (b))) { LOG(ERROR) << " CHECK_GE failed " << endl << #a << " = "<< (a) << endl << #b << "= " << (b) << endl; abort(); } #define CHECK_DOUBLE_EQ(a, b) do { CHECK_LE((a), (b)+0.000000000000001L); CHECK_GE((a), (b)-0.000000000000001L); }while (0) #endif
logger.cpp文件源码:
#include "logger.h" #include <cstdlib> #include <ctime> std::ofstream Logger::m_error_log_file; std::ofstream Logger::m_info_log_file; std::ofstream Logger::m_warn_log_file; void initLogger(const std::string&info_log_filename, const std::string&warn_log_filename, const std::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) : (m_error_log_file.is_open()? m_error_log_file : std::cerr)); } std::ostream& Logger::start(log_rank_tlog_rank, const int32 line, const std::string&function) { time_t tm; time(&tm); char time_string[128]; ctime_r(&tm, time_string); return getStream(log_rank) << time_string << "function (" << function << ")" << "line " << line <<std::flush; } Logger::~Logger(){ getStream(m_log_rank) << std::endl << std::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”;即可。your info表示你要输入到日志文件中的信息。
以WARN日志为例,输出的信息大致如下:
Sun Jul 5 09:49:48 2015
function (getNextTask) line 75 no task to berun
Sun Jul 5 09:49:53 2015
function (getNextTask) line 75 no task to berun
Sun Jul 5 09:49:58 2015
function (getNextTask) line 75 no task to berun
Sun Jul 5 09:50:03 2015
function (getNextTask) line 75 no task to berun
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/k346k346/article/details/46908167