Logger.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #ifndef __TWINKLE_LOGGER_H__
  2. #define __TWINKLE_LOGGER_H__
  3. //////////////////////////////////////////////////////////////////////////
  4. // @author: Josephus
  5. // @date: 2016-5-3
  6. // @version: 1.0.0
  7. // @edit_history:
  8. // @date:2016-6-26 set option for no buffer or not.
  9. // @date:2016-7-2 delete erroCode stored;
  10. // add Trace Logger format; add GetLastError() formatting message;
  11. // add LOG_FUNCION() to log function enter and leave event;
  12. // @date:2016-7-4 improve the logger time accurating to millisecond;
  13. // @date:2016-7-26 change the time-formate depend on file_mode.
  14. // @date:2016-7-29 support for unicode characterset.
  15. // @date:2016-7-29 write the log buffer into the file for specified time interval.
  16. // @date:2016-9-2 add 'TRACE_FUNCTION' to log function with returned value(type: int, dword).
  17. // @date:2016-12-2 add header file: <tchar.h>
  18. // @date:2017-1-24 add WRITE_ERRCODE_LOG
  19. // @date:2017-2-9 add FileModeEnum::CustomDir_DaySplit_Mode
  20. //
  21. //////////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include <Windows.h>
  24. #include <fstream>
  25. #include <string>
  26. #include <tchar.h>
  27. #include <io.h>
  28. #include <direct.h>
  29. #include <time.h>
  30. #include <process.h>
  31. // When using Unicode Windows functions, use Unicode C-Runtime functions too.
  32. #ifdef UNICODE
  33. #ifndef _UNICODE
  34. #define _UNICODE
  35. #endif
  36. #endif
  37. #define MAX_INFOR_LEN 4096
  38. #define MAX_TIME_LEN 128
  39. #define DEFALUT_INFOR_LEN 2048
  40. #define MIN_INFOR_LEN 256
  41. //#define TIME_TO_WRITE_LOG (5 * 1000)
  42. #define TIME_TO_WRITE_LOG (2 * 60 * 1000)
  43. #define LEVEL_TRACE_WRITEABLE 0x1111
  44. #define LEVEL_INFOR_WRITEABLE 0x1111
  45. #define LEVEL_DEBUG_WRITEABLE 0x0111
  46. #define LEVEL_WARNING_WRITEABLE 0x0011
  47. #define LEVEL_ERROR_WRITEABLE 0x0001
  48. #define LEVEL_NONE_WRITEABLE 0x0000
  49. #define GET_LOGGER() (Logger::GetInstance())
  50. #ifdef UNICODE
  51. # define WRITE_INFO_LOG (Logger::GetInstance()->TraceInfor)
  52. # define WRITE_DEBUG_LOG (Logger::GetInstance()->TraceDebug)
  53. # define WRITE_WARN_LOG (Logger::GetInstance()->TraceWarning)
  54. # define WRITE_ERROR_LOG (Logger::GetInstance()->TraceError)
  55. # define WRITE_ERRCODE_LOG (Logger::GetInstance()->TraceErrWithLastCode)
  56. # define WRITE_INFO_PARAM (Logger::GetInstance()->TraceInfor_f)
  57. # define WRITE_DEBUG_PARAM (Logger::GetInstance()->TraceDebug_f)
  58. # define WRITE_WARN_PARAM (Logger::GetInstance()->TraceWarning_f)
  59. # define WRITE_ERROR_PARAM (Logger::GetInstance()->TraceError_f)
  60. # define WRITE_TRACE_PARAM (Logger::GetInstance()->TraceDefault_f)
  61. # define TLOG_TEXT2(STRING) L##STRING
  62. # define TSTRING2 std::string
  63. # define tfstream std::wfstream
  64. #else
  65. # define WRITE_INFO_LOG (Logger::GetInstance()->TraceInfor)
  66. # define WRITE_DEBUG_LOG (Logger::GetInstance()->TraceDebug)
  67. # define WRITE_WARN_LOG (Logger::GetInstance()->TraceWarning)
  68. # define WRITE_ERROR_LOG (Logger::GetInstance()->TraceError)
  69. # define WRITE_ERRCODE_LOG (Logger::GetInstance()->TraceErrWithLastCode)
  70. # define WRITE_INFO_PARAM (Logger::GetInstance()->TraceInfor_f)
  71. # define WRITE_DEBUG_PARAM (Logger::GetInstance()->TraceDebug_f)
  72. # define WRITE_WARN_PARAM (Logger::GetInstance()->TraceWarning_f)
  73. # define WRITE_ERROR_PARAM (Logger::GetInstance()->TraceError_f)
  74. # define WRITE_TRACE_PARAM (Logger::GetInstance()->TraceDefault_f)
  75. # define TLOG_TEXT2(STRING) STRING
  76. # define TSTRING2 std::wstring
  77. # define tfstream std::fstream
  78. #endif //UNICODE
  79. #define TLOG_TEXT(STRING) TLOG_TEXT2(STRING)
  80. #if defined(UNICODE)
  81. typedef std::wstring tstring;
  82. typedef wchar_t tchar;
  83. #else
  84. typedef std::string tstring;
  85. typedef char tchar;
  86. #endif
  87. const tstring DEFAULT_LOG_DIR = TLOG_TEXT("");
  88. const tstring DEFAULT_LOG_NAME = TLOG_TEXT("C:\\Log.txt");
  89. const tstring TRACE_INFOR = TLOG_TEXT("Infor: ");
  90. const tstring TRACE_DEBUG = TLOG_TEXT("Debug: ");
  91. const tstring TRACE_WARNNING = TLOG_TEXT("Warning: ");
  92. const tstring TRACE_ERROR = TLOG_TEXT("Error: ");
  93. const tstring TRACE_DEFAULT = TLOG_TEXT("Trace: ");
  94. enum FileModeEnum
  95. {
  96. Default_Mode,
  97. Single_File_Mode,
  98. Day_Seperated_Mode,
  99. MAX_Mode
  100. };
  101. enum DateTypeEnum
  102. {
  103. For_Record_Type,
  104. For_File_Type
  105. };
  106. enum
  107. {
  108. /*path//directory//program.exe*/
  109. MODE_DEFAULT,
  110. /*path//directory//*/
  111. MODE_DIRECTORY,
  112. /*program.exe*/
  113. MODE_FILENAME,
  114. /*program*/
  115. MODE_FILENAME_ONLY,
  116. MODE_FILENAME_WITH_PATH,
  117. MODE_MAX
  118. };
  119. class Logger
  120. {
  121. public:
  122. ~Logger(void);
  123. /*
  124. * lpszDir is reserved.
  125. */
  126. static void InitLog(FileModeEnum eMode = Day_Seperated_Mode, const tchar* lpszDir = TLOG_TEXT(""));
  127. static void EndLog();
  128. static Logger* GetInstance();
  129. static CRITICAL_SECTION s_cs;
  130. static int bInitialized;
  131. static void DelayLoop(unsigned long usec);
  132. static void SetFileWriteMode(FileModeEnum eMode = Day_Seperated_Mode, const tchar* lpszDir = TLOG_TEXT(""));
  133. static DWORD GetCurExeNameOrPath(tchar* outFilePath, int sizeLen, int fetchKind);
  134. static bool IsEnableLogg()
  135. {
  136. return (bInitialized != 0);
  137. }
  138. void TraceInfor(const tchar* strInfo);
  139. void TraceDebug(const tchar* strInfo);
  140. void TraceWarning(const tchar* strInfo);
  141. void TraceError(const tchar* strInfo);
  142. void TraceDefault(const tchar* strInfo);
  143. void TraceInfor_f(const tchar* fmt, ...);
  144. void TraceDebug_f(const tchar* fmt, ...);
  145. void TraceWarning_f(const tchar* fmt, ...);
  146. void TraceError_f(const tchar* fmt, ...);
  147. void TraceDefault_f(const tchar* fmt, ...);
  148. //Set log file name with inner static value, this function always returned true.
  149. bool RefleshFileName()
  150. {
  151. if(m_eFileMode != Day_Seperated_Mode)
  152. {
  153. m_fileName = m_strLogDirOrFilePath;
  154. }
  155. return true;
  156. }
  157. tstring GetFileName();
  158. //0x1111, 0x0111, 0x0011, 0x0001, 0x0000
  159. void SetWriteAbleLevel(USHORT value = LEVEL_INFOR_WRITEABLE) { m_usWriteStatus = value; }
  160. void DisableRecord() { m_usWriteStatus = LEVEL_NONE_WRITEABLE; }
  161. void SetRecordNoBuffer()
  162. {
  163. if(!m_bWriteRealTime && GetTimerEvent() != NULL)
  164. {
  165. SetEvent(hEventWrite);
  166. }
  167. m_bWriteRealTime = true;
  168. }
  169. /*
  170. *Account for GetLastError() with plain text.
  171. *@param erroCode: the error code which would be explained. if 0 function would invoke
  172. *GetLastError() Api inner.
  173. */
  174. int FormatLastError(tchar* szOutMsg, unsigned int sizeLen, DWORD erroCode = 0);
  175. void TraceErrWithLastCode(const tchar* strInfo);
  176. HANDLE GetTimerEvent()
  177. {
  178. if(hEventWrite && hEventWrite != INVALID_HANDLE_VALUE)
  179. return hEventWrite;
  180. return NULL;
  181. }
  182. void Start();
  183. __int64 Now() const;
  184. __int64 NowInMicro() const;
  185. private:
  186. class CAutoWriteHelper;
  187. friend CAutoWriteHelper;
  188. Logger();
  189. static Logger* m_pLogger;
  190. tstring m_fileName;
  191. tfstream m_logStream;
  192. tstring GetCustomTime(DateTypeEnum type = For_Record_Type);
  193. tstring GetTimeOfDay();
  194. void Trace(tstring strInfo);
  195. void Trace_format(const tchar* fmt, va_list list_arg);
  196. bool WriteToFile(tstring str);
  197. bool ClearToFile();
  198. USHORT m_usWriteStatus;
  199. tstring m_strBuffer;
  200. unsigned int m_bufCurLen;
  201. static FileModeEnum m_eFileMode;
  202. static tstring m_strLogDirOrFilePath;
  203. HANDLE hMutexForBuffer;
  204. HANDLE hEventWrite;
  205. bool m_bWriteRealTime;
  206. LARGE_INTEGER m_liPerfFreq;
  207. LARGE_INTEGER m_liPerfStart;
  208. private:
  209. /*
  210. http://bbs.csdn.net/topics/390648143
  211. */
  212. class CAutoWriteHelper
  213. {
  214. public:
  215. CAutoWriteHelper():m_pLog(NULL),m_threadHandle(NULL)
  216. {
  217. if(Logger::InitLog(), m_pLog = Logger::GetInstance())
  218. {
  219. unsigned int threadID = 0;
  220. m_threadHandle = (HANDLE)_beginthreadex(NULL, 0,
  221. Logger::CAutoWriteHelper::TimerWriteProc,
  222. this, 0, &threadID);
  223. }
  224. }
  225. ~CAutoWriteHelper()
  226. {
  227. if(Logger::m_pLogger != NULL)
  228. {
  229. if(m_pLogger->GetTimerEvent() != NULL)
  230. {
  231. SetEvent(m_pLog->hEventWrite);
  232. WaitForSingleObject(m_threadHandle, INFINITE);
  233. CloseHandle(m_threadHandle);
  234. m_threadHandle = NULL;
  235. }
  236. m_pLog = NULL;
  237. delete Logger::m_pLogger;
  238. Logger::m_pLogger = NULL;
  239. }
  240. }
  241. static unsigned int _stdcall TimerWriteProc(void* param);
  242. private:
  243. Logger* m_pLog;
  244. HANDLE m_threadHandle;
  245. void WriteToLog()
  246. {
  247. if(m_pLog)
  248. {
  249. m_pLog->ClearToFile();
  250. }
  251. }
  252. HANDLE GetLogTimerEvent()
  253. {
  254. if(m_pLog)
  255. {
  256. return m_pLogger->GetTimerEvent();
  257. }
  258. return NULL;
  259. }
  260. };
  261. static CAutoWriteHelper helper;
  262. };
  263. namespace TwinkleLib {
  264. class TraceLogger
  265. {
  266. public:
  267. TraceLogger(const tchar* message, const tchar* fileName, int nLine)
  268. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
  269. {
  270. if(GET_LOGGER()->IsEnableLogg())
  271. {
  272. WRITE_TRACE_PARAM(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  273. }
  274. }
  275. TraceLogger(const tchar* message, const tchar* fileName, int nLine, int* pRet)
  276. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(pRet), m_pDwRet(NULL), m_retType(0)
  277. {
  278. if(GET_LOGGER()->IsEnableLogg())
  279. {
  280. WRITE_TRACE_PARAM(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  281. }
  282. }
  283. TraceLogger(const tchar* message, const tchar* fileName, int nLine, PDWORD pRet)
  284. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(pRet), m_retType(1)
  285. {
  286. if(GET_LOGGER()->IsEnableLogg())
  287. {
  288. WRITE_TRACE_PARAM(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  289. }
  290. }
  291. ~TraceLogger()
  292. {
  293. if(GET_LOGGER()->IsEnableLogg())
  294. {
  295. if(m_retType == 0)
  296. {
  297. WRITE_TRACE_PARAM(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}, return: {%d}."),
  298. m_pszMes, m_pszFileN, m_nLine, *m_pnRet);
  299. }
  300. else if(m_retType == 1)
  301. {
  302. WRITE_TRACE_PARAM(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}, return: {%u}."),
  303. m_pszMes, m_pszFileN, m_nLine, *m_pDwRet);
  304. }
  305. else
  306. {
  307. WRITE_TRACE_PARAM(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  308. }
  309. }
  310. }
  311. private:
  312. TraceLogger (TraceLogger const &);
  313. TraceLogger & operator = (TraceLogger const &);
  314. const tchar* m_pszMes;
  315. const tchar* m_pszFileN;
  316. int m_nLine;
  317. int* m_pnRet;
  318. PDWORD m_pDwRet;
  319. int m_retType;
  320. };
  321. }
  322. const tchar *_GetFileNameForLog(const tchar *pszFilePath);
  323. #define LOG_FUNCTION() TwinkleLib::TraceLogger _FunctionTraceLogger(\
  324. TLOG_TEXT(__FUNCTION__), _GetFileNameForLog(TLOG_TEXT(__FILE__)), __LINE__)
  325. #define TRACE_FUNCTION(pValue) TwinkleLib::TraceLogger _FunctionTraceLogger(\
  326. TLOG_TEXT(__FUNCTION__), _GetFileNameForLog(TLOG_TEXT(__FILE__)), __LINE__, (pValue))
  327. #endif //__TWINKLE_LOGGER_H__