开发程序时,记录运行状态对于调试非常重要,从最简单好用的printf(),到VC++环境提供的TRACE宏,都是开发者的得力助手。其实打印记录程序运行状态的重要性还应该更加重要,不仅开发时,而且在部署完毕运行时,也要把运行状态通过日志文件展现出来,以便于跟踪排查错误。看看现在大型的软件如Tomat,Oracle,IIS,无不提供了日志功能。可测量跟踪成为了软件健壮的重要标志。
对于开发者来讲,不仅需要记录程序的状态,还要记录对应的源代码位置,记录的时间等。对于这些通用的记录项,就应该尽量自动的去完成,从而避免繁琐的日志代码,为此我开发了一个非常简单的C++日志类来完成这个工作。
为使用更加简单,全部日志功能通过一个宏定义导出,使用者只需 LOG(L"记录内容"); 即可,最终这个宏会自动把源文件位置,记录时间,连同日志一起作为一行写入日志文件。需要注意,字符编码全部要求是UNICODE编码。
#pragma once /* 日志记录类 功能描述: 根据当前时间自动生成日志文件名,自动记录日志到日志文件。 日志文件名格式(样例): 20141219211252255.log 日志内容格式(样例): 2014年12月19日11时52分55秒,源文件:e:\work\udptest\udptestdlg.cpp,第109行, 这里是要写的日志内容 使用方式: 此类采用单例模式设计,为使用方便,定义了两个宏供用户调用。样例代码: LOG(L"这里是要写的日志内容"); // 记录日志到文件 ENDLOG // 程序退出之前调用,关闭日志文件 */ class LogWriter { protected: LogWriter(); ~LogWriter(); private: wchar_t fileName[1024]; FILE* fp; public: void Log(wchar_t* log); public: static LogWriter* GetLogWriter(); static void DeleteLogWriter(); private: static LogWriter* theOnlyLogWriter; }; #define LOG(x) \ { \ wchar_t buffer[2048];\ SYSTEMTIME st;\ ::GetLocalTime(&st);\ swprintf_s(buffer, L"%04d年%02d月%02d日%02d时%02d分%02d秒,源文件:%s,第%d行, %s\n", \ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,\ TEXT(__FILE__),__LINE__,x);\ LogWriter::GetLogWriter()->Log(buffer);\ } #define ENDLOG \ LogWriter::DeleteLogWriter();
#include "stdafx.h" #include "LogWriter.h" #include "share.h" LogWriter* LogWriter::theOnlyLogWriter = NULL; LogWriter::LogWriter() { // determine the log file's name, yyyyMMddhhmmss.log SYSTEMTIME st; ::GetLocalTime(&st); ::swprintf_s(this->fileName, L"%04d%02d%02d%02d%02d%02d.log", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); fp = ::_wfsopen(this->fileName, L"w,ccs=UTF-8", _SH_DENYNO); // 以共享读写模式打开日志文件 } // 线程安全的写入文件 void LogWriter::Log(wchar_t* log) { if (fp != NULL) { ::fwprintf(this->fp, L"%s", log); } } LogWriter::~LogWriter() { if (this->fp != NULL) ::fclose(fp); } LogWriter* LogWriter::GetLogWriter() { if (theOnlyLogWriter == NULL) { theOnlyLogWriter = new LogWriter(); } return theOnlyLogWriter; } void LogWriter::DeleteLogWriter() { if (theOnlyLogWriter != NULL) { delete theOnlyLogWriter; theOnlyLogWriter = NULL; } }