中间件底层,websocket

LoggerEntity.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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. if (m_bStopLog.load()) return;
  103. m_bStopLog.store(true);
  104. m_bIsLogger = FALSE;
  105. m_cond.notify_one(); // 条件变量通知
  106. try
  107. {
  108. if (m_pThread&& m_pThread->joinable()) {
  109. m_pThread->join();
  110. }
  111. __flush();
  112. }
  113. catch (const std::exception&)
  114. {
  115. }
  116. }
  117. /****************************************************************
  118. **【函数名称】 start
  119. **【函数功能】 开始显示日志
  120. **【参数】
  121. **【返回值】
  122. *****************************************************************/
  123. void CLoggerEntity::start( void )
  124. {
  125. m_bIsLogger = TRUE;
  126. }
  127. /****************************************************************
  128. **【函数名称】 stop
  129. **【函数功能】 停止显示日志
  130. **【参数】
  131. **【返回值】
  132. *****************************************************************/
  133. void CLoggerEntity::stop( void )
  134. {
  135. m_bIsLogger = FALSE;
  136. }
  137. /****************************************************************
  138. **【函数名称】 log
  139. **【函数功能】 添加一条新日志
  140. **【参数】 nClass:日志类型
  141. nLevel:日志级别
  142. format:日志信息
  143. **【返回值】
  144. *****************************************************************/
  145. void CLoggerEntity::log(LOG_CLASS nClass, LOG_LEVEL nLevel, char* format, ...)
  146. {
  147. // 检查过滤标志
  148. if (!m_bStopLog && (m_nFilterClass & nClass) == nClass && (m_nFilterLevel & nLevel) == nLevel && nLevel < 5)
  149. {
  150. // 解析日志信息参数
  151. char szMsgBuffer[LOG_BUFFER_LENGTH];
  152. memset(szMsgBuffer, 0, sizeof(szMsgBuffer));
  153. va_list ap;
  154. va_start(ap, format);
  155. //vsprintf_s(szMsgBuffer, sizeof(szMsgBuffer), format, ap);
  156. vsnprintf(szMsgBuffer, sizeof(szMsgBuffer), format, ap);
  157. va_end(ap);
  158. __pushLog(nClass, nLevel, szMsgBuffer);
  159. }
  160. }
  161. /****************************************************************
  162. **【函数名称】 filterShow
  163. **【函数功能】 设置日志内容过滤方式
  164. **【参数】 nClass:日志类型
  165. nLevel:日志级别
  166. **【返回值】
  167. *****************************************************************/
  168. void CLoggerEntity::filterShow( LOG_CLASS nClass /*= LOG_CLASS_GENERAL*/, LOG_LEVEL nLevel /*= LOG_LEVEL_NORMAL */ )
  169. {
  170. m_nFilterClass = nClass; // 日志类型过滤
  171. m_nFilterLevel = nLevel; // 日志级别过滤
  172. }
  173. /****************************************************************
  174. **【函数名称】 __frameControl
  175. **【函数功能】 日志界面控制
  176. **【参数】
  177. **【返回值】
  178. *****************************************************************/
  179. void CLoggerEntity::__frameControl()
  180. {
  181. CRect mRect;
  182. m_pListCtrl->GetClientRect(&mRect);
  183. int length = mRect.right - mRect.left - 240;
  184. //加载日志图标信息
  185. CImageList imgList;
  186. imgList.Create(16, 16, ILC_MASK|ILC_COLOR16, 3, 1);
  187. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
  188. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_WARNING));
  189. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_ERROR));
  190. imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
  191. m_pListCtrl->SetImageList(&imgList, LVSIL_SMALL);
  192. imgList.Detach();
  193. //加载日志列表
  194. //m_pListCtrl->SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
  195. m_pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP | LVS_EX_SUBITEMIMAGES);
  196. m_pListCtrl->InsertColumn(0, (LPCTSTR)"时间", LVCFMT_LEFT, 140, -1);
  197. m_pListCtrl->InsertColumn(1, (LPCTSTR)"类型", LVCFMT_LEFT, 50, -1);
  198. m_pListCtrl->InsertColumn(2, (LPCTSTR)"分类", LVCFMT_LEFT, 50, -1);
  199. m_pListCtrl->InsertColumn(3, (LPCTSTR)"信息", LVCFMT_LEFT, length, -1);
  200. m_pListCtrl->SetItemCount(m_pListCtrlCount); // 设置总行数
  201. }
  202. /****************************************************************
  203. **【函数名称】 启动控制台窗口
  204. **【函数功能】 __initConsoleWindow
  205. **【参数】
  206. **【返回值】
  207. *****************************************************************/
  208. void CLoggerEntity::__initConsoleWindow( void )
  209. {
  210. if(!AllocConsole())
  211. return;
  212. int nCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
  213. if(nCrt == -1)
  214. return;
  215. FILE* fp = _fdopen(nCrt, "w");
  216. if(fp == NULL)
  217. return;
  218. *stdout = *fp;
  219. setvbuf(stdout, NULL, _IONBF, 0);
  220. }
  221. /****************************************************************
  222. **【函数名称】 创建日志文件
  223. **【函数功能】 __openLoggerFile
  224. **【参数】 lpFile
  225. **【返回值】
  226. *****************************************************************/
  227. FILE* CLoggerEntity::__openLoggerFile( void )
  228. {
  229. static int nCount = 1;
  230. FILE* pFile = NULL;
  231. // 获取当前日期
  232. CTime time = CTime::GetCurrentTime();
  233. // 创建日志总目录
  234. if (_access(m_strFileDircet, 0) == -1) {
  235. //CreateDirectoryA(m_strFileDircet, NULL);
  236. boost::filesystem::create_directories(m_strFileDircet.GetBuffer(0));
  237. m_strFileDircet.ReleaseBuffer();
  238. }
  239. // 创建日期目录
  240. CString strPath = _T("");
  241. strPath.Format(_T("%s\\%d-%d-%d"), m_strFileDircet, time.GetYear(), time.GetMonth(), time.GetDay());
  242. // 防止日期文件夹存在时,日志文件索引不会从1开始
  243. static CString lastPath = strPath; // 初始化目录日期
  244. if (lastPath != strPath)
  245. {
  246. nCount = 1;
  247. lastPath = strPath;
  248. }
  249. if(_access(strPath, 0) == -1)
  250. {
  251. nCount = 1;
  252. CreateDirectoryA(strPath, NULL);
  253. }
  254. // 如果文件存在且大于指定大小,生成新的文件名
  255. CString strFileName = _T("");
  256. struct stat st;
  257. do
  258. {
  259. memset(&st, 0, sizeof(st));
  260. strFileName.Format(_T("%s\\%s_%d.txt"), strPath, m_strLoggerName, nCount);
  261. if(stat(strFileName, &st) == 0)
  262. {
  263. if(st.st_size > FILE_MAX_SIZE) nCount++;
  264. }
  265. }
  266. while(st.st_size > FILE_MAX_SIZE);
  267. // 打开文件
  268. fopen_s(&pFile, strFileName, "a+");
  269. return pFile;
  270. }
  271. /****************************************************************
  272. **【函数名称】 __pushLog
  273. **【函数功能】 将日志压入链表
  274. **【参数】
  275. **【返回值】
  276. *****************************************************************/
  277. void CLoggerEntity::__pushLog( LOG_CLASS nClass, LOG_LEVEL nLevel, LPCTSTR lpMessage )
  278. {
  279. // 获取当前时间
  280. CTime t1 = CTime::GetCurrentTime();
  281. CString strTime = t1.Format("%Y-%m-%d %H:%M:%S");
  282. if (m_logBufferSize.load() <= LOG_BUFFER_SIZE && !m_bStopLog.load())
  283. {
  284. PLOG_ITEM pItem = new(std::nothrow)LOG_ITEM(nClass, nLevel, strTime, lpMessage);
  285. if (pItem != NULL)
  286. {
  287. std::unique_lock<std::mutex>lock(m_mut);
  288. m_ItemList.emplace_back(pItem);
  289. m_logBufferSize.store(m_ItemList.size());
  290. m_cond.notify_one(); // 条件变量通知
  291. }
  292. }
  293. }
  294. /****************************************************************
  295. **【函数名称】 __logShow
  296. **【函数功能】 显示日志
  297. **【参数】
  298. **【返回值】
  299. *****************************************************************/
  300. void CLoggerEntity::__saveLog( PLOG_ITEM pItem, FILE* pFile )
  301. {
  302. LOG_CLASS Class = pItem->Class;
  303. LOG_LEVEL Level = pItem->Level;
  304. CString LogContent;
  305. LogContent.Format(_T("%s %s %s %s\r\n"), pItem->Date, m_arLevel[Level], m_arClass[Class], pItem->Content);
  306. // 写日志文件
  307. //fwrite(LogContent, LogContent.GetLength(), 1, pFile);
  308. fwrite(LogContent.GetBuffer(0), LogContent.GetLength(), 1, pFile);
  309. if(!m_bIsLogger || m_bStopLog.load())
  310. return;
  311. if (Level > LOG_LEVEL_NORMAL)
  312. return;
  313. // UI展现
  314. if(m_pListCtrl == NULL)
  315. {
  316. cout << LogContent;
  317. }
  318. else
  319. {
  320. // 日志显示行数控制(500)
  321. if (m_pListCtrl->GetItemCount() >= m_pListCtrlCount)
  322. {
  323. m_pListCtrl->DeleteAllItems();
  324. }
  325. // 定义系统日志显示条数的上限为499条
  326. m_pListCtrl->InsertItem(0, pItem->Date, Level);
  327. //m_pListCtrl->InsertItem(0, pItem->Date);
  328. m_pListCtrl->SetItemText(0, 1, m_arLevel[Level]);
  329. m_pListCtrl->SetItemText(0, 2, m_arClass[Class]);
  330. m_pListCtrl->SetItemText(0, 3, pItem->Content);
  331. }
  332. }
  333. /****************************************************************
  334. **【函数名称】 记录日志线程函数
  335. **【函数功能】 __logThreadFunc
  336. **【参数】 pParam:线程参数
  337. **【返回值】
  338. *****************************************************************/
  339. void CLoggerEntity::logThread()
  340. {
  341. PLOG_ITEM pItem = NULL;
  342. while (!m_bStopLog.load()) {
  343. FILE *pFile = __openLoggerFile();
  344. if (pFile) {
  345. while (!m_bStopLog.load()) {
  346. std::unique_lock<std::mutex> lock(m_mut);
  347. if (!m_ItemList.empty()&& !m_bStopLog.load()) {
  348. pItem = m_ItemList.front();
  349. m_ItemList.pop_front();
  350. }
  351. else {
  352. break;
  353. }
  354. lock.unlock();
  355. if (pItem) {
  356. __saveLog(pItem, pFile);
  357. delete pItem;
  358. pItem = NULL;
  359. }
  360. }
  361. // 关闭文件
  362. fclose(pFile);
  363. pFile = NULL;
  364. }
  365. if (m_bStopLog.load()) {
  366. break;
  367. }
  368. else {
  369. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  370. }
  371. }
  372. //while (!m_bStopLog.load()) {
  373. // std::unique_lock<std::mutex> lock(m_mut);
  374. // m_cond.wait(lock);
  375. // lock.unlock();
  376. // if (m_bStopLog.load()) break;
  377. // FILE *pFile = __openLoggerFile();
  378. // if (pFile) {
  379. // for (; !m_bStopLog.load() && m_logBufferSize > 0;) {
  380. // std::unique_lock<std::mutex> lock1(m_mut);
  381. // if (!m_ItemList.empty()) {
  382. // pItem = m_ItemList.front();
  383. // m_ItemList.pop_front();
  384. // }
  385. // m_logBufferSize.store(m_ItemList.size());
  386. // lock1.unlock();
  387. // if (pItem) {
  388. // __saveLog(pItem, pFile);
  389. // delete pItem;
  390. // pItem = NULL;
  391. // }
  392. // }
  393. // // 关闭文件
  394. // fclose(pFile);
  395. // pFile = NULL;
  396. // }
  397. //}
  398. std::cout << "线程结束" << std::endl;
  399. }
  400. /****************************************************************
  401. **【函数名称】 __flush
  402. **【函数功能】 保存残留的LOGITEM
  403. **【参数】
  404. **【返回值】
  405. *****************************************************************/
  406. void CLoggerEntity::__flush(void)
  407. {
  408. if (m_ItemList.empty())
  409. return;
  410. FILE *pFile = __openLoggerFile();
  411. if (pFile == NULL)
  412. return;
  413. std::unique_lock<std::mutex> lock(m_mut);
  414. for (auto pItem : m_ItemList) {
  415. if (pItem != NULL) {
  416. __saveLog(pItem, pFile);
  417. delete pItem;
  418. pItem = NULL;
  419. }
  420. }
  421. m_ItemList.clear();
  422. fclose(pFile);
  423. pFile = NULL;
  424. }