Logger.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Logger.cpp - 日志实现
  2. #include "pch.h"
  3. #include "Logger.h"
  4. #include <ctime>
  5. #include <iomanip>
  6. #include <sstream>
  7. namespace commkit {
  8. Logger::Logger() {}
  9. Logger::~Logger() {}
  10. Logger& Logger::Instance() {
  11. static Logger instance;
  12. return instance;
  13. }
  14. void Logger::SetLevel(Level level) {
  15. level_ = level;
  16. }
  17. void Logger::EnableFileOutput(bool enable) {
  18. std::lock_guard<std::mutex> lock(file_mutex_);
  19. file_output_enabled_ = enable;
  20. }
  21. std::wstring Logger::StringToWString(const std::string& str) const {
  22. if (str.empty()) return L"";
  23. int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
  24. if (len <= 0) return L"";
  25. std::wstring wstr(len - 1, L'\0');
  26. MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &wstr[0], len);
  27. return wstr;
  28. }
  29. std::wstring Logger::FormatLine(Level level, const std::string& message) {
  30. // 获取当前本地时间
  31. auto now = std::time(nullptr);
  32. struct tm tm_buf;
  33. localtime_s(&tm_buf, &now);
  34. // 格式化时间戳
  35. std::wostringstream woss;
  36. woss << L"[" << std::put_time(&tm_buf, L"%Y-%m-%d %H:%M:%S") << L"]";
  37. // 级别标记
  38. const wchar_t* level_str = L"?";
  39. switch (level) {
  40. case Level::Debug: level_str = L"DBG"; break;
  41. case Level::Info: level_str = L"INF"; break;
  42. case Level::Warning: level_str = L"WRN"; break;
  43. case Level::Error: level_str = L"ERR"; break;
  44. }
  45. woss << L"[" << level_str << L"] ";
  46. // 消息体
  47. woss << StringToWString(message);
  48. return woss.str();
  49. }
  50. void Logger::WriteToFile(const std::wstring& line) {
  51. // 日志文件路径:%TEMP%\CommModifyKit.log
  52. wchar_t temp_path[MAX_PATH] = {0};
  53. if (GetTempPathW(MAX_PATH, temp_path) == 0) return;
  54. std::wstring file_path = std::wstring(temp_path) + L"CommModifyKit.log";
  55. // 追加模式打开
  56. HANDLE hFile = CreateFileW(file_path.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ,
  57. nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
  58. if (hFile == INVALID_HANDLE_VALUE) return;
  59. // 写入一行 + 换行
  60. std::wstring line_with_eol = line + L"\r\n";
  61. DWORD written = 0;
  62. WriteFile(hFile, line_with_eol.c_str(),
  63. static_cast<DWORD>(line_with_eol.size() * sizeof(wchar_t)),
  64. &written, nullptr);
  65. CloseHandle(hFile);
  66. }
  67. void Logger::Log(Level level, const std::string& message) {
  68. // 级别过滤
  69. if (static_cast<int>(level) < static_cast<int>(level_)) {
  70. return;
  71. }
  72. // 格式化日志行
  73. std::wstring line = FormatLine(level, message);
  74. // 输出到调试器(DebugView 等)
  75. OutputDebugStringW(line.c_str());
  76. OutputDebugStringW(L"\r\n");
  77. // 可选:写入文件
  78. {
  79. std::lock_guard<std::mutex> lock(file_mutex_);
  80. if (file_output_enabled_) {
  81. WriteToFile(line);
  82. }
  83. }
  84. }
  85. } // namespace commkit