Logger.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. #ifndef __TWINKLE_LOGGER_H__
  2. #define __TWINKLE_LOGGER_H__
  3. #pragma once
  4. //#define TWINKLE_LOGGER_VERSION 1
  5. //////////////////////////////////////////////////////////////////////////
  6. // @author: Josephus
  7. // @date: 2016-5-3
  8. // @version: 1.0.0
  9. // @edit_history:
  10. // @date:2016-6-26 set option for no buffer or not.
  11. // @date:2016-7-2 delete erroCode stored;
  12. // add Trace Logger format; add GetLastError() formatting message;
  13. // add LOG_FUNCION() to log function enter and leave event;
  14. // @date:2016-7-4 improve the logger time accurating to millisecond;
  15. // @date:2016-7-26 change the time-formate depend on file_mode.
  16. // @date:2016-7-29 support for unicode characterset.
  17. // @date:2016-7-29 write the log buffer into the file for specified time interval.
  18. // @date:2016-9-2 add 'TRACE_FUNCTION' to log function with returned value(type: int, dword).
  19. // @date:2016-12-2 add header file: <tchar.h>
  20. // @date:2017-1-24 add WRITE_ERRCODE_LOG
  21. // @date:2017-2-9 add FileModeEnum::CustomDir_DaySplit_Mode
  22. // @date:2017-5-2 add WRITE_TRACE_LOG
  23. // @date:2017-5-8 add LOG_ASSERT and change WRITE_TRACE_PARAM implemention.
  24. // @date:2017-5-18 add LAZY_MODEL definition for avoiding creating LogFiles folder.
  25. //
  26. //////////////////////////////////////////////////////////////////////////
  27. #include <Windows.h>
  28. #include <fstream>
  29. #include <string>
  30. #include <sstream>
  31. #include <tchar.h>
  32. #include <io.h>
  33. #include <direct.h>
  34. #include <time.h>
  35. #include <process.h>
  36. #include <vector>
  37. #include <map>
  38. // When using Unicode Windows functions, use Unicode C-Runtime functions too.
  39. #ifdef UNICODE
  40. #ifndef _UNICODE
  41. #define _UNICODE
  42. #endif
  43. #endif
  44. #define LAZY_MODEL
  45. #define MAX_INFOR_LEN 4096
  46. #define MAX_TIME_LEN 128
  47. #define DEFALUT_INFOR_LEN 2048
  48. #define MIN_INFOR_LEN 256
  49. //#define TIME_TO_WRITE_LOG (5 * 1000)
  50. #define TIME_TO_WRITE_LOG (2 * 60 * 1000)
  51. #define LEVEL_OVERALL_WRITEABLE 0xFFFF
  52. #define LEVEL_LIMITED_WRITEABLE 0x00FF
  53. #define LEVEL_TRACE_WRITEABLE 0x001F
  54. #define LEVEL_INFOR_WRITEABLE 0x000F
  55. #define LEVEL_DEBUG_WRITEABLE 0x0007
  56. #define LEVEL_WARNING_WRITEABLE 0x0003
  57. #define LEVEL_ERROR_WRITEABLE 0x0001
  58. #define LEVEL_NONE_WRITEABLE 0x0000
  59. typedef int LogLevel;
  60. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  61. # define GET_LOGGER() (Logger::GetInstance())
  62. #else
  63. #include "TWSmartPointer.h"
  64. # define GET_LOGGER() (GetLoggerFactory()->GetLoggerProduct(tstring()))
  65. # define GET_LOG_INSTANCE(ndc) (GetLoggerFactory()->GetLoggerProduct(tstring(ndc)))
  66. #endif //!(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  67. #ifdef UNICODE
  68. # define WRITE_INFO_LOG (GET_LOGGER()->TraceInfor)
  69. # define WRITE_DEBUG_LOG (GET_LOGGER()->TraceDebug)
  70. # define WRITE_WARN_LOG (GET_LOGGER()->TraceWarning)
  71. # define WRITE_ERROR_LOG (GET_LOGGER()->TraceError)
  72. # define WRITE_ERRCODE_LOG (GET_LOGGER()->TraceErrWithLastCode)
  73. # define WRITE_TRACE_LOG(str) \
  74. GET_LOGGER()->TraceTrace(_GetFileNameForLog(__FILE__), __LINE__, str)
  75. # define WRITE_INFO_PARAM (GET_LOGGER()->TraceInfor_f)
  76. # define WRITE_DEBUG_PARAM (GET_LOGGER()->TraceDebug_f)
  77. # define WRITE_WARN_PARAM (GET_LOGGER()->TraceWarning_f)
  78. # define WRITE_ERROR_PARAM (GET_LOGGER()->TraceError_f)
  79. # define WRITE_TRACE_PARAM_INNER_USE (GET_LOGGER()->TraceDefault_f)
  80. # define WRITE_TRACE_PARAM(fmt, ...) \
  81. GET_LOGGER()->TraceTrace_f(_GetFileNameForLog(__FILE__), __LINE__, fmt, __VA_ARGS__)
  82. #ifdef NDEBUG
  83. #define _TLOG_ASSERT(expr) \
  84. do { if (!expr){ \
  85. GET_LOGGER()->TraceAssert(_GetFileNameForLog(__FILE__), __LINE__, \
  86. L"(\""#expr"\") Under NDEBUG !!!"); \
  87. }while(0)
  88. #else
  89. # define _TLOG_ASSERT(expr) \
  90. do { if (!expr){ \
  91. GET_LOGGER()->TraceAssert(_GetFileNameForLog(__FILE__), __LINE__, L"(\""#expr"\") !!!"); \
  92. if(1 == _CrtDbgReport(_CRT_ASSERT, (__FILE__), __LINE__, \
  93. NULL, #expr) ) \
  94. {_CrtDbgBreak(); \
  95. }}}while(0)
  96. #endif
  97. # define TLOG_TEXT2(STRING) L##STRING
  98. # define TSTRING2 std::string
  99. # define tfstream std::wfstream
  100. #else
  101. # define WRITE_INFO_LOG (GET_LOGGER()->TraceInfor)
  102. # define WRITE_DEBUG_LOG (GET_LOGGER()->TraceDebug)
  103. # define WRITE_WARN_LOG (GET_LOGGER()->TraceWarning)
  104. # define WRITE_ERROR_LOG (GET_LOGGER()->TraceError)
  105. # define WRITE_ERRCODE_LOG (GET_LOGGER()->TraceErrWithLastCode)
  106. # define WRITE_TRACE_LOG(str) \
  107. GET_LOGGER()->TraceTrace(_GetFileNameForLog(__FILE__), __LINE__, str)
  108. # define WRITE_INFO_PARAM (GET_LOGGER()->TraceInfor_f)
  109. # define WRITE_DEBUG_PARAM (GET_LOGGER()->TraceDebug_f)
  110. # define WRITE_WARN_PARAM (GET_LOGGER()->TraceWarning_f)
  111. # define WRITE_ERROR_PARAM (GET_LOGGER()->TraceError_f)
  112. # define WRITE_TRACE_PARAM_INNER_USE (GET_LOGGER()->TraceDefault_f)
  113. # define WRITE_TRACE_PARAM(fmt, ...) \
  114. GET_LOGGER()->TraceTrace_f(_GetFileNameForLog(__FILE__), __LINE__, fmt, __VA_ARGS__)
  115. #ifdef NDEBUG
  116. #define _TLOG_ASSERT(expr) \
  117. do { if (!expr){ \
  118. GET_LOGGER()->TraceAssert(_GetFileNameForLog(__FILE__), __LINE__, \
  119. "(\""#expr"\") Under NDEBUG !!!"); \
  120. }while(0)
  121. #else
  122. # define _TLOG_ASSERT(expr) \
  123. do { if (!expr){ \
  124. GET_LOGGER()->TraceAssert(_GetFileNameForLog(__FILE__), __LINE__, "(\""#expr"\") !!!"); \
  125. if(1 == _CrtDbgReport(_CRT_ASSERT, (__FILE__), __LINE__, \
  126. NULL, #expr) ) \
  127. {_CrtDbgBreak(); \
  128. }}}while(0)
  129. #endif
  130. # define TLOG_TEXT2(STRING) STRING
  131. # define TSTRING2 std::wstring
  132. # define tfstream std::fstream
  133. #endif //UNICODE
  134. #define TLOG_TEXT(STRING) TLOG_TEXT2(STRING)
  135. #define LOG_ASSERT(expr) _TLOG_ASSERT(expr)
  136. #if defined(UNICODE)
  137. typedef std::wstring tstring;
  138. typedef std::wstringstream tstringstream;
  139. typedef wchar_t tchar;
  140. #else
  141. typedef std::string tstring;
  142. typedef std::stringstream tstringstream;
  143. typedef char tchar;
  144. #endif
  145. //class Logger;
  146. const tstring DEFAULT_LOG_DIR = TLOG_TEXT("");
  147. const tstring DEFAULT_LOG_NAME = TLOG_TEXT("C:\\Log.txt");
  148. const tstring TRACE_INFOR = TLOG_TEXT("Infor: ");
  149. const tstring TRACE_DEBUG = TLOG_TEXT("Debug: ");
  150. const tstring TRACE_WARNNING = TLOG_TEXT("Warning: ");
  151. const tstring TRACE_ERROR = TLOG_TEXT("Error: ");
  152. const tstring TRACE_DEFAULT = TLOG_TEXT("Trace: ");
  153. const tstring TRACE_TRACE = TLOG_TEXT("Trace: ");
  154. const tstring TRACE_ASSERT = TLOG_TEXT("Assert: ");
  155. enum FileModeEnum
  156. {
  157. Default_Mode,
  158. Single_File_Mode,
  159. Day_Seperated_Mode,
  160. Module_Seperated_Mode,
  161. MAX_Mode
  162. };
  163. enum DateTypeEnum
  164. {
  165. For_Record_Type,
  166. For_File_Type
  167. };
  168. enum
  169. {
  170. /*path//directory//program.exe*/
  171. MODE_DEFAULT,
  172. /*path//directory//*/
  173. MODE_DIRECTORY,
  174. /*program.exe*/
  175. MODE_FILENAME,
  176. /*program*/
  177. MODE_FILENAME_ONLY,
  178. MODE_FILENAME_WITH_PATH,
  179. MODE_MAX
  180. };
  181. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  182. class LoggerShell;
  183. typedef std::vector<LoggerShell> LoggerList;
  184. typedef std::map<tstring, LoggerShell> LoggerMap;
  185. #endif //(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  186. class Logger
  187. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  188. : public TWSharedObject
  189. #endif
  190. {
  191. public:
  192. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  193. Logger(const tstring& name, const tchar* lpszLogSummaryDir = TLOG_TEXT(""));
  194. #endif //(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  195. ~Logger(void);
  196. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  197. /** lpszDir is reserved. */
  198. static void InitLog(FileModeEnum eMode = Day_Seperated_Mode, const tchar* lpszDir = TLOG_TEXT(""));
  199. static void ReleaseLog();
  200. static Logger* GetInstance();
  201. static CRITICAL_SECTION s_cs;
  202. static int bInitialized;
  203. static bool IsEnableLogg() { return (bInitialized != 0); }
  204. static void EndLog();
  205. static void SetFileWriteMode(FileModeEnum eMode = Day_Seperated_Mode,
  206. const tchar* lpszDir = TLOG_TEXT(""));
  207. #else
  208. bool IsEnableLogg() { return !(m_usWriteStatus == LEVEL_NONE_WRITEABLE); }
  209. void SetLogParentDirectory(const tchar* lpszdir);
  210. void SetFileWriteMode(FileModeEnum eMode = Day_Seperated_Mode,
  211. const tchar* lpszDir = TLOG_TEXT(""));
  212. #endif
  213. static void DelayLoop(unsigned long usec);
  214. static DWORD GetCurExeNameOrPath(tchar* outFilePath, int sizeLen, int fetchKind);
  215. void TraceInfor(const tchar* strInfo);
  216. void TraceDebug(const tchar* strInfo);
  217. void TraceWarning(const tchar* strInfo);
  218. void TraceError(const tchar* strInfo);
  219. void TraceDefault(const tchar* strInfo);
  220. void TraceTrace(const tchar* szFile, int line, const tchar* strInfo);
  221. void TraceAssert(const tchar* szFile, int line, const tchar* strInfo);
  222. void TraceInfor_f(const tchar* fmt, ...);
  223. void TraceDebug_f(const tchar* fmt, ...);
  224. void TraceWarning_f(const tchar* fmt, ...);
  225. void TraceError_f(const tchar* fmt, ...);
  226. void TraceDefault_f(const tchar* fmt, ...);
  227. void TraceTrace_f(const tchar* szFile, int line, const tchar* fmt, ...);
  228. /*
  229. *Account for GetLastError() with plain text.
  230. *@param erroCode: the error code which would be explained. if 0 function would invoke
  231. *GetLastError() Api inner.
  232. */
  233. int FormatLastError(tchar* szOutMsg, unsigned int sizeLen, DWORD erroCode = 0);
  234. void TraceErrWithLastCode(const tchar* strInfo);
  235. //Set log file name with inner static value, this function always returned true.
  236. bool RefleshFileName() {
  237. if(m_eFileMode != Day_Seperated_Mode) {
  238. m_fileName = m_strLogDirOrFilePath;
  239. }
  240. return true;
  241. }
  242. tstring GetFileName();
  243. //0x1111, 0x0111, 0x0011, 0x0001, 0x0000
  244. void SetWriteAbleLevel(USHORT value = LEVEL_INFOR_WRITEABLE) { m_usWriteStatus = value; }
  245. void DisableRecord() { m_usWriteStatus = LEVEL_NONE_WRITEABLE; }
  246. void SetRecordNoBuffer() {
  247. if(!m_bWriteRealTime && GetTimerEvent() != NULL) {
  248. SetEvent(hEventWrite);
  249. }
  250. m_bWriteRealTime = true;
  251. }
  252. HANDLE GetTimerEvent() {
  253. if(hEventWrite && hEventWrite != INVALID_HANDLE_VALUE)
  254. return hEventWrite;
  255. return NULL;
  256. }
  257. void Start();
  258. __int64 Now() const;
  259. __int64 NowInMicro() const;
  260. private:
  261. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  262. class CAutoWriteHelper;
  263. friend CAutoWriteHelper;
  264. static Logger* m_pLogger;
  265. static tstring m_strLogDirOrFilePath;
  266. #else
  267. tstring m_strLogDirOrFilePath;
  268. #endif //!(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  269. Logger();
  270. tstring m_fileName;
  271. tfstream m_logStream;
  272. tstring GetCustomTime(DateTypeEnum type = For_Record_Type);
  273. tstring GetTimeOfDay();
  274. void Trace(tstring strInfo);
  275. void Trace_format(const tchar* fmt, va_list list_arg);
  276. bool WriteToFile(tstring str);
  277. bool ClearToFile();
  278. USHORT m_usWriteStatus;
  279. tstring m_strBuffer;
  280. unsigned int m_bufCurLen;
  281. static FileModeEnum m_eFileMode;
  282. HANDLE hMutexForBuffer;
  283. HANDLE hEventWrite;
  284. bool m_bWriteRealTime;
  285. LARGE_INTEGER m_liPerfFreq;
  286. LARGE_INTEGER m_liPerfStart;
  287. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  288. public:
  289. tstring GetName() const { return m_name; }
  290. CRITICAL_SECTION s_cs;
  291. private:
  292. // Disallow copying of instances of this class
  293. Logger(const Logger&);
  294. Logger& operator = (const Logger& );
  295. friend class LoggerShell;
  296. private:
  297. tstring m_name;
  298. #else
  299. private:
  300. /*
  301. http://bbs.csdn.net/topics/390648143
  302. */
  303. class CAutoWriteHelper
  304. {
  305. public:
  306. CAutoWriteHelper():m_pLog(NULL),m_threadHandle(NULL)
  307. {
  308. if(Logger::InitLog(), m_pLog = Logger::GetInstance())
  309. {
  310. unsigned int threadID = 0;
  311. m_threadHandle = (HANDLE)_beginthreadex(NULL, 0,
  312. Logger::CAutoWriteHelper::TimerWriteProc,
  313. this, 0, &threadID);
  314. }
  315. }
  316. ~CAutoWriteHelper()
  317. {
  318. if(Logger::m_pLogger != NULL)
  319. {
  320. if(m_pLogger->GetTimerEvent() != NULL)
  321. {
  322. SetEvent(m_pLog->hEventWrite);
  323. WaitForSingleObject(m_threadHandle, INFINITE);
  324. CloseHandle(m_threadHandle);
  325. m_threadHandle = NULL;
  326. }
  327. m_pLog = NULL;
  328. Logger::EndLog();
  329. }
  330. }
  331. static unsigned int _stdcall TimerWriteProc(void* param);
  332. private:
  333. Logger* m_pLog;
  334. HANDLE m_threadHandle;
  335. void WriteToLog()
  336. {
  337. if(m_pLog)
  338. {
  339. m_pLog->ClearToFile();
  340. }
  341. }
  342. HANDLE GetLogTimerEvent()
  343. {
  344. if(m_pLog)
  345. {
  346. return m_pLogger->GetTimerEvent();
  347. }
  348. return NULL;
  349. }
  350. };
  351. static CAutoWriteHelper helper;
  352. #endif //(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  353. };
  354. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  355. class LoggerFactory;
  356. class LoggerShell
  357. {
  358. public:
  359. static LoggerShell GetInstance(const tstring& name);
  360. static LoggerList GetCurrentLoggers();
  361. static bool Exists(const tstring& name);
  362. static LoggerShell GetDefaultLogger();
  363. LoggerShell()
  364. :swaddle(nullptr)
  365. {}
  366. LoggerShell(Logger* ptr)
  367. :swaddle(ptr)
  368. {
  369. if (swaddle)
  370. printf("LoggerShell::Constructor: %s\n", swaddle->GetName().c_str());
  371. if (swaddle)
  372. swaddle->AddRef();
  373. }
  374. LoggerShell(const LoggerShell& rhs)
  375. : swaddle(rhs.swaddle)
  376. {
  377. if (swaddle)
  378. printf("LoggerShell::Constructor1: %s\n", swaddle->GetName().c_str());
  379. if (swaddle)
  380. swaddle->AddRef();
  381. }
  382. LoggerShell & operator = (const LoggerShell& rhs)
  383. {
  384. if (swaddle)
  385. printf("LoggerShell::Constructor2: %s\n", swaddle->GetName().c_str());
  386. LoggerShell(rhs).Swap(*this);
  387. return *this;
  388. }
  389. ~LoggerShell()
  390. {
  391. if (swaddle)
  392. printf("LoggerShell::Destructor: %s\n", swaddle->GetName().c_str());
  393. if (swaddle)
  394. swaddle->RemoveRef();
  395. }
  396. void Swap(LoggerShell & other)
  397. {
  398. using std::swap;
  399. swap(swaddle, other.swaddle);
  400. }
  401. //LogLevel GetLogLevel() const
  402. //{
  403. // return swaddle->GetLogLevel();
  404. //}
  405. //void SetLogLevel(LogLevel ll)
  406. //{
  407. // swaddle->SetLogLevel(ll);
  408. //}
  409. tstring GetName() const
  410. {
  411. return swaddle->GetName();
  412. }
  413. const Logger* operator->() const
  414. {
  415. if (swaddle) return swaddle;
  416. else return nullptr;
  417. }
  418. Logger* operator->()
  419. {
  420. if (swaddle) return swaddle;
  421. else return nullptr;
  422. }
  423. bool IsFillFlesh() const
  424. {
  425. if (swaddle) return true;
  426. return false;
  427. }
  428. private:
  429. Logger * swaddle;
  430. };
  431. class LoggerFactory
  432. {
  433. public:
  434. LoggerFactory()
  435. :m_strLogDirectory(TLOG_TEXT(""))
  436. {
  437. /*if (!m_defaultLogger.IsFillFlesh())*/ {
  438. tchar szExeName[MAX_PATH] = { 0 };
  439. if (Logger::GetCurExeNameOrPath(szExeName, MAX_PATH, MODE_FILENAME_ONLY) >= 0) {
  440. m_defaultLogger = CreateNewLoggerInstance(szExeName);
  441. }
  442. if (Logger::GetCurExeNameOrPath(szExeName, MAX_PATH, MODE_DIRECTORY) >= 0) {
  443. m_strLogDirectory = szExeName;
  444. }
  445. }
  446. }
  447. ~LoggerFactory() {}
  448. LoggerShell GetLoggerProduct(const tstring& name)
  449. {
  450. LoggerShell logger;
  451. LoggerMap::iterator iter;
  452. if (name.empty())
  453. {
  454. //TODO:
  455. logger = m_defaultLogger;
  456. }
  457. else if ((iter = m_ActivedLoggers.find(name)) != m_ActivedLoggers.end())
  458. {
  459. logger = iter->second;
  460. }
  461. else
  462. {
  463. logger = CreateNewLoggerInstance(name);
  464. //m_ActivedLoggers.insert(std::pair<tstring, LoggerShell>);
  465. std::pair<LoggerMap::iterator, bool> ret = m_ActivedLoggers.insert(make_pair(name, logger));
  466. }
  467. return logger;
  468. }
  469. LoggerShell CreateNewLoggerInstance(const tstring& name)
  470. {
  471. return LoggerShell(new Logger(name, m_strLogDirectory.c_str()));
  472. }
  473. void InitializeLoggerList(LoggerList& list)
  474. {
  475. list.reserve(list.size() + m_ActivedLoggers.size());
  476. LoggerMap::const_iterator citer = m_ActivedLoggers.cbegin();
  477. while (citer != m_ActivedLoggers.cend())
  478. {
  479. list.push_back(citer->second);
  480. citer++;
  481. }
  482. }
  483. void InitializeDefaultLogger(LoggerShell& logger)
  484. {
  485. logger = m_defaultLogger;
  486. }
  487. void Test() {
  488. printf("directory: %s\n", m_strLogDirectory.c_str());
  489. }
  490. bool SaveAndCreateLogDirectory(const tchar* lpszPath)
  491. {
  492. size_t len = 0;
  493. if (lpszPath == NULL || (len = _tcslen(lpszPath)) == 0)
  494. return false;
  495. if (len == 1)
  496. if (!((lpszPath[0] <= TLOG_TEXT('z') && lpszPath[0] >= TLOG_TEXT('a'))
  497. || (lpszPath[0] <= TLOG_TEXT('Z') && lpszPath[0] >= TLOG_TEXT('A'))))
  498. return false;
  499. if (len >= 2 && lpszPath[1] != TLOG_TEXT(':'))
  500. return false;
  501. if (len >= 3 && (lpszPath[2] != TLOG_TEXT('\\') && lpszPath[2] != TLOG_TEXT('/')))
  502. return false;
  503. if (len <= 3)
  504. {
  505. tchar disk = lpszPath[0];
  506. if (disk >= TLOG_TEXT('a') && disk <= TLOG_TEXT('z')) disk -= 32;
  507. int no = disk - TLOG_TEXT('A');
  508. DWORD dwRes = GetLogicalDrives();
  509. if ((dwRes & (1 << no)) == 0)
  510. return false;
  511. m_strLogDirectory.assign(1, disk);
  512. m_strLogDirectory.append(TLOG_TEXT(":"));
  513. return true;
  514. }
  515. tchar* path = new tchar[len + 2];
  516. memset(path, 0, sizeof(tchar)*(len + 2));
  517. memcpy(path, lpszPath, len);
  518. path[len] = TLOG_TEXT('\0');
  519. int pos = len - 1;
  520. for (; pos >= 0 && (path[pos] == TLOG_TEXT('\\') || path[pos] == TLOG_TEXT('/')); --pos){;}
  521. path[pos + 1] = TLOG_TEXT('\0');
  522. path[pos + 2] = TLOG_TEXT('\0');
  523. len = strlen(path);
  524. WIN32_FIND_DATA wfd = { 0 };
  525. HANDLE hFile = FindFirstFile(path, &wfd);
  526. path[pos + 1] = TLOG_TEXT('\\');
  527. if (hFile != INVALID_HANDLE_VALUE) {
  528. FindClose(hFile);
  529. }
  530. if (hFile == INVALID_HANDLE_VALUE || !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  531. printf("Create log directory.\n");
  532. tchar *p = &path[0];
  533. while ((p = strchr(p, TLOG_TEXT('\\'))) != NULL) {
  534. *p = 0;
  535. DWORD dwRes = GetFileAttributes(path);
  536. if (!(dwRes != INVALID_FILE_ATTRIBUTES && (dwRes & FILE_ATTRIBUTE_DIRECTORY))) {
  537. if (!CreateDirectory(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
  538. delete[] path;
  539. return false;
  540. }
  541. }
  542. *p = TLOG_TEXT('\\');
  543. p++;
  544. }
  545. }
  546. path[pos + 1] = TLOG_TEXT('\0');
  547. m_strLogDirectory.assign(path);
  548. delete[] path;
  549. if(m_defaultLogger.IsFillFlesh()) {
  550. m_defaultLogger->SetFileWriteMode(Module_Seperated_Mode, m_strLogDirectory.c_str());
  551. }
  552. return true;
  553. }
  554. private:
  555. LoggerFactory(const LoggerFactory&);
  556. LoggerFactory& operator=(const LoggerFactory&);
  557. LoggerMap m_ActivedLoggers;
  558. LoggerShell m_defaultLogger;
  559. tstring m_strLogDirectory;
  560. };
  561. //Declare global variable.
  562. extern LoggerFactory logger_factory;
  563. static LoggerFactory* GetLoggerFactory() { return &logger_factory; }
  564. #endif //(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  565. namespace TwinkleLib {
  566. class TraceLogger
  567. {
  568. public:
  569. TraceLogger(const tchar* message, const tchar* fileName, int nLine)
  570. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
  571. {
  572. if(GET_LOGGER()->IsEnableLogg())
  573. {
  574. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  575. }
  576. }
  577. TraceLogger(const tchar* message, const tchar* fileName, int nLine, int* pRet)
  578. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(pRet), m_pDwRet(NULL), m_retType(0)
  579. {
  580. if(GET_LOGGER()->IsEnableLogg())
  581. {
  582. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  583. }
  584. }
  585. TraceLogger(const tchar* message, const tchar* fileName, int nLine, PDWORD pRet)
  586. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(pRet), m_retType(1)
  587. {
  588. if(GET_LOGGER()->IsEnableLogg())
  589. {
  590. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Enter {%s}, file: {%s}, line: {%d}."), m_pszMes, m_pszFileN, m_nLine);
  591. }
  592. }
  593. ~TraceLogger()
  594. {
  595. if(GET_LOGGER()->IsEnableLogg())
  596. {
  597. if(m_retType == 0)
  598. {
  599. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}, return: {%d}."),
  600. m_pszMes, m_pszFileN, m_nLine, *m_pnRet);
  601. }
  602. else if(m_retType == 1)
  603. {
  604. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}, return: {%u}."),
  605. m_pszMes, m_pszFileN, m_nLine, *m_pDwRet);
  606. }
  607. else
  608. {
  609. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("Leave {%s}, file: {%s}, line: {%d}."),
  610. m_pszMes, m_pszFileN, m_nLine);
  611. }
  612. }
  613. }
  614. private:
  615. TraceLogger (TraceLogger const &);
  616. TraceLogger & operator = (TraceLogger const &);
  617. const tchar* m_pszMes;
  618. const tchar* m_pszFileN;
  619. int m_nLine;
  620. int* m_pnRet;
  621. PDWORD m_pDwRet;
  622. int m_retType;
  623. };
  624. }
  625. const tchar *_GetFileNameForLog(const tchar *pszFilePath);
  626. #define LOG_FUNCTION() TwinkleLib::TraceLogger _FunctionTraceLogger(\
  627. TLOG_TEXT(__FUNCTION__), _GetFileNameForLog(TLOG_TEXT(__FILE__)), __LINE__)
  628. #define TRACE_FUNCTION(pValue) TwinkleLib::TraceLogger _FunctionTraceLogger(\
  629. TLOG_TEXT(__FUNCTION__), _GetFileNameForLog(TLOG_TEXT(__FILE__)), __LINE__, (pValue))
  630. #endif //__TWINKLE_LOGGER_H__