组件

LoggerEntity.cpp 10KB

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