#include "native_logger.hpp" #include #include #include #include #include #include #include #include #include namespace netcore { static std::mutex g_mu; static int g_fd = -1; static std::string g_path = "netcore.log"; static LogLevel g_level = LogLevel::kDebug; //LogLevel::kInfo; static const char* level_name(LogLevel lvl) { switch (lvl) { case LogLevel::kError: return "E"; case LogLevel::kWarn: return "W"; case LogLevel::kInfo: return "I"; case LogLevel::kDebug: return "D"; default: return "?"; } } static void ensure_open_locked() { if (g_path.empty()) return; if (g_fd >= 0) return; g_fd = ::open(g_path.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644); } void set_log_file(const std::string& path) { std::lock_guard lk(g_mu); g_path = path; if (g_fd >= 0) { ::close(g_fd); g_fd = -1; } ensure_open_locked(); } void set_log_level(LogLevel level) { std::lock_guard lk(g_mu); g_level = level; } void log(LogLevel level, const std::string& msg) { std::lock_guard lk(g_mu); if (static_cast(level) > static_cast(g_level)) return; if (g_path.empty()) return; ensure_open_locked(); if (g_fd < 0) { // Last resort: stderr (avoid any Python APIs) ::write(STDERR_FILENO, msg.c_str(), msg.size()); ::write(STDERR_FILENO, "\n", 1); return; } // Timestamp: epoch milliseconds (simple and cheap) struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); // long long ms = (long long)ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL; // 1. 将秒数转换为本地时间结构体 struct tm struct tm *tm_info = localtime(&ts.tv_sec); // 2. 准备一个缓冲区来存储时间字符串 char buffer[30]; // 3. 格式化秒的部分 // 格式: 年-月-日 时:分:秒 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_info); // 4. 计算毫秒部分并追加到字符串中 // ts.tv_nsec 是纳秒,除以 1,000,000 得到毫秒 char ms_buffer[8]; snprintf(ms_buffer, sizeof(ms_buffer), ".%03ld", ts.tv_nsec / 1000000); // Build one line to keep writes atomic-ish char head[256]; int n = ::snprintf(head, sizeof(head), "[%s%s] [%s] ", buffer, ms_buffer, level_name(level)); if (n < 0) n = 0; ::write(g_fd, head, (size_t)n); ::write(g_fd, msg.c_str(), msg.size()); ::write(g_fd, "\n", 1); } void log_debug(const std::string& msg) { log(LogLevel::kDebug, msg); } void log_info (const std::string& msg) { log(LogLevel::kInfo, msg); } void log_warn (const std::string& msg) { log(LogLevel::kWarn, msg); } void log_error(const std::string& msg) { log(LogLevel::kError, msg); } } // namespace netcore