#include "StdAfx.h" #include "TraceService.h" // #include "EventService.h" #include "../Spdlog/spdlog/sinks/base_sink.h" #include "../Spdlog/spdlog/sinks/msvc_sink.h" #include "../Spdlog/spdlog/sinks/stdout_color_sinks.h" #include "../Spdlog/spdlog/sinks/daily_file_sink.h" #include "../Spdlog/spdlog/sinks/basic_file_sink.h" ////////////////////////////////////////////////////////////////////////// //颜色定义 #define COLOR_TIME RGB(0,0,0) #define COLOR_NORMAL RGB(125,125,125) #define COLOR_WARN RGB(255,128,0) #define COLOR_EXCEPTION RGB(200,0,0) #define COLOR_DEBUG RGB(0,128,128) #define EVENT_LEVEL_COUNT 5 #define IDM_MENU0 100 #define IDM_MENU1 110 #define IDM_MENU2 120 #define IDM_MENU3 130 #define IDM_MENU4 140 #define IDM_MENU5 150 ////////////////////////////////////////////////////////////////////////// //追踪服务 ////////////////////////////////////////////////////////////////////////// Logger::~Logger() { }; //Spdlog void Logger::ShutDown() { spdlog::shutdown(); }; Logger& Logger::GetInstance() { static Logger _log; return _log; } std::shared_ptr Logger::GetTableLogger(int tableId) { if (tablelogger_.count(tableId)) { return tablelogger_.at(tableId); } //创建新的logger auto new_loger = spdlog::basic_logger_mt(fmt::format("{}", tableId), fmt::format("{}table_{}.log", logfile_dir_, tableId)); tablelogger_[tableId] = new_loger; return new_loger; } void Logger::DeleteTableLogger(int tableId) { if (tablelogger_.count(tableId)) { spdlog::drop(fmt::format("{}", tableId)); tablelogger_.erase(tableId); } } ; bool Logger::InitDefaultLog(std::string logger_name, std::string file_name, spdlog::level::level_enum log_level /*= spdlog::level::trace*/) { [](const char* dir, size_t len = 0) -> bool { assert(dir != NULL); if (len < 1 || len > 1024) return false; char* head, * p; char tmpDir[1024] = { 0 }; // strcpy_s(tmpDir, 1024, dir); //拷贝1024字节发现,len之后的字符全部变为-2 strcpy_s(tmpDir, len + 1, dir); head = tmpDir; if (*head == '\\' || *head == '/') ++head; p = head; if (*(tmpDir + len - 1) != '\\' && *(tmpDir + len - 1) != '/') *(tmpDir + len) = '\\'; while (*p) { if (*p == '\\' || *p == '/') { *p = '\0'; if (_access(head, 0)) // 头文件io.h { if (_mkdir(head)) { #ifdef _DEBUG fprintf(stderr, "Failed to create directory %s\n", head); return false; #endif } } *p = '\\'; } ++p; } return true; }("logs"); spdlog::set_level(spdlog::level::trace); //SPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23); //SPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23); //设置为异步日志 // spdlog::set_async_mode(32768); // 必须为 2 的幂 //spdlog::pattern_formatter formatter("%g", spdlog::pattern_time_type::local, ""); //创建一个对应多个sink的_logger_,每一个sink都有独有的格式和日志级别 std::vector> logger_sinks; //#ifdef _CONSOLE #ifdef _DEBUG auto console_sink = std::make_shared(); console_sink->set_level(log_level); console_sink->set_pattern("[%m-%d %H:%M:%S.%e][%^%L%$] [%t:%@] %v"); logger_sinks.push_back(console_sink); #endif // Create a daily logger - a new file is created every day on 2:30am. logfile_dir_ = fmt::format("logs/{}/", CT2A(AfxGetAppName())); auto dailyfile_sink = std::make_shared(logfile_dir_ + file_name, 23, 59, true); dailyfile_sink->set_level(log_level); //格式说明参照https://github.com/gabime/spdlog/wiki/3.-Custom-formatting dailyfile_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%t:%@] %v"); logger_sinks.push_back(dailyfile_sink); #ifdef _WIN32 //使用OutputDebugStringA窗口输出日志 auto vs_sink = std::make_shared(); vs_sink->set_level(log_level); vs_sink->set_pattern("[%m-%d %H:%M:%S.%e] [%^%l%$] [%t:%@] %v"); logger_sinks.push_back(vs_sink); #endif logger_ = std::make_shared(logger_name, begin(logger_sinks), end(logger_sinks)); // register it if you need to access it globally spdlog::register_logger(logger_); // 设置日志记录级别 #ifdef _DEBUG logger_->set_level(log_level); #else logger_->set_level(spdlog::level::err); #endif //设置当出发 err 或更严重的错误时立刻刷新日志到 disk logger_->flush_on(spdlog::level::err); //对所有已注册的loggers定期1秒调用flush() spdlog::flush_every(std::chrono::seconds(1)); //替换任何其它logger为默认logger spdlog::set_default_logger(logger_); logger_->info("spdlog init success\n"); //SPDLOG_LOGGER_TRACE(logger_, "test"); return true; }; static ITraceService* g_pITraceService = NULL; //函数定义 ////////////////////////////////////////////////////////////////////////// //构造函数 CTraceService::CTraceService() { } //服务配置 ////////////////////////////////////////////////////////////////////////// //设置服务 bool CTraceService::SetTraceService(IUnknownEx* pIUnknownEx) { g_pITraceService = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITraceService); return NULL != g_pITraceService; } //获取服务 VOID* CTraceService::GetTraceService(const IID& Guid, DWORD dwQueryVer) { ASSERT(g_pITraceService); if (g_pITraceService) return NULL; return (VOID*)g_pITraceService->QueryInterface(Guid, dwQueryVer); return NULL; } //获取服务 VOID* CTraceService::GetTraceServiceManager(const IID& Guid, DWORD dwQueryVer) { return NULL; } //状态管理 ////////////////////////////////////////////////////////////////////////// //追踪状态 bool CTraceService::IsEnableTrace(enTraceLevel TraceLevel) { return false; } //追踪控制 bool CTraceService::EnableTrace(enTraceLevel TraceLevel, bool bEnableTrace) { return false; } //功能函数 ////////////////////////////////////////////////////////////////////////// //追踪信息 bool CTraceService::TraceString(LPCTSTR pszString, enTraceLevel TraceLevel) { if (TraceLevel == TraceLevel_Debug) return false; if (g_pITraceService) return g_pITraceService->TraceString(pszString, TraceLevel); return false; } ////////////////////////////////////////////////////////////////////////// //追踪服务 ////////////////////////////////////////////////////////////////////////// BEGIN_MESSAGE_MAP(CTraceServiceControl, CRichEditCtrl) ON_WM_RBUTTONDOWN() ON_COMMAND(IDM_MENU0, OnCopyString) ON_COMMAND(IDM_MENU1, OnSelectAll) ON_COMMAND(IDM_MENU2, OnDeleteString) ON_COMMAND(IDM_MENU3, OnClearAll) ON_COMMAND(IDM_MENU4, OnSaveString) END_MESSAGE_MAP() //函数定义 ////////////////////////////////////////////////////////////////////////// //构造函数 CTraceServiceControl::CTraceServiceControl() { CTraceService::SetTraceService((IUnknownEx*)QueryInterface(IID_IUnknownEx, VER_IUnknownEx)); } //析构函数 CTraceServiceControl::~CTraceServiceControl() { CTraceService::SetTraceService(NULL); } //基础接口 ////////////////////////////////////////////////////////////////////////// //接口查询 VOID* CTraceServiceControl::QueryInterface(const IID& Guid, DWORD dwQueryVer) { QUERYINTERFACE(ITraceService, Guid, dwQueryVer); QUERYINTERFACE_IUNKNOWNEX(ITraceService, Guid, dwQueryVer); return NULL; } //信息接口 ////////////////////////////////////////////////////////////////////////// //追踪信息 bool CTraceServiceControl::TraceString(LPCTSTR pszString, enTraceLevel TraceLevel) { //效验参数 ITraceService* pITraceService = (ITraceService*)(QueryInterface(IID_ITraceService, VER_ITraceService)); ASSERT(pITraceService != NULL); if (pITraceService == NULL) return false; //变量定义 CHARFORMAT2 CharFormat; ZeroMemory(&CharFormat, sizeof(CharFormat)); //构造数据 CharFormat.cbSize = sizeof(CharFormat); CharFormat.dwMask = CFM_COLOR | CFM_BACKCOLOR; CTraceServiceControl* pRichEditTrace = static_cast(pITraceService); if (pRichEditTrace == NULL) return false; CharFormat.crTextColor = RGB(0, 0, 0); CharFormat.crBackColor = RGB(255, 255, 255); lstrcpyn(CharFormat.szFaceName, TEXT("宋体"), sizeof(CharFormat.szFaceName)); //获取时间 SYSTEMTIME SystemTime; TCHAR szTimeBuffer[4098] = { 0 }; ZeroMemory(szTimeBuffer, sizeof(TCHAR) * 4096); GetLocalTime(&SystemTime); _snwprintf(szTimeBuffer, sizeof(szTimeBuffer), TEXT("【 %04d-%02d-%02d %02d:%02d:%02d 】"), SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); // InsertString(szTimeBuffer, CharFormat); //长度判断 int iLen = wcslen(pszString); if (iLen > 3800) { _sntprintf(szTimeBuffer, sizeof(szTimeBuffer), TEXT("%s%s\n"), szTimeBuffer, _T("输出信息超长,信息请小于4K。")); } else { _sntprintf(szTimeBuffer, sizeof(szTimeBuffer), TEXT("%s%s\n"), szTimeBuffer, pszString); } CharFormat.crTextColor = pRichEditTrace->GetTraceColor(TraceLevel); return InsertString(szTimeBuffer, CharFormat); } //重载函数 ////////////////////////////////////////////////////////////////////////// //绑定函数 VOID CTraceServiceControl::PreSubclassWindow() { __super::PreSubclassWindow(); CTraceService::SetTraceService((IUnknownEx*)QueryInterface(IID_IUnknownEx, VER_IUnknownEx)); } //功能函数 ////////////////////////////////////////////////////////////////////////// //加载消息 bool CTraceServiceControl::LoadMessage(LPCTSTR pszFileName) { if (static_cast(g_pITraceService) == NULL) return false; return static_cast(g_pITraceService)->LoadMessage(pszFileName); } //保存信息 bool CTraceServiceControl::SaveMessage(LPCTSTR pszFileName) { if (static_cast(g_pITraceService) == NULL) return false; return static_cast(g_pITraceService)->SaveMessage(pszFileName); } //设置参数 bool CTraceServiceControl::SetParameter(LONG lMaxLineCount, LONG lReserveLineCount) { m_lMaxLineCount = lMaxLineCount; //最大行数 m_lReserveLineCount = lReserveLineCount; //保留行数 return true; } //辅助函数 ////////////////////////////////////////////////////////////////////////// //配置服务 VOID CTraceServiceControl::InitializeService() { } //获取颜色 COLORREF CTraceServiceControl::GetTraceColor(enTraceLevel TraceLevel) { switch (TraceLevel) { case TraceLevel_Info: return RGB(133, 124, 129); break; case TraceLevel_Normal: return RGB(133, 124, 129); break; case TraceLevel_Warning: return RGB(255, 0, 0); break; case TraceLevel_Exception: return RGB(255, 0, 0); break; case TraceLevel_Debug: return RGB(19, 127, 140); break; } return RGB(0, 0, 0); } //字符判断 bool EfficacyUrlChar(TCHAR chChar) { //特殊字符 if (chChar == TEXT('.')) return true; if (chChar == TEXT('=')) return true; if (chChar == TEXT('+')) return true; if (chChar == TEXT('?')) return true; if (chChar == TEXT('#')) return true; if (chChar == TEXT('%')) return true; if (chChar == TEXT('/')) return true; if (chChar == TEXT(':')) return true; if (chChar == TEXT('&')) return true; //字符范围 if ((chChar >= TEXT('a')) && (chChar <= TEXT('z'))) return true; if ((chChar >= TEXT('A')) && (chChar <= TEXT('Z'))) return true; if ((chChar >= TEXT('0')) && (chChar <= TEXT('9'))) return true; return false; } //地址判断 bool EfficacyUrlString(LPCTSTR pszUrl) { for (WORD i = 0; i < wcslen(pszUrl); i++) { if (!EfficacyUrlChar(pszUrl[i])) return false; } return true; } //插入字串 bool CTraceServiceControl::InsertString(LPCTSTR pszString, CHARFORMAT2& CharFormat) { if (GetTextLength() >= 1024 * 512) OnClearAll(); //插入消息 //变量定义 bool bResumeSelect; CHARRANGE CharRange; //保存状态 SetSel(-1L, -1L); GetSel(CharRange.cpMin, CharRange.cpMax); bResumeSelect = (CharRange.cpMax != CharRange.cpMin); //搜索变量 LPCTSTR pszHttp = TEXT("http://"); const INT nHttpLength = lstrlen(pszHttp); const INT nStringLength = lstrlen(pszString); //索引定义 INT nStringStart = 0; INT nStringPause = 0; //字符解释 for (INT i = 0; i < nStringLength; i++) { //变量定义 INT nUrlPause = i; //地址判断 if (((i + nHttpLength) < nStringLength) && (memcmp(&pszString[i], pszHttp, nHttpLength * sizeof(TCHAR)) == 0)) { //设置索引 nUrlPause = i + nHttpLength; //地址搜索 while (nUrlPause < nStringLength) { //字符判断 if (EfficacyUrlChar(pszString[nUrlPause]) == true) { nUrlPause++; continue; } break; } } //终止字符 if (nUrlPause <= (i + nHttpLength)) nStringPause = (i + 1); //插入字符 if ((i == (nStringLength - 1)) || (nUrlPause > (i + nHttpLength))) { //普通字符 if (nStringPause > nStringStart) { //获取缓冲 CString strNormalString; LPTSTR pszNormalString = strNormalString.GetBuffer(nStringPause - nStringStart + 1); //拷贝字符 pszNormalString[nStringPause - nStringStart] = 0; CopyMemory(pszNormalString, &pszString[nStringStart], (nStringPause - nStringStart) * sizeof(TCHAR)); //释放缓冲 strNormalString.ReleaseBuffer(); //插入消息 SetSel(-1L, -1L); SetWordCharFormat(CharFormat); ReplaceSel((LPCTSTR)strNormalString); } //连接地址 if (nUrlPause > (i + nHttpLength)) { //获取缓冲 CString strUrlString; LPTSTR pszUrlString = strUrlString.GetBuffer((nUrlPause - i) + 1); //拷贝字符 pszUrlString[nUrlPause - i] = 0; CopyMemory(pszUrlString, &pszString[i], (nUrlPause - i) * sizeof(TCHAR)); //释放缓冲 strUrlString.ReleaseBuffer(); //构造格式 CHARFORMAT2 CharFormatHyper; CharFormatHyper = CharFormat; //效验地址 if (EfficacyUrlString(strUrlString) == true) { CharFormatHyper.dwMask |= CFM_LINK; CharFormatHyper.dwEffects |= CFE_LINK; } //插入消息 SetSel(-1L, -1L); SetWordCharFormat(CharFormatHyper); ReplaceSel((LPCTSTR)strUrlString); } //设置索引 nStringStart = __max(i, nUrlPause); } //设置索引 i += (nUrlPause - i); } //状态设置 if (bResumeSelect == true) SetSel(CharRange); else PostMessage(WM_VSCROLL, SB_BOTTOM, 0); return true; } //回调函数 ////////////////////////////////////////////////////////////////////////// //加载回调 DWORD CALLBACK CTraceServiceControl::LoadCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb) { return 0; } //保存回调 DWORD CALLBACK CTraceServiceControl::SaveCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb) { return 0; } //菜单命令 ////////////////////////////////////////////////////////////////////////// //删除信息 VOID CTraceServiceControl::OnClearAll() { SetWindowText(NULL); } //全部选择 VOID CTraceServiceControl::OnSelectAll() { __super::SetSel(0, __super::GetTextLength()); } //拷贝字符 VOID CTraceServiceControl::OnCopyString() { __super::Copy(); } //保存信息 VOID CTraceServiceControl::OnSaveString() { CFileDialog dlg(FALSE, TEXT("*.txt"), NULL, 4 | 2, TEXT("信息|*.txt||")); if (dlg.DoModal() == IDOK) { CString m_filename = dlg.GetPathName(); CString strInput; GetWindowText(strInput); CFile file(m_filename, CFile::modeCreate | CFile::modeWrite); file.Write(strInput, strInput.GetLength()); file.Close(); } } //删除字符 VOID CTraceServiceControl::OnDeleteString() { ReplaceSel(NULL, true); } //消息映射 ////////////////////////////////////////////////////////////////////////// //建立消息 INT CTraceServiceControl::OnCreate(LPCREATESTRUCT lpCreateStruct) { return __super::OnCreate(lpCreateStruct); } //右键消息 VOID CTraceServiceControl::OnRButtonDown(UINT nFlags, CPoint point) { CMenu menu; ClientToScreen(&point); menu.CreatePopupMenu(); CHARRANGE sl; GetSel(sl); menu.AppendMenu(MF_STRING | (sl.cpMax != sl.cpMin) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU0, TEXT("复制(&C)\tCtrl+C")); menu.AppendMenu(MF_STRING | (GetTextLength() > 0 && sl.cpMax - sl.cpMin < GetTextLength()) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU1, TEXT("全选(&A)\tCtrl+A")); menu.AppendMenu(MF_STRING | (false) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU2, TEXT("删除(&D)")); menu.AppendMenu(MF_STRING | (GetTextLength() > 0) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU3, TEXT("清除信息")); menu.AppendMenu(MF_SEPARATOR, 0); menu.AppendMenu(MF_STRING | (GetTextLength() > 0) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU4, TEXT("保存信息...")); TrackPopupMenu(menu.m_hMenu, nFlags, point.x, point.y, 0, m_hWnd, NULL); } //追踪消息 LRESULT CTraceServiceControl::OnTraceServiceMessage(WPARAM wParam, LPARAM lParam) { return 0; }