中间件底层,websocket

LoggerEntity.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. #include "StdAfx.h"
  2. #include "LoggerEntity.h"
  3. #include <io.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <boost/filesystem.hpp>
  8. SINGLETON_IMPLEMENT(CLoggerEntity)
  9. ILogger& ILogger::getInstance(void)
  10. {
  11. return CLoggerEntity::GetInstance();
  12. }
  13. CLoggerEntity::CLoggerEntity(void) : m_bStopLog(TRUE), m_bIsLogger(FALSE), m_nFilterClass(LOG_CLASS_GENERAL), m_nFilterLevel(0x07), m_pThread(nullptr), m_logBufferSize(0), m_pListCtrlCount(100)
  14. {
  15. m_arClass[0] = "PDU";
  16. m_arClass[1] = "DEV";
  17. m_arClass[2] = "业务";
  18. m_arClass[3] = "基本";
  19. m_arLevel[0] = "";
  20. m_arLevel[1] = "警告";
  21. m_arLevel[2] = "错误";
  22. m_arLevel[3] = "信息";
  23. m_arLevel[4] = "详细";
  24. }
  25. CLoggerEntity::~CLoggerEntity(void)
  26. {
  27. //close();
  28. }
  29. /****************************************************************
  30. **【函数名称】 init
  31. **【函数功能】 日志初始化
  32. **【参数】 pList:日志显示的List控件
  33. nDevType:使用日志的系统
  34. lpFilePath:日志记录路径
  35. **【返回值】
  36. *****************************************************************/
  37. void CLoggerEntity::init(CListCtrl* pList, LOG_DEV nDevType, LPCTSTR lpFilePath /*= NULL */ )
  38. {
  39. // 列表控件的初始化
  40. if((m_pListCtrl = pList) != NULL)
  41. __frameControl();
  42. else
  43. __initConsoleWindow();
  44. // 保存设备类型
  45. m_nDevType = nDevType;
  46. switch(m_nDevType)
  47. {
  48. case LOG_DEV_CTI:
  49. m_strLoggerName = _T("log_cti");
  50. break;
  51. case LOG_DEV_IVR:
  52. m_strLoggerName = _T("log_ivr");
  53. break;
  54. case LOG_DEV_ACD:
  55. m_strLoggerName = _T("log_acd");
  56. break;
  57. case LOG_DEV_VS:
  58. m_strLoggerName = _T("log_vs");
  59. break;
  60. case LOG_DEV_FS:
  61. m_strLoggerName = _T("log_fs");
  62. break;
  63. case LOG_DEV_AC:
  64. m_strLoggerName = _T("log_ac");
  65. break;
  66. case LOG_DEV_SC:
  67. m_strLoggerName = _T("log_sc");
  68. break;
  69. case LOG_DEV_GUARD:
  70. m_strLoggerName = _T("log_guard");
  71. break;
  72. case LOG_DEV_SERVER:
  73. m_strLoggerName = _T("log_http");
  74. break;
  75. default:
  76. m_strLoggerName = _T("log_unknow");
  77. break;
  78. }
  79. if (lpFilePath == NULL)
  80. {
  81. // 默认路径
  82. m_strFileDircet = _T("d:\\middleware_log");
  83. }
  84. else
  85. {
  86. // 指定路径
  87. m_strFileDircet = lpFilePath;
  88. }
  89. m_bStopLog = FALSE;
  90. // 初始化记录日志线程
  91. if (m_pThread == nullptr)
  92. m_pThread = std::make_shared<std::thread>(std::bind(&CLoggerEntity::logThread, this));
  93. }
  94. /****************************************************************
  95. **【函数名称】 close
  96. **【函数功能】 日志关闭
  97. **【参数】
  98. **【返回值】
  99. *****************************************************************/
  100. void CLoggerEntity::close(void)
  101. {
  102. m_bIsLogger = FALSE;
  103. m_bStopLog.store(true);
  104. m_cond.notify_one(); // 条件变量通知
  105. if (m_pThread&& m_pThread->joinable()) {
  106. m_pThread->join();
  107. }
  108. __flush();
  109. }
  110. /****************************************************************
  111. **【函数名称】 start
  112. **【函数功能】 开始显示日志
  113. **【参数】
  114. **【返回值】
  115. *****************************************************************/
  116. void CLoggerEntity::start( void )
  117. {
  118. m_bIsLogger = TRUE;
  119. }
  120. /****************************************************************
  121. **【函数名称】 stop
  122. **【函数功能】 停止显示日志
  123. **【参数】
  124. **【返回值】
  125. *****************************************************************/
  126. void CLoggerEntity::stop( void )
  127. {
  128. std::unique_lock<std::mutex> lock(m_mut);
  129. m_bIsLogger = FALSE;
  130. lock.unlock();
  131. }
  132. /****************************************************************
  133. **【函数名称】 log
  134. **【函数功能】 添加一条新日志
  135. **【参数】 nClass:日志类型
  136. nLevel:日志级别
  137. format:日志信息
  138. **【返回值】
  139. *****************************************************************/
  140. void CLoggerEntity::log(LOG_CLASS nClass, LOG_LEVEL nLevel, char* format, ...)
  141. {
  142. try {
  143. if (!m_bIsLogger) return;
  144. // 检查过滤标志
  145. if (!m_bStopLog && (m_nFilterClass & nClass) == nClass && (m_nFilterLevel & nLevel) == nLevel && nLevel < 5) {
  146. // 解析日志信息参数
  147. char szMsgBuffer[LOG_BUFFER_LENGTH];
  148. memset(szMsgBuffer, 0, sizeof(szMsgBuffer));
  149. va_list ap;
  150. va_start(ap, format);
  151. vsnprintf(szMsgBuffer, sizeof(szMsgBuffer), format, ap);
  152. va_end(ap);
  153. __pushLog(nClass, nLevel, szMsgBuffer);
  154. }
  155. }
  156. catch (CException* e) {
  157. std::ofstream file("logger_except.txt", std::ios::app);
  158. if (file) {
  159. file << "CException 异常:";
  160. TCHAR szErr[1024];
  161. if (e->GetErrorMessage(szErr, 1024))
  162. file << szErr << std::endl;
  163. file.close();
  164. }
  165. e->Delete();
  166. }
  167. }
  168. /****************************************************************
  169. **【函数名称】 filterShow
  170. **【函数功能】 设置日志内容过滤方式
  171. **【参数】 nClass:日志类型
  172. nLevel:日志级别
  173. **【返回值】
  174. *****************************************************************/
  175. void CLoggerEntity::filterShow( LOG_CLASS nClass /*= LOG_CLASS_GENERAL*/, LOG_LEVEL nLevel /*= LOG_LEVEL_NORMAL */ )
  176. {
  177. m_nFilterClass = nClass; // 日志类型过滤
  178. m_nFilterLevel = nLevel; // 日志级别过滤
  179. }
  180. /****************************************************************
  181. **【函数名称】 __frameControl
  182. **【函数功能】 日志界面控制
  183. **【参数】
  184. **【返回值】
  185. *****************************************************************/
  186. void CLoggerEntity::__frameControl()
  187. {
  188. CRect mRect;
  189. m_pListCtrl->GetClientRect(&mRect);
  190. int length = mRect.right - mRect.left - 240;
  191. //加载日志图标信息
  192. CImageList imgList;
  193. imgList.Create(16, 16, ILC_MASK|ILC_COLOR16, 3, 1);
  194. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
  195. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_WARNING));
  196. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_ERROR));
  197. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
  198. m_pListCtrl->SetImageList(&imgList, LVSIL_SMALL);
  199. imgList.Detach();
  200. //加载日志列表
  201. m_pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP | LVS_EX_SUBITEMIMAGES);
  202. m_pListCtrl->InsertColumn(0, (LPCTSTR)"时间", LVCFMT_LEFT, 140, -1);
  203. m_pListCtrl->InsertColumn(1, (LPCTSTR)"类型", LVCFMT_LEFT, 50, -1);
  204. m_pListCtrl->InsertColumn(2, (LPCTSTR)"分类", LVCFMT_LEFT, 50, -1);
  205. m_pListCtrl->InsertColumn(3, (LPCTSTR)"信息", LVCFMT_LEFT, length, -1);
  206. m_pListCtrl->SetItemCount(m_pListCtrlCount); // 设置总行数
  207. }
  208. /****************************************************************
  209. **【函数名称】 启动控制台窗口
  210. **【函数功能】 __initConsoleWindow
  211. **【参数】
  212. **【返回值】
  213. *****************************************************************/
  214. void CLoggerEntity::__initConsoleWindow( void )
  215. {
  216. if(!AllocConsole())
  217. return;
  218. int nCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
  219. if(nCrt == -1)
  220. return;
  221. FILE* fp = _fdopen(nCrt, "w");
  222. if(fp == NULL)
  223. return;
  224. *stdout = *fp;
  225. setvbuf(stdout, NULL, _IONBF, 0);
  226. }
  227. /****************************************************************
  228. **【函数名称】 创建日志文件
  229. **【函数功能】 __openLoggerFile
  230. **【参数】 lpFile
  231. **【返回值】
  232. *****************************************************************/
  233. FILE* CLoggerEntity::__openLoggerFile( void )
  234. {
  235. static int nCount = 1;
  236. FILE* pFile = NULL;
  237. // 获取当前日期
  238. CTime time = CTime::GetCurrentTime();
  239. // 创建日志总目录
  240. if (_access(m_strFileDircet, 0) == -1) {
  241. boost::filesystem::create_directories(m_strFileDircet.GetBuffer(0));
  242. m_strFileDircet.ReleaseBuffer();
  243. }
  244. // 创建日期目录
  245. CString strPath = _T("");
  246. strPath.Format(_T("%s\\%d-%d-%d"), m_strFileDircet, time.GetYear(), time.GetMonth(), time.GetDay());
  247. // 防止日期文件夹存在时,日志文件索引不会从1开始
  248. static CString lastPath = strPath; // 初始化目录日期
  249. if (lastPath != strPath)
  250. {
  251. nCount = 1;
  252. lastPath = strPath;
  253. }
  254. if(_access(strPath, 0) == -1)
  255. {
  256. nCount = 1;
  257. CreateDirectoryA(strPath, NULL);
  258. }
  259. // 如果文件存在且大于指定大小,生成新的文件名
  260. CString strFileName = _T("");
  261. struct stat st;
  262. do
  263. {
  264. memset(&st, 0, sizeof(st));
  265. strFileName.Format(_T("%s\\%s_%d.txt"), strPath, m_strLoggerName, nCount);
  266. if(stat(strFileName, &st) == 0)
  267. {
  268. if(st.st_size > FILE_MAX_SIZE) nCount++;
  269. }
  270. }
  271. while(st.st_size > FILE_MAX_SIZE);
  272. // 打开文件
  273. fopen_s(&pFile, strFileName, "a+");
  274. return pFile;
  275. }
  276. /****************************************************************
  277. **【函数名称】 __pushLog
  278. **【函数功能】 将日志压入链表
  279. **【参数】
  280. **【返回值】
  281. *****************************************************************/
  282. void CLoggerEntity::__pushLog( LOG_CLASS nClass, LOG_LEVEL nLevel, LPCTSTR lpMessage )
  283. {
  284. // 获取当前时间
  285. CTime t1 = CTime::GetCurrentTime();
  286. CString strTime = t1.Format("%Y-%m-%d %H:%M:%S");
  287. if (m_logBufferSize.load() <= LOG_BUFFER_SIZE && !m_bStopLog.load()){
  288. PLOG_ITEM pItem = new(std::nothrow)LOG_ITEM(nClass, nLevel, strTime, lpMessage);
  289. if (pItem != NULL){
  290. std::unique_lock<std::mutex>lock(m_mut);
  291. m_ItemList.emplace_back(pItem);
  292. m_logBufferSize.store(m_ItemList.size());
  293. m_cond.notify_one(); // 条件变量通知
  294. }
  295. }
  296. }
  297. /****************************************************************
  298. **【函数名称】 __logShow
  299. **【函数功能】 显示日志
  300. **【参数】
  301. **【返回值】
  302. *****************************************************************/
  303. void CLoggerEntity::__saveLog( PLOG_ITEM pItem, FILE* pFile )
  304. {
  305. LOG_CLASS Class = pItem->Class;
  306. LOG_LEVEL Level = pItem->Level;
  307. CString LogContent;
  308. LogContent.Format(_T("%s %s %s %s\r\n"), pItem->Date, m_arLevel[Level], m_arClass[Class], pItem->Content);
  309. // 写日志文件
  310. fwrite(LogContent.GetBuffer(0), LogContent.GetLength(), 1, pFile);
  311. if(!m_bIsLogger || m_bStopLog.load())
  312. return;
  313. if (Level > LOG_LEVEL_NORMAL)
  314. return;
  315. // UI展现
  316. if(m_pListCtrl == NULL)
  317. {
  318. cout << LogContent;
  319. }
  320. else
  321. {
  322. // 日志显示行数控制(500)
  323. if (m_pListCtrl->GetItemCount() >= m_pListCtrlCount)
  324. {
  325. m_pListCtrl->DeleteAllItems();
  326. }
  327. // 定义系统日志显示条数的上限为499条
  328. m_pListCtrl->InsertItem(0, pItem->Date, Level);
  329. m_pListCtrl->SetItemText(0, 1, m_arLevel[Level]);
  330. m_pListCtrl->SetItemText(0, 2, m_arClass[Class]);
  331. m_pListCtrl->SetItemText(0, 3, pItem->Content);
  332. }
  333. }
  334. /****************************************************************
  335. **【函数名称】 记录日志线程函数
  336. **【函数功能】 __logThreadFunc
  337. **【参数】 pParam:线程参数
  338. **【返回值】
  339. *****************************************************************/
  340. void CLoggerEntity::logThread()
  341. {
  342. PLOG_ITEM pItem = NULL;
  343. while (!m_bStopLog.load()) {
  344. std::unique_lock<std::mutex> lock(m_mut);
  345. for (; m_ItemList.empty() && !m_bStopLog.load();) {
  346. m_cond.wait(lock);
  347. }
  348. if (m_bStopLog.load()) break;
  349. lock.unlock();
  350. FILE *pFile = __openLoggerFile();
  351. if (pFile) {
  352. for (; m_logBufferSize > 0 && !m_bStopLog.load();) {
  353. std::unique_lock<std::mutex> lock1(m_mut);
  354. if (!m_ItemList.empty()) {
  355. pItem = m_ItemList.front();
  356. m_ItemList.pop_front();
  357. m_logBufferSize.store(m_ItemList.size());
  358. lock1.unlock();
  359. if (pItem) {
  360. __saveLog(pItem, pFile);
  361. delete pItem;
  362. pItem = NULL;
  363. }
  364. }
  365. else {
  366. m_logBufferSize.store(0);
  367. break;
  368. }
  369. }
  370. // 关闭文件
  371. fclose(pFile);
  372. pFile = NULL;
  373. }
  374. }
  375. std::cout << "线程结束" << std::endl;
  376. }
  377. /****************************************************************
  378. **【函数名称】 __flush
  379. **【函数功能】 保存残留的LOGITEM
  380. **【参数】
  381. **【返回值】
  382. *****************************************************************/
  383. void CLoggerEntity::__flush(void)
  384. {
  385. if (m_ItemList.empty())
  386. return;
  387. FILE *pFile = __openLoggerFile();
  388. if (pFile == NULL)
  389. return;
  390. for (auto pItem : m_ItemList) {
  391. if (pItem != NULL) {
  392. __saveLog(pItem, pFile);
  393. delete pItem;
  394. pItem = NULL;
  395. }
  396. }
  397. m_ItemList.clear();
  398. fclose(pFile);
  399. pFile = NULL;
  400. }