Logger.cpp 20 KB

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