Logger.h 20 KB

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