CustomLog.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #pragma once
  2. #include <iostream>
  3. #include <fstream>
  4. #include <string>
  5. #include <chrono>
  6. #include <iomanip>
  7. #include <sstream>
  8. #include <mutex>
  9. #ifdef _WIN32
  10. #include <windows.h>
  11. #else
  12. #include <unistd.h>
  13. #include <limits.h>
  14. #include <sys/stat.h>
  15. #endif
  16. enum LogLevel {
  17. LOG_INFO,
  18. LOG_WARNING,
  19. LOG_ERROR
  20. };
  21. class CustomLogger {
  22. public:
  23. static CustomLogger& getInstance() {
  24. static CustomLogger instance;
  25. return instance;
  26. }
  27. bool initialize(const std::string& logDir = "logs") {
  28. std::lock_guard<std::mutex> lock(LogMutex_);
  29. // 创建日志目录
  30. if (!createDirectory(logDir)) {
  31. std::cerr << "Failed to create log directory: " << logDir << std::endl;
  32. return false;
  33. }
  34. // 生成基于时间的日志文件名
  35. auto now = std::chrono::system_clock::now();
  36. auto time_t = std::chrono::system_clock::to_time_t(now);
  37. std::tm tm;
  38. #ifdef _WIN32
  39. localtime_s(&tm, &time_t);
  40. #else
  41. localtime_r(&time_t, &tm);
  42. #endif
  43. std::ostringstream filename;
  44. filename << logDir << "/log_"
  45. << std::setfill('0') << std::setw(4) << (tm.tm_year + 1900)
  46. << std::setw(2) << (tm.tm_mon + 1)
  47. << std::setw(2) << tm.tm_mday << "_"
  48. << std::setw(2) << tm.tm_hour
  49. << std::setw(2) << tm.tm_min
  50. << std::setw(2) << tm.tm_sec << ".log";
  51. logFile_.open(filename.str(), std::ios::out | std::ios::app);
  52. if (!logFile_.is_open()) {
  53. std::cerr << "Failed to open log file: " << filename.str() << std::endl;
  54. return false;
  55. }
  56. //log(LOG_INFO, "Logger initialized successfully");
  57. return true;
  58. }
  59. void log(LogLevel level, const std::string& message) {
  60. std::lock_guard<std::mutex> lock(LogMutex_);
  61. std::cout << message << std::endl;
  62. return;
  63. if (!logFile_.is_open()) return;
  64. auto now = std::chrono::system_clock::now();
  65. auto time_t = std::chrono::system_clock::to_time_t(now);
  66. std::tm tm;
  67. #ifdef _WIN32
  68. localtime_s(&tm, &time_t);
  69. #else
  70. localtime_r(&time_t, &tm);
  71. #endif
  72. const char* levelStr = "";
  73. switch (level) {
  74. case LOG_INFO: levelStr = "INFO"; break;
  75. case LOG_WARNING: levelStr = "WARNING"; break;
  76. case LOG_ERROR: levelStr = "ERROR"; break;
  77. }
  78. logFile_ << "[" << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << "] "
  79. << "[" << levelStr << "] " << message << std::endl;
  80. // 同时输出到控制台
  81. logFile_.flush();
  82. }
  83. void shutdown() {
  84. std::lock_guard<std::mutex> lock(LogMutex_);
  85. if (logFile_.is_open()) {
  86. log(LOG_INFO, "Logger shutdown");
  87. logFile_.close();
  88. }
  89. }
  90. private:
  91. CustomLogger() = default;
  92. ~CustomLogger() { shutdown(); }
  93. CustomLogger(const CustomLogger&) = delete;
  94. CustomLogger& operator=(const CustomLogger&) = delete;
  95. bool createDirectory(const std::string& path) {
  96. #ifdef _WIN32
  97. return CreateDirectoryA(path.c_str(), NULL) != 0 ||
  98. GetLastError() == ERROR_ALREADY_EXISTS;
  99. #else
  100. return mkdir(path.c_str(), 0755) == 0 || errno == EEXIST;
  101. #endif
  102. }
  103. std::ofstream logFile_;
  104. std::mutex LogMutex_;
  105. };
  106. // 宏定义简化日志调用
  107. #define LOG_INFO(msg) CustomLogger::getInstance().log(LOG_INFO, msg)
  108. #define LOG_WARNING(msg) CustomLogger::getInstance().log(LOG_WARNING, msg)
  109. #define LOG_ERROR(msg) CustomLogger::getInstance().log(LOG_ERROR, msg)