Logger.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. #include "stdafx.h"
  2. #include "Logger.h"
  3. FileModeEnum Logger::m_eFileMode = Default_Mode;
  4. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  5. int Logger::bInitialized = 0;
  6. Logger* Logger::m_pLogger = NULL;
  7. CRITICAL_SECTION Logger::s_cs;
  8. tstring Logger::m_strLogDirOrFilePath = DEFAULT_LOG_DIR;
  9. Logger::CAutoWriteHelper Logger::helper;
  10. #endif
  11. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  12. Logger::Logger(void)
  13. :m_bWriteRealTime(true),
  14. m_fileName(DEFAULT_LOG_NAME),
  15. m_usWriteStatus(LEVEL_OVERALL_WRITEABLE),
  16. m_bufCurLen(0),
  17. hMutexForBuffer(NULL),
  18. hEventWrite(NULL)
  19. {
  20. QueryPerformanceFrequency(&m_liPerfFreq);
  21. m_strBuffer = TLOG_TEXT("");
  22. SetFileWriteMode(Day_Seperated_Mode);
  23. hMutexForBuffer = CreateMutex(NULL, FALSE, LPCTSTR("iGobalBuffer"));
  24. if(!m_bWriteRealTime)
  25. {
  26. hEventWrite = CreateEvent(NULL, TRUE, FALSE, TLOG_TEXT("iGobalTimerWriteEvent"));
  27. }
  28. }
  29. #else
  30. Logger::Logger(void)
  31. :m_name(nullptr),
  32. m_bWriteRealTime(true),
  33. m_fileName(nullptr),
  34. m_usWriteStatus(LEVEL_NONE_WRITEABLE),
  35. m_bufCurLen(0),
  36. hMutexForBuffer(NULL),
  37. hEventWrite(NULL)
  38. {
  39. QueryPerformanceFrequency(&m_liPerfFreq);
  40. m_strBuffer = TLOG_TEXT("");
  41. SetFileWriteMode(Day_Seperated_Mode);
  42. hMutexForBuffer = CreateMutex(NULL, FALSE, LPCTSTR("iGobalBuffer"));
  43. if(!m_bWriteRealTime)
  44. {
  45. hEventWrite = CreateEvent(NULL, TRUE, FALSE, TLOG_TEXT("iGobalTimerWriteEvent"));
  46. }
  47. }
  48. Logger::Logger(const tstring& name, const tchar* lpszLogSummaryDir)
  49. :m_name(name),
  50. m_bWriteRealTime(true),
  51. m_fileName(name),
  52. m_usWriteStatus(LEVEL_OVERALL_WRITEABLE),
  53. m_bufCurLen(0),
  54. hMutexForBuffer(NULL),
  55. hEventWrite(NULL)
  56. {
  57. InitializeCriticalSection(&s_cs);
  58. QueryPerformanceFrequency(&m_liPerfFreq);
  59. m_strBuffer = TLOG_TEXT("");
  60. SetFileWriteMode(Module_Seperated_Mode, lpszLogSummaryDir);
  61. tstring mtxName(name);
  62. mtxName += TLOG_TEXT("iGobalBuffer");
  63. hMutexForBuffer = CreateMutex(NULL, FALSE, mtxName.c_str());
  64. if(!m_bWriteRealTime) {
  65. mtxName = name + TLOG_TEXT("TimerWriteEvent");
  66. hEventWrite = CreateEvent(NULL, TRUE, FALSE, mtxName.c_str());
  67. }
  68. _tprintf(TLOG_TEXT("-------------------------Logger::Contrustor: %s: \n"), m_name.c_str());
  69. }
  70. #endif
  71. Logger::~Logger(void)
  72. {
  73. WaitForSingleObject(hMutexForBuffer, INFINITE);
  74. if(m_strBuffer.length() > 0)
  75. {
  76. bool retFlag = false;
  77. if(m_eFileMode == Day_Seperated_Mode)
  78. {
  79. m_fileName = GetCustomTime(For_File_Type);
  80. }
  81. retFlag = WriteToFile(m_strBuffer);
  82. if(retFlag)
  83. {
  84. m_strBuffer = TLOG_TEXT("");
  85. m_bufCurLen = 0;
  86. }
  87. }
  88. ReleaseMutex(hMutexForBuffer);
  89. if(hMutexForBuffer && hMutexForBuffer != INVALID_HANDLE_VALUE)
  90. {
  91. CloseHandle(hMutexForBuffer);
  92. hMutexForBuffer = NULL;
  93. }
  94. if(hEventWrite && hEventWrite != INVALID_HANDLE_VALUE)
  95. {
  96. CloseHandle(hEventWrite);
  97. hEventWrite = NULL;
  98. }
  99. //TODO: Bug thirsty to fix !!! -Josephus@2017913 8:29:40
  100. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  101. //bInitialized = 0;
  102. #else
  103. DeleteCriticalSection(&s_cs);
  104. #endif
  105. }
  106. tstring Logger::GetCustomTime(DateTypeEnum type)
  107. {
  108. tchar strTime[MAX_TIME_LEN] = {0};
  109. time_t now;
  110. time(&now);
  111. tm *pTm = new tm;
  112. localtime_s(pTm, &now);
  113. if(type == For_File_Type)
  114. {
  115. _tcsftime(strTime, MAX_TIME_LEN*sizeof(tchar), TLOG_TEXT("%Y%m%d.log"), pTm);
  116. #ifdef LAZY_MODEL
  117. #ifndef UNICODE
  118. if(_access(m_strLogDirOrFilePath.c_str(), 0) == -1)
  119. #else
  120. char tlsDirectory[MAX_PATH] = {0};
  121. int nt = WideCharToMultiByte(CP_ACP, 0, m_strLogDirOrFilePath.c_str(),
  122. -1, tlsDirectory, MAX_PATH, NULL, NULL);
  123. if(_access(tlsDirectory, 0) == -1)
  124. #endif
  125. {
  126. CreateDirectory(m_strLogDirOrFilePath.c_str(), NULL);
  127. }
  128. #endif
  129. return (m_strLogDirOrFilePath + TLOG_TEXT("\\") + strTime);
  130. }
  131. else if(type == For_Record_Type)
  132. {
  133. _tcsftime(strTime, MAX_TIME_LEN*sizeof(tchar), TLOG_TEXT("[%Y/%m/%d %H:%M:%S] "), pTm);
  134. return tstring(strTime);
  135. }
  136. return TLOG_TEXT("");
  137. }
  138. tstring Logger::GetTimeOfDay()
  139. {
  140. FILETIME time;
  141. double timed;
  142. tchar strTime[MAX_TIME_LEN] = {0};
  143. GetSystemTimeAsFileTime( &time );
  144. // Apparently Win32 has units of 1e-7 sec (tenths of microsecs)
  145. // 4294967296 is 2^32, to shift high word over
  146. // 11644473600 is the number of seconds between
  147. // the Win32 epoch 1601-Jan-01 and the Unix epoch 1970-Jan-01
  148. // Tests found floating point to be 10x faster than 64bit int math.
  149. timed = ((time.dwHighDateTime * 4294967296e-7) - 11644473600.0) +
  150. (time.dwLowDateTime * 1e-7);
  151. tm *pTm = new tm;
  152. long temp = (long) timed;
  153. time_t clock = (long) timed;
  154. long appendix = (long) ((timed - temp) * 1e6);
  155. localtime_s(pTm, &clock);
  156. if(m_eFileMode == Day_Seperated_Mode || m_eFileMode == Module_Seperated_Mode)
  157. {
  158. _tcsftime(strTime, MAX_TIME_LEN, TLOG_TEXT("[%H:%M:%S"), pTm);
  159. }
  160. else
  161. {
  162. _tcsftime(strTime, MAX_TIME_LEN, TLOG_TEXT("[%Y/%m/%d %H:%M:%S"), pTm);
  163. }
  164. int nowLen = _tcslen(strTime);
  165. _stprintf_s(strTime+nowLen, MAX_TIME_LEN-nowLen, TLOG_TEXT(",%03d] "), appendix / 1000);
  166. return tstring(strTime);
  167. }
  168. void Logger::Trace(tstring strInfo)
  169. {
  170. bool retFlag = false;
  171. WaitForSingleObject(hMutexForBuffer, INFINITE);
  172. m_strBuffer += strInfo;
  173. m_strBuffer += TLOG_TEXT("\r\n");
  174. if(m_bWriteRealTime || m_strBuffer.length() > MAX_INFOR_LEN)
  175. {
  176. if(m_eFileMode == Day_Seperated_Mode || m_eFileMode == Module_Seperated_Mode)
  177. {
  178. m_fileName = GetCustomTime(For_File_Type);
  179. }
  180. //MessageBox(NULL, TLOG_TEXT(m_fileName.c_str()),
  181. // TLOG_TEXT(""), MB_ICONINFORMATION | MB_OK);
  182. retFlag = WriteToFile(m_strBuffer);
  183. if(retFlag)
  184. {
  185. m_strBuffer = TLOG_TEXT("");
  186. m_bufCurLen = 0;
  187. }
  188. }
  189. ReleaseMutex(hMutexForBuffer);
  190. }
  191. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  192. Logger* Logger::GetInstance()
  193. {
  194. EnterCriticalSection(&s_cs);
  195. if(m_pLogger == NULL)
  196. {
  197. m_pLogger = new Logger();
  198. //if(m_pLogger)
  199. //{
  200. // unsigned int threadID = 0;
  201. // HANDLE threadHD = (HANDLE)_beginthreadex(NULL, 0, Logger::TimerWriteProc, m_pLogger, 0, &threadID);
  202. // if(threadHD && threadHD != INVALID_HANDLE_VALUE)
  203. // {
  204. // CloseHandle(threadHD);
  205. // }
  206. //}
  207. }
  208. LeaveCriticalSection(&s_cs);
  209. return m_pLogger;
  210. }
  211. void Logger::InitLog(FileModeEnum eMode, const tchar* lpszDir)
  212. {
  213. if(bInitialized == 0)
  214. {
  215. InitializeCriticalSection(&s_cs);
  216. //SetFileWriteMode(eMode, lpszDir);
  217. bInitialized = 1;
  218. }
  219. }
  220. void Logger::ReleaseLog()
  221. {
  222. if(bInitialized)
  223. {
  224. DeleteCriticalSection(&s_cs);
  225. bInitialized = 0;
  226. }
  227. }
  228. void Logger::EndLog()
  229. {
  230. if(m_pLogger != NULL)
  231. {
  232. delete m_pLogger;
  233. m_pLogger = NULL;
  234. }
  235. }
  236. #endif
  237. void Logger::SetFileWriteMode(FileModeEnum eMode, const tchar* lpszDir)
  238. {
  239. tchar fileName[MAX_PATH] = {0};
  240. if(eMode == Single_File_Mode) {
  241. if(lpszDir == NULL || _tcslen(lpszDir) <= 0) {
  242. if(GetCurExeNameOrPath(fileName, MAX_PATH, MODE_FILENAME_WITH_PATH) != -1) {
  243. _tcscat_s(fileName, MAX_PATH*sizeof(tchar), TLOG_TEXT("_log.txt"));
  244. m_strLogDirOrFilePath = fileName;
  245. m_eFileMode = Single_File_Mode;
  246. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  247. if(m_pLogger != NULL && m_pLogger->RefleshFileName()){;}
  248. #endif
  249. return;
  250. }
  251. }
  252. else {
  253. if(GetCurExeNameOrPath(fileName, MAX_PATH, MODE_FILENAME_ONLY) != -1) {
  254. _tcscat_s(fileName, MAX_PATH*sizeof(tchar), TLOG_TEXT("_log.txt"));
  255. m_strLogDirOrFilePath = lpszDir;
  256. const tchar* pchSuffix = _tcsrchr(lpszDir, TLOG_TEXT('\\'));
  257. if(pchSuffix == NULL || pchSuffix[1] != '\0') {
  258. m_strLogDirOrFilePath += tstring(TLOG_TEXT("\\"));
  259. }
  260. m_strLogDirOrFilePath += fileName;
  261. m_eFileMode = Single_File_Mode;
  262. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  263. if(m_pLogger != NULL && m_pLogger->RefleshFileName()){;}
  264. #endif
  265. return;
  266. }
  267. }
  268. }
  269. else if(eMode == Day_Seperated_Mode)
  270. {
  271. if(lpszDir == NULL || _tcslen(lpszDir) <= 0) {
  272. if(GetCurExeNameOrPath(fileName, MAX_PATH, MODE_DIRECTORY) != -1) {
  273. m_strLogDirOrFilePath = tstring(fileName) + TLOG_TEXT("LogFiles");
  274. }
  275. } else {
  276. const tchar* pchSuffix = _tcsrchr(lpszDir, TLOG_TEXT('\\'));
  277. if (pchSuffix != NULL && pchSuffix[1] == TLOG_TEXT('\0')) {
  278. _tcscpy_s(fileName, MAX_PATH*sizeof(tchar), lpszDir);
  279. fileName[_tcslen(fileName)-1] = TLOG_TEXT('\0');
  280. m_strLogDirOrFilePath = tstring(fileName);
  281. } else {
  282. m_strLogDirOrFilePath = lpszDir;
  283. }
  284. //MessageBox(NULL, TLOG_TEXT(m_strLogDirOrFilePath.c_str()),
  285. // TLOG_TEXT(""), MB_ICONINFORMATION | MB_OK);
  286. }
  287. #ifndef LAZY_MODEL
  288. #ifndef UNICODE
  289. if(_access(m_strLogDirOrFilePath.c_str(), 0) == -1)
  290. #else
  291. char tlsDirectory[MAX_PATH] = {0};
  292. int nt = WideCharToMultiByte(CP_ACP, 0, m_strLogDirOrFilePath.c_str(),
  293. -1, tlsDirectory, MAX_PATH, NULL, NULL);
  294. if(_access(tlsDirectory, 0) == -1)
  295. #endif
  296. {
  297. CreateDirectory(m_strLogDirOrFilePath.c_str(), NULL);
  298. }
  299. #endif
  300. m_eFileMode = Day_Seperated_Mode;
  301. }
  302. else if(eMode == Default_Mode)
  303. {
  304. m_eFileMode = Default_Mode;
  305. m_strLogDirOrFilePath = DEFAULT_LOG_NAME;
  306. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  307. if(m_pLogger != NULL && m_pLogger->RefleshFileName()){;}
  308. #endif
  309. }
  310. #if (defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  311. else if(eMode == Module_Seperated_Mode) {
  312. if(m_name.length() <= 0) {
  313. _tprintf(TLOG_TEXT("module name is invalid.\n"));
  314. return;
  315. }
  316. if(lpszDir == NULL || _tcslen(lpszDir) <= 0) {
  317. if(GetCurExeNameOrPath(fileName, MAX_PATH, MODE_DIRECTORY) != -1) {
  318. m_strLogDirOrFilePath = tstring(fileName) + TLOG_TEXT("LogFiles");
  319. }else {
  320. _tprintf(TLOG_TEXT("GetCurExeNameOrPath failed: %s"), fileName);
  321. return;
  322. }
  323. }else {
  324. const tchar* pchSuffix = _tcsrchr(lpszDir, TLOG_TEXT('\\'));
  325. if (pchSuffix != NULL && pchSuffix[1] == TLOG_TEXT('\0')) {
  326. _tcscpy_s(fileName, MAX_PATH*sizeof(tchar), lpszDir);
  327. fileName[_tcslen(fileName)-1] = TLOG_TEXT('\0');
  328. m_strLogDirOrFilePath = tstring(fileName);
  329. }else {
  330. m_strLogDirOrFilePath = lpszDir;
  331. }
  332. }
  333. m_strLogDirOrFilePath += TLOG_TEXT("\\");
  334. m_strLogDirOrFilePath += m_name;
  335. #ifndef LAZY_MODEL
  336. #ifndef UNICODE
  337. if(_access(m_strLogDirOrFilePath.c_str(), 0) == -1) {
  338. #else
  339. char tlsDirectory[MAX_PATH] = {0};
  340. int nt = WideCharToMultiByte(CP_ACP, 0, m_strLogDirOrFilePath.c_str(),
  341. -1, tlsDirectory, MAX_PATH, NULL, NULL);
  342. if(_access(tlsDirectory, 0) == -1) {
  343. #endif
  344. CreateDirectory(m_strLogDirOrFilePath.c_str(), NULL);
  345. }
  346. #endif
  347. m_eFileMode = Module_Seperated_Mode;
  348. }
  349. #endif
  350. }
  351. void Logger::TraceInfor(const tchar* strInfo)
  352. {
  353. if((m_usWriteStatus & LEVEL_INFOR_WRITEABLE) != LEVEL_INFOR_WRITEABLE) return;
  354. tstring str(GetTimeOfDay()+TRACE_INFOR);
  355. str += strInfo;
  356. Trace(str);
  357. }
  358. void Logger::TraceDebug(const tchar* strInfo)
  359. {
  360. if((m_usWriteStatus & LEVEL_DEBUG_WRITEABLE) != LEVEL_DEBUG_WRITEABLE) return;
  361. tstring str(GetTimeOfDay()+TRACE_DEBUG);
  362. str += strInfo;
  363. Trace(str);
  364. }
  365. void Logger::TraceWarning(const tchar* strInfo)
  366. {
  367. if((m_usWriteStatus & LEVEL_WARNING_WRITEABLE) != LEVEL_WARNING_WRITEABLE) return;
  368. tstring str(GetTimeOfDay() + TRACE_WARNNING);
  369. str += strInfo;
  370. Trace(str);
  371. }
  372. void Logger::TraceError(const tchar* strInfo)
  373. {
  374. if((m_usWriteStatus & LEVEL_ERROR_WRITEABLE) != LEVEL_ERROR_WRITEABLE) return;
  375. tstring str(GetTimeOfDay() + TRACE_ERROR);
  376. str += strInfo;
  377. Trace(str);
  378. }
  379. void Logger::TraceDefault(const tchar* strInfo)
  380. {
  381. if((m_usWriteStatus & LEVEL_LIMITED_WRITEABLE) != LEVEL_LIMITED_WRITEABLE) return;
  382. tstring str(GetTimeOfDay() + TRACE_DEFAULT);
  383. str += strInfo;
  384. Trace(str);
  385. }
  386. void Logger::TraceTrace(const tchar* szFile, int line, const tchar* strInfo)
  387. {
  388. if((m_usWriteStatus & LEVEL_TRACE_WRITEABLE) != LEVEL_TRACE_WRITEABLE) return;
  389. tstring str(GetTimeOfDay() + TRACE_TRACE);
  390. tstringstream tss;
  391. tss << line;
  392. str += strInfo;
  393. str = str + TLOG_TEXT(" file: {") + szFile + TLOG_TEXT("}, line: {") + tss.str() + TLOG_TEXT("}.");
  394. Trace(str);
  395. }
  396. void Logger::TraceAssert(const tchar* szFile, int line, const tchar* strInfo)
  397. {
  398. if((m_usWriteStatus & LEVEL_ERROR_WRITEABLE) != LEVEL_ERROR_WRITEABLE) return;
  399. tstring str(GetTimeOfDay() + TRACE_ASSERT);
  400. tstringstream tss;
  401. tss << line;
  402. str += strInfo;
  403. str = str + TLOG_TEXT(" file: {") + szFile + TLOG_TEXT("}, line: {") + tss.str() + TLOG_TEXT("}.");
  404. Trace(str);
  405. }
  406. void Logger::Trace_format(const tchar* fmt, va_list list_arg)
  407. {
  408. int n;
  409. n = _vsctprintf(fmt, list_arg);
  410. //#ifdef UNICODE
  411. // n = _vscwprintf(fmt, list_arg);
  412. //#else
  413. // n = _vscprintf(fmt, list_arg);
  414. //#endif
  415. if(n > 0)
  416. {
  417. tchar *buf = new tchar[n+1];
  418. memset(buf, 0, sizeof(tchar)*(n+1));
  419. _vstprintf_s(buf, n+1, fmt, list_arg);
  420. //#ifdef UNICODE
  421. // vswprintf_s(buf, n+1, fmt, list_arg);
  422. //#else
  423. // vsprintf_s(buf, n+1, fmt, list_arg);
  424. //#endif
  425. Trace(tstring(buf));
  426. delete buf;
  427. buf = NULL;
  428. }
  429. va_end(list_arg);
  430. }
  431. void Logger::TraceInfor_f(const tchar* fmt, ...)
  432. {
  433. if((m_usWriteStatus & LEVEL_INFOR_WRITEABLE) != LEVEL_INFOR_WRITEABLE) return;
  434. tstring str(GetTimeOfDay()+TRACE_INFOR + fmt);
  435. va_list arg;
  436. va_start(arg, fmt);
  437. Trace_format(str.c_str(), arg);
  438. }
  439. void Logger::TraceDebug_f(const tchar* fmt, ...)
  440. {
  441. if((m_usWriteStatus & LEVEL_DEBUG_WRITEABLE) != LEVEL_DEBUG_WRITEABLE) return;
  442. tstring str(GetTimeOfDay()+TRACE_DEBUG + fmt);
  443. va_list arg;
  444. va_start(arg, fmt);
  445. Trace_format(str.c_str(), arg);
  446. }
  447. void Logger::TraceWarning_f(const tchar* fmt, ...)
  448. {
  449. if((m_usWriteStatus & LEVEL_WARNING_WRITEABLE) != LEVEL_WARNING_WRITEABLE) return;
  450. tstring str(GetTimeOfDay()+TRACE_WARNNING + fmt);
  451. va_list arg;
  452. va_start(arg, fmt);
  453. Trace_format(str.c_str(), arg);
  454. }
  455. void Logger::TraceError_f(const tchar* fmt, ...)
  456. {
  457. if((m_usWriteStatus & LEVEL_ERROR_WRITEABLE) != LEVEL_ERROR_WRITEABLE) return;
  458. tstring str(GetTimeOfDay()+TRACE_ERROR + fmt);
  459. va_list arg;
  460. va_start(arg, fmt);
  461. Trace_format(str.c_str(), arg);
  462. }
  463. void Logger::TraceDefault_f(const tchar* fmt, ...)
  464. {
  465. if((m_usWriteStatus & LEVEL_LIMITED_WRITEABLE) != LEVEL_LIMITED_WRITEABLE) return;
  466. tstring str(GetTimeOfDay()+TRACE_DEFAULT + fmt);
  467. va_list arg;
  468. va_start(arg, fmt);
  469. Trace_format(str.c_str(), arg);
  470. }
  471. void Logger::TraceTrace_f(const tchar* szFile, int line, const tchar* fmt, ...)
  472. {
  473. if((m_usWriteStatus & LEVEL_TRACE_WRITEABLE) != LEVEL_TRACE_WRITEABLE) return;
  474. tstring str(GetTimeOfDay()+TRACE_TRACE + fmt);
  475. tstringstream tss;
  476. tss << line;
  477. //str += TLOG_TEXT("{");
  478. //str += fmt;
  479. //str += TLOG_TEXT("}");
  480. str = str + TLOG_TEXT(" file: {") + szFile + TLOG_TEXT("}, line: {") + tss.str() + TLOG_TEXT("}.");
  481. va_list arg;
  482. va_start(arg, fmt);
  483. Trace_format(str.c_str(), arg);
  484. }
  485. /*获取当前调用该日志文件的程序路径或程序名称(无类型后缀),主用于日志名称声明
  486. *@param: [out] outFilePath 获取到程序路径或程序名称的字符串
  487. * [in] sizeLen outFilePath字符数组的大小
  488. * [in] fetchKind FALSE表示仅获取程序路径,TRUE表示获取程序名称
  489. *@return 如果获取成功则表示实际得到的字符串长度,-1表示失败
  490. */
  491. DWORD Logger::GetCurExeNameOrPath(tchar* outFilePath, int sizeLen, int fetchKind)
  492. {
  493. DWORD tmpDwRes = 0;
  494. if(sizeLen <= 0)
  495. return -1;
  496. memset(outFilePath, 0, sizeof(tchar)*sizeLen);
  497. if(tmpDwRes = GetModuleFileName(NULL, outFilePath, sizeLen) == 0)
  498. {
  499. _stprintf_s(outFilePath, sizeLen, TLOG_TEXT("GetModuleFileName failed %d"), GetLastError());
  500. return -1;
  501. }
  502. if(fetchKind == MODE_DEFAULT)
  503. {
  504. return tmpDwRes;
  505. }
  506. if(fetchKind == MODE_FILENAME_WITH_PATH)
  507. {
  508. tchar* pch2 = _tcsrchr(outFilePath, TLOG_TEXT('.'));
  509. if(pch2 == NULL)
  510. {
  511. return -1;
  512. }
  513. pch2[0] = TLOG_TEXT('\0');
  514. return (int)(pch2 - outFilePath);
  515. }
  516. tchar* pch1 = _tcsrchr(outFilePath, TLOG_TEXT('\\'));
  517. if(fetchKind == MODE_DIRECTORY)
  518. {
  519. if(pch1 == NULL)
  520. {
  521. return -1;
  522. }
  523. if(int(pch1 - outFilePath) + 1 < sizeLen)
  524. {
  525. *(pch1 + 1) = TLOG_TEXT('\0');
  526. }
  527. return (int)(pch1 - outFilePath + 1);
  528. }
  529. tchar tmpFilePath[MAX_PATH] = {0};
  530. int idx = 0;
  531. tchar* pstart = pch1 + 1;
  532. if(fetchKind == MODE_FILENAME)
  533. {
  534. for(; *pstart != TLOG_TEXT('\0'); idx++)
  535. {
  536. tmpFilePath[idx] = *pstart++;
  537. }
  538. tmpFilePath[idx] = TLOG_TEXT('\0');
  539. memcpy_s(outFilePath, sizeof(tchar)*sizeLen, tmpFilePath, sizeof(tchar)*(idx+1));
  540. return idx+1;
  541. }
  542. if(fetchKind == MODE_FILENAME_ONLY)
  543. {
  544. tchar* pch2 = _tcsrchr(outFilePath, TLOG_TEXT('.'));
  545. if(pch1 == NULL || pch2 == NULL)
  546. {
  547. return -1;
  548. }
  549. for(; pstart < pch2; idx++)
  550. {
  551. tmpFilePath[idx] = *pstart++;
  552. }
  553. tmpFilePath[idx] = TLOG_TEXT('\0');
  554. memcpy_s(outFilePath, sizeof(tchar)*sizeLen, tmpFilePath, sizeof(tchar)*(idx+1));
  555. return idx+1;
  556. }
  557. return -1;
  558. }
  559. void Logger::DelayLoop(unsigned long usec)
  560. {
  561. LOG_FUNCTION();
  562. LARGE_INTEGER freq, start, now;
  563. //返回硬件支持的高精度计数器的每秒钟嘀嗒的次数,零表示硬件不支持,读取失败
  564. if (!QueryPerformanceFrequency(&freq))
  565. {
  566. Sleep(usec);
  567. }
  568. else
  569. {
  570. QueryPerformanceCounter(&start);
  571. for(;;)
  572. {
  573. QueryPerformanceCounter((LARGE_INTEGER*) &now);
  574. if( ((double)(now.QuadPart - start.QuadPart) / (double)freq.QuadPart) * 1000 > usec ) break;
  575. }
  576. }
  577. }
  578. bool Logger::WriteToFile(tstring str)
  579. {
  580. bool flag = false;
  581. EnterCriticalSection(&s_cs);
  582. try
  583. {
  584. m_logStream.open(m_fileName.c_str(), tfstream::in | tfstream::app);
  585. if(!m_logStream)
  586. {
  587. //MessageBox(NULL, TLOG_TEXT(m_fileName.c_str()),
  588. // TLOG_TEXT(""), MB_ICONINFORMATION | MB_OK);
  589. str.clear();
  590. }
  591. else if(m_logStream.is_open())
  592. {
  593. m_logStream << str.c_str();// << endl;
  594. m_logStream.close();
  595. flag = true;
  596. }
  597. }
  598. catch (std::exception e)
  599. {
  600. str.clear();
  601. LeaveCriticalSection(&s_cs);
  602. return flag;
  603. }
  604. LeaveCriticalSection(&s_cs);
  605. return flag;
  606. }
  607. bool Logger::ClearToFile()
  608. {
  609. bool flag = false;
  610. WaitForSingleObject(hMutexForBuffer, INFINITE);
  611. if(m_strBuffer.length() > 0)
  612. {
  613. if(m_eFileMode == Day_Seperated_Mode || m_eFileMode == Module_Seperated_Mode)
  614. {
  615. m_fileName = GetCustomTime(For_File_Type);
  616. }
  617. flag = WriteToFile(m_strBuffer);
  618. if(flag)
  619. {
  620. m_strBuffer = TLOG_TEXT("");
  621. m_bufCurLen = 0;
  622. }
  623. }
  624. ReleaseMutex(hMutexForBuffer);
  625. return flag;
  626. }
  627. int Logger::FormatLastError(tchar* szOutMsg, unsigned int sizeLen, DWORD erroCode)
  628. {
  629. if(sizeLen == 0 || szOutMsg == NULL)
  630. return 0;
  631. LPVOID lpMsgBuf;
  632. if(erroCode == 0)
  633. {
  634. erroCode = ::GetLastError();
  635. }
  636. if(!FormatMessage(
  637. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  638. FORMAT_MESSAGE_FROM_SYSTEM |
  639. FORMAT_MESSAGE_MAX_WIDTH_MASK,
  640. NULL,
  641. erroCode,
  642. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  643. (LPTSTR) &lpMsgBuf,
  644. 0, NULL ))
  645. {
  646. return 0;
  647. }
  648. _tcscpy_s(szOutMsg, sizeLen,(LPCTSTR)lpMsgBuf);
  649. LocalFree(lpMsgBuf);
  650. return _tcslen(szOutMsg);
  651. }
  652. void Logger::Start()
  653. {
  654. QueryPerformanceCounter(&m_liPerfStart);
  655. }
  656. __int64 Logger::Now() const
  657. {
  658. LARGE_INTEGER liPerfNow;
  659. QueryPerformanceCounter(&liPerfNow);
  660. return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000) / m_liPerfFreq.QuadPart);
  661. }
  662. __int64 Logger::NowInMicro() const
  663. {
  664. LARGE_INTEGER liPerfNow;
  665. QueryPerformanceCounter(&liPerfNow);
  666. return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000000) / m_liPerfFreq.QuadPart);
  667. }
  668. void Logger::TraceErrWithLastCode(const tchar* strInfo)
  669. {
  670. DWORD dwErrCode = ::GetLastError();
  671. TCHAR szMsg[MIN_INFOR_LEN] = {0};
  672. int nLen = FormatLastError(szMsg, MIN_INFOR_LEN, dwErrCode);
  673. TraceError_f(TLOG_TEXT("%s : (%d)%s."), strInfo, dwErrCode, szMsg);
  674. return;
  675. }
  676. const tchar * _GetFileNameForLog(const tchar *pszFilePath)
  677. {
  678. if(pszFilePath == NULL || _tcslen(pszFilePath) == 0)
  679. return TLOG_TEXT("empty");
  680. const tchar* backlash = _tcsrchr(pszFilePath, (int)(TLOG_TEXT('\\')));
  681. if(!backlash)
  682. {
  683. return pszFilePath;
  684. }
  685. return (backlash+1);
  686. }
  687. #if !(defined(TWINKLE_LOGGER_VERSION) && TWINKLE_LOGGER_VERSION == 2)
  688. unsigned int _stdcall Logger::CAutoWriteHelper::TimerWriteProc(void* param)
  689. {
  690. if(param == nullptr)
  691. {
  692. return -1;
  693. }
  694. Logger::CAutoWriteHelper* helper = (Logger::CAutoWriteHelper*)param;
  695. HANDLE hEvent = helper->GetLogTimerEvent();
  696. BOOL bLoop = TRUE;
  697. if(!hEvent)
  698. {
  699. return 0;
  700. }
  701. while(bLoop)
  702. {
  703. DWORD dwRet = WaitForSingleObject(hEvent, TIME_TO_WRITE_LOG);
  704. switch(dwRet)
  705. {
  706. case WAIT_OBJECT_0:
  707. //WRITE_TRACE_PARAM(TLOG_TEXT("WAIT_OBJECT_0"));
  708. helper->WriteToLog();
  709. bLoop = FALSE;
  710. break;
  711. case WAIT_TIMEOUT:
  712. //WRITE_TRACE_PARAM(TLOG_TEXT("WAIT_TIMEOUT"));
  713. helper->WriteToLog();
  714. break;
  715. case WAIT_FAILED:
  716. WRITE_TRACE_PARAM_INNER_USE(TLOG_TEXT("WAIT_FAILED"));
  717. bLoop = FALSE;
  718. break;
  719. }
  720. }
  721. //WRITE_TRACE_PARAM(TLOG_TEXT("hiahiahia"));
  722. return 0;
  723. }
  724. #else
  725. LoggerShell LoggerShell::GetInstance(const tstring& name)
  726. {
  727. return GetLoggerFactory()->GetLoggerProduct(name);
  728. }
  729. LoggerList LoggerShell::GetCurrentLoggers()
  730. {
  731. LoggerList list;
  732. GetLoggerFactory()->InitializeLoggerList(list);
  733. return list;
  734. }
  735. bool LoggerShell::Exists(const tstring& name)
  736. {
  737. return false;
  738. }
  739. LoggerShell LoggerShell::GetDefaultLogger()
  740. {
  741. LoggerShell instance;
  742. GetLoggerFactory()->InitializeDefaultLogger(instance);
  743. return instance;
  744. }
  745. //Define real global variable.
  746. LoggerFactory logger_factory;
  747. #endif