28Logger::Logger() =
default;
40 const std::lock_guard<std::mutex> lock(m_mutex);
42 m_minLevel = minLevel;
43 m_logFilePath = logFilePath;
45 if (!logFilePath.empty()) {
47 auto parentPath = logFilePath.parent_path();
48 if (!parentPath.empty() && !std::filesystem::exists(parentPath)) {
50 std::filesystem::create_directories(parentPath, ec);
52 std::cerr <<
"Warning: Could not create log directory: " << ec.message() <<
'\n';
56 m_logFile.open(logFilePath, std::ios::out | std::ios::app);
57 if (m_logFile.is_open()) {
59 m_logFile <<
"\n========== Log Session Started: " << GetTimestamp() <<
" ==========\n";
62 std::cerr <<
"Failed to open log file: " << logFilePath <<
'\n';
67 if (m_consoleOutput) {
68 std::cout <<
"Logger initialized (Level: " << LevelToString(minLevel) <<
")" <<
'\n';
73 const std::lock_guard<std::mutex> lock(m_mutex);
75 if (m_logFile.is_open()) {
76 m_logFile <<
"========== Log Session Ended: " << GetTimestamp() <<
" ==========\n\n";
82 const std::lock_guard<std::mutex> lock(m_mutex);
87 const std::lock_guard<std::mutex> lock(m_mutex);
92 const std::lock_guard<std::mutex> lock(m_mutex);
93 m_consoleOutput = enable;
97 const std::lock_guard<std::mutex> lock(m_mutex);
98 m_fileOutput = enable && m_logFile.is_open();
102 const std::lock_guard<std::mutex> lock(m_mutex);
103 if (m_logFile.is_open()) {
111 const std::lock_guard<std::mutex> lock(m_mutex);
112 return m_logFilePath;
115void Logger::LogMessage(
LogLevel level,
const std::string& message) {
116 const std::lock_guard<std::mutex> lock(m_mutex);
118 const std::string timestamp = GetTimestamp();
119 const std::string levelStr = LevelToString(level);
120 const std::string formattedMessage =
"[" + timestamp +
"] [" + levelStr +
"] " + message;
123 if (m_consoleOutput) {
124 const char* color = LevelToColor(level);
125 const char* reset =
"\033[0m";
127 std::ostream& out = (level >=
LogLevel::Error) ? std::cerr : std::cout;
128 out << color << formattedMessage << reset <<
'\n';
132 if (m_fileOutput && m_logFile.is_open()) {
133 m_logFile << formattedMessage <<
'\n';
142std::string Logger::GetTimestamp()
const {
143 auto now = std::chrono::system_clock::now();
144 auto time = std::chrono::system_clock::to_time_t(now);
145 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
149 localtime_s(&tm_buf, &time);
151 localtime_r(&time, &tm_buf);
154 std::ostringstream oss;
155 oss << std::put_time(&tm_buf,
"%Y-%m-%d %H:%M:%S");
156 oss <<
'.' << std::setfill(
'0') << std::setw(3) << ms.count();
160std::string Logger::LevelToString(
LogLevel level)
const {
177const char* Logger::LevelToColor(
LogLevel level)
const {