| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- #include "StdAfx.h"
- #include "LoggerEntity.h"
- #include <io.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <boost/filesystem.hpp>
- SINGLETON_IMPLEMENT(CLoggerEntity)
- ILogger& ILogger::getInstance(void)
- {
- return CLoggerEntity::GetInstance();
-
- }
- 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)
- {
- m_arClass[0] = "PDU";
- m_arClass[1] = "DEV";
- m_arClass[2] = "业务";
- m_arClass[3] = "基本";
- m_arLevel[0] = "";
- m_arLevel[1] = "警告";
- m_arLevel[2] = "错误";
- m_arLevel[3] = "信息";
- m_arLevel[4] = "详细";
- }
- CLoggerEntity::~CLoggerEntity(void)
- {
- //close();
- }
- /****************************************************************
- **【函数名称】 init
- **【函数功能】 日志初始化
- **【参数】 pList:日志显示的List控件
- nDevType:使用日志的系统
- lpFilePath:日志记录路径
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::init(CListCtrl* pList, LOG_DEV nDevType, LPCTSTR lpFilePath /*= NULL */ )
- {
- // 列表控件的初始化
- if((m_pListCtrl = pList) != NULL)
- __frameControl();
- else
- __initConsoleWindow();
- // 保存设备类型
- m_nDevType = nDevType;
- switch(m_nDevType)
- {
- case LOG_DEV_CTI:
- m_strLoggerName = _T("log_cti");
- break;
- case LOG_DEV_IVR:
- m_strLoggerName = _T("log_ivr");
- break;
- case LOG_DEV_ACD:
- m_strLoggerName = _T("log_acd");
- break;
- case LOG_DEV_VS:
- m_strLoggerName = _T("log_vs");
- break;
- case LOG_DEV_FS:
- m_strLoggerName = _T("log_fs");
- break;
- case LOG_DEV_AC:
- m_strLoggerName = _T("log_ac");
- break;
- case LOG_DEV_SC:
- m_strLoggerName = _T("log_sc");
- break;
- case LOG_DEV_GUARD:
- m_strLoggerName = _T("log_guard");
- break;
- case LOG_DEV_SERVER:
- m_strLoggerName = _T("log_http");
- break;
- default:
- m_strLoggerName = _T("log_unknow");
- break;
- }
- if (lpFilePath == NULL)
- {
- // 默认路径
- m_strFileDircet = _T("d:\\middleware_log");
- }
- else
- {
- // 指定路径
- m_strFileDircet = lpFilePath;
- }
- m_bStopLog = FALSE;
- // 初始化记录日志线程
- if (m_pThread == nullptr)
- m_pThread = std::make_shared<std::thread>(std::bind(&CLoggerEntity::logThread, this));
- }
- /****************************************************************
- **【函数名称】 close
- **【函数功能】 日志关闭
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::close(void)
- {
- m_bIsLogger = FALSE;
- m_bStopLog.store(true);
- m_cond.notify_one(); // 条件变量通知
- if (m_pThread&& m_pThread->joinable()) {
- m_pThread->join();
- }
- __flush();
- }
- /****************************************************************
- **【函数名称】 start
- **【函数功能】 开始显示日志
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::start( void )
- {
- m_bIsLogger = TRUE;
- }
- /****************************************************************
- **【函数名称】 stop
- **【函数功能】 停止显示日志
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::stop( void )
- {
- std::unique_lock<std::mutex> lock(m_mut);
- m_bIsLogger = FALSE;
- lock.unlock();
- }
- /****************************************************************
- **【函数名称】 log
- **【函数功能】 添加一条新日志
- **【参数】 nClass:日志类型
- nLevel:日志级别
- format:日志信息
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::log(LOG_CLASS nClass, LOG_LEVEL nLevel, char* format, ...)
- {
- try {
- if (!m_bIsLogger) return;
- // 检查过滤标志
- if (!m_bStopLog && (m_nFilterClass & nClass) == nClass && (m_nFilterLevel & nLevel) == nLevel && nLevel < 5) {
- // 解析日志信息参数
- char szMsgBuffer[LOG_BUFFER_LENGTH];
- memset(szMsgBuffer, 0, sizeof(szMsgBuffer));
- va_list ap;
- va_start(ap, format);
- vsnprintf(szMsgBuffer, sizeof(szMsgBuffer), format, ap);
- va_end(ap);
- __pushLog(nClass, nLevel, szMsgBuffer);
- }
- }
- catch (CException* e) {
- std::ofstream file("logger_except.txt", std::ios::app);
- if (file) {
- file << "CException 异常:";
- TCHAR szErr[1024];
- if (e->GetErrorMessage(szErr, 1024))
- file << szErr << std::endl;
- file.close();
- }
- e->Delete();
- }
- }
- /****************************************************************
- **【函数名称】 filterShow
- **【函数功能】 设置日志内容过滤方式
- **【参数】 nClass:日志类型
- nLevel:日志级别
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::filterShow( LOG_CLASS nClass /*= LOG_CLASS_GENERAL*/, LOG_LEVEL nLevel /*= LOG_LEVEL_NORMAL */ )
- {
- m_nFilterClass = nClass; // 日志类型过滤
- m_nFilterLevel = nLevel; // 日志级别过滤
- }
- /****************************************************************
- **【函数名称】 __frameControl
- **【函数功能】 日志界面控制
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::__frameControl()
- {
- CRect mRect;
- m_pListCtrl->GetClientRect(&mRect);
- int length = mRect.right - mRect.left - 240;
- //加载日志图标信息
- CImageList imgList;
- imgList.Create(16, 16, ILC_MASK|ILC_COLOR16, 3, 1);
- imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
- imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_WARNING));
- imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_ERROR));
- imgList.Add(AfxGetApp()->LoadStandardIcon(IDI_INFORMATION));
- m_pListCtrl->SetImageList(&imgList, LVSIL_SMALL);
- imgList.Detach();
-
- //加载日志列表
- m_pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP | LVS_EX_SUBITEMIMAGES);
- m_pListCtrl->InsertColumn(0, (LPCTSTR)"时间", LVCFMT_LEFT, 140, -1);
- m_pListCtrl->InsertColumn(1, (LPCTSTR)"类型", LVCFMT_LEFT, 50, -1);
- m_pListCtrl->InsertColumn(2, (LPCTSTR)"分类", LVCFMT_LEFT, 50, -1);
- m_pListCtrl->InsertColumn(3, (LPCTSTR)"信息", LVCFMT_LEFT, length, -1);
- m_pListCtrl->SetItemCount(m_pListCtrlCount); // 设置总行数
- }
- /****************************************************************
- **【函数名称】 启动控制台窗口
- **【函数功能】 __initConsoleWindow
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::__initConsoleWindow( void )
- {
- if(!AllocConsole())
- return;
- int nCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
- if(nCrt == -1)
- return;
- FILE* fp = _fdopen(nCrt, "w");
- if(fp == NULL)
- return;
- *stdout = *fp;
- setvbuf(stdout, NULL, _IONBF, 0);
- }
- /****************************************************************
- **【函数名称】 创建日志文件
- **【函数功能】 __openLoggerFile
- **【参数】 lpFile
- **【返回值】
- *****************************************************************/
- FILE* CLoggerEntity::__openLoggerFile( void )
- {
- static int nCount = 1;
- FILE* pFile = NULL;
- // 获取当前日期
- CTime time = CTime::GetCurrentTime();
- // 创建日志总目录
- if (_access(m_strFileDircet, 0) == -1) {
- boost::filesystem::create_directories(m_strFileDircet.GetBuffer(0));
- m_strFileDircet.ReleaseBuffer();
- }
- // 创建日期目录
- CString strPath = _T("");
- strPath.Format(_T("%s\\%d-%d-%d"), m_strFileDircet, time.GetYear(), time.GetMonth(), time.GetDay());
- // 防止日期文件夹存在时,日志文件索引不会从1开始
- static CString lastPath = strPath; // 初始化目录日期
- if (lastPath != strPath)
- {
- nCount = 1;
- lastPath = strPath;
- }
- if(_access(strPath, 0) == -1)
- {
- nCount = 1;
- CreateDirectoryA(strPath, NULL);
- }
- // 如果文件存在且大于指定大小,生成新的文件名
- CString strFileName = _T("");
- struct stat st;
- do
- {
- memset(&st, 0, sizeof(st));
- strFileName.Format(_T("%s\\%s_%d.txt"), strPath, m_strLoggerName, nCount);
- if(stat(strFileName, &st) == 0)
- {
- if(st.st_size > FILE_MAX_SIZE) nCount++;
- }
- }
- while(st.st_size > FILE_MAX_SIZE);
- // 打开文件
- fopen_s(&pFile, strFileName, "a+");
- return pFile;
- }
- /****************************************************************
- **【函数名称】 __pushLog
- **【函数功能】 将日志压入链表
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::__pushLog( LOG_CLASS nClass, LOG_LEVEL nLevel, LPCTSTR lpMessage )
- {
- // 获取当前时间
- CTime t1 = CTime::GetCurrentTime();
- CString strTime = t1.Format("%Y-%m-%d %H:%M:%S");
- if (m_logBufferSize.load() <= LOG_BUFFER_SIZE && !m_bStopLog.load()){
- PLOG_ITEM pItem = new(std::nothrow)LOG_ITEM(nClass, nLevel, strTime, lpMessage);
- if (pItem != NULL){
- std::unique_lock<std::mutex>lock(m_mut);
- m_ItemList.emplace_back(pItem);
- m_logBufferSize.store(m_ItemList.size());
- m_cond.notify_one(); // 条件变量通知
- }
- }
- }
- /****************************************************************
- **【函数名称】 __logShow
- **【函数功能】 显示日志
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::__saveLog( PLOG_ITEM pItem, FILE* pFile )
- {
- LOG_CLASS Class = pItem->Class;
- LOG_LEVEL Level = pItem->Level;
- CString LogContent;
- LogContent.Format(_T("%s %s %s %s\r\n"), pItem->Date, m_arLevel[Level], m_arClass[Class], pItem->Content);
- // 写日志文件
- fwrite(LogContent.GetBuffer(0), LogContent.GetLength(), 1, pFile);
-
- if(!m_bIsLogger || m_bStopLog.load())
- return;
-
- if (Level > LOG_LEVEL_NORMAL)
- return;
- // UI展现
- if(m_pListCtrl == NULL)
- {
- cout << LogContent;
- }
- else
- {
- // 日志显示行数控制(500)
- if (m_pListCtrl->GetItemCount() >= m_pListCtrlCount)
- {
- m_pListCtrl->DeleteAllItems();
- }
- // 定义系统日志显示条数的上限为499条
- m_pListCtrl->InsertItem(0, pItem->Date, Level);
- m_pListCtrl->SetItemText(0, 1, m_arLevel[Level]);
- m_pListCtrl->SetItemText(0, 2, m_arClass[Class]);
- m_pListCtrl->SetItemText(0, 3, pItem->Content);
- }
- }
- /****************************************************************
- **【函数名称】 记录日志线程函数
- **【函数功能】 __logThreadFunc
- **【参数】 pParam:线程参数
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::logThread()
- {
- PLOG_ITEM pItem = NULL;
- while (!m_bStopLog.load()) {
- std::unique_lock<std::mutex> lock(m_mut);
- for (; m_ItemList.empty() && !m_bStopLog.load();) {
- m_cond.wait(lock);
- }
- if (m_bStopLog.load()) break;
- lock.unlock();
- FILE *pFile = __openLoggerFile();
- if (pFile) {
- for (; m_logBufferSize > 0 && !m_bStopLog.load();) {
- std::unique_lock<std::mutex> lock1(m_mut);
- if (!m_ItemList.empty()) {
- pItem = m_ItemList.front();
- m_ItemList.pop_front();
- m_logBufferSize.store(m_ItemList.size());
- lock1.unlock();
- if (pItem) {
- __saveLog(pItem, pFile);
- delete pItem;
- pItem = NULL;
- }
- }
- else {
- m_logBufferSize.store(0);
- break;
- }
- }
- // 关闭文件
- fclose(pFile);
- pFile = NULL;
- }
- }
- std::cout << "线程结束" << std::endl;
- }
- /****************************************************************
- **【函数名称】 __flush
- **【函数功能】 保存残留的LOGITEM
- **【参数】
- **【返回值】
- *****************************************************************/
- void CLoggerEntity::__flush(void)
- {
- if (m_ItemList.empty())
- return;
- FILE *pFile = __openLoggerFile();
- if (pFile == NULL)
- return;
- for (auto pItem : m_ItemList) {
- if (pItem != NULL) {
- __saveLog(pItem, pFile);
- delete pItem;
- pItem = NULL;
- }
- }
- m_ItemList.clear();
- fclose(pFile);
- pFile = NULL;
- }
|