|
9 | 9 | #include "ze_logger.h" |
10 | 10 | #include "ze_util.h" |
11 | 11 |
|
| 12 | +#include <cerrno> |
12 | 13 | #include <chrono> |
| 14 | +#include <cstdio> |
13 | 15 | #include <ctime> |
14 | 16 | #include <iomanip> |
15 | 17 | #include <iostream> |
@@ -158,9 +160,10 @@ LogLevel logLevelFromString(const std::string &s) { |
158 | 160 | if (s == "trace") return LogLevel::trace; |
159 | 161 | if (s == "debug") return LogLevel::debug; |
160 | 162 | if (s == "info") return LogLevel::info; |
161 | | - if (s == "warn") return LogLevel::warn; |
162 | | - if (s == "error") return LogLevel::err; |
163 | | - if (s == "critical") return LogLevel::critical; |
| 163 | + if (s == "warn" || s == "warning") return LogLevel::warn; |
| 164 | + if (s == "err" || s == "error") return LogLevel::err; |
| 165 | + if (s == "crit" || s == "critical") return LogLevel::critical; |
| 166 | + if (s == "off") return LogLevel::off; |
164 | 167 | return LogLevel::warn; // default |
165 | 168 | } |
166 | 169 |
|
@@ -205,7 +208,7 @@ void ZeLogger::flush() { |
205 | 208 | // Default pattern tokens: |
206 | 209 | // %Y-%m-%d %H:%M:%S.%e — timestamp with milliseconds |
207 | 210 | // %t — thread id (cached thread_local, STB_LOCAL — safe for dlclose) |
208 | | -// %P — process id (cached at construction) |
| 211 | +// %P — process id |
209 | 212 | // %^%l%$ — level label (with color when tty) |
210 | 213 | // %v — message |
211 | 214 | // |
@@ -516,16 +519,47 @@ std::shared_ptr<ZeLogger> createLogger(const std::string &caller) { |
516 | 519 | logger = std::make_shared<ZeLogger>(/*use_stderr=*/true, level, log_pattern); |
517 | 520 | output_dest = "stderr (console)"; |
518 | 521 | } else { |
519 | | - // Create the log directory only if it does not already exist. |
| 522 | + // Create the full directory path (equivalent to mkdir -p). |
520 | 523 | #ifdef _WIN32 |
521 | | - DWORD attrs = GetFileAttributesA(log_directory.c_str()); |
522 | | - if (attrs == INVALID_FILE_ATTRIBUTES || !(attrs & FILE_ATTRIBUTE_DIRECTORY)) { |
523 | | - _mkdir(log_directory.c_str()); |
| 524 | + // Walk each component and create it if missing. |
| 525 | + for (std::size_t pos = 0; pos <= log_directory.size(); ++pos) { |
| 526 | + if (pos == log_directory.size() || |
| 527 | + log_directory[pos] == '\\' || log_directory[pos] == '/') { |
| 528 | + if (pos == 0) continue; |
| 529 | + std::string partial = log_directory.substr(0, pos); |
| 530 | + DWORD attrs = GetFileAttributesA(partial.c_str()); |
| 531 | + if (attrs == INVALID_FILE_ATTRIBUTES) { |
| 532 | + if (_mkdir(partial.c_str()) != 0 && errno != EEXIST) { |
| 533 | + std::cerr << "ze_logger: Failed to create log directory '" |
| 534 | + << partial << "': " << strerror(errno) << "\n"; |
| 535 | + return std::make_shared<ZeLogger>(); |
| 536 | + } |
| 537 | + } else if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) { |
| 538 | + std::cerr << "ze_logger: Log directory path component '" |
| 539 | + << partial << "' exists but is not a directory\n"; |
| 540 | + return std::make_shared<ZeLogger>(); |
| 541 | + } |
| 542 | + } |
524 | 543 | } |
525 | 544 | #else |
526 | | - struct stat st{}; |
527 | | - if (stat(log_directory.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) { |
528 | | - mkdir(log_directory.c_str(), 0755); |
| 545 | + // Walk each component and create it if missing. |
| 546 | + for (std::size_t pos = 0; pos <= log_directory.size(); ++pos) { |
| 547 | + if (pos == log_directory.size() || log_directory[pos] == '/') { |
| 548 | + if (pos == 0) continue; |
| 549 | + std::string partial = log_directory.substr(0, pos); |
| 550 | + struct stat st{}; |
| 551 | + if (stat(partial.c_str(), &st) != 0) { |
| 552 | + if (mkdir(partial.c_str(), 0755) != 0 && errno != EEXIST) { |
| 553 | + std::cerr << "ze_logger: Failed to create log directory '" |
| 554 | + << partial << "': " << strerror(errno) << "\n"; |
| 555 | + return std::make_shared<ZeLogger>(); |
| 556 | + } |
| 557 | + } else if (!S_ISDIR(st.st_mode)) { |
| 558 | + std::cerr << "ze_logger: Log directory path component '" |
| 559 | + << partial << "' exists but is not a directory\n"; |
| 560 | + return std::make_shared<ZeLogger>(); |
| 561 | + } |
| 562 | + } |
529 | 563 | } |
530 | 564 | #endif |
531 | 565 | logger = std::make_shared<ZeLogger>(full_log_file_path, level, log_pattern); |
|
0 commit comments