Logger.h 20 KB

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