#include "export.h" #include "../system/export.h" #include #include #include #include "Core/Base/global_include.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/spdlog.h" #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include "Windows.h" #else std::string handle_fileName(const std::string& utf8_str) { return utf8_str; } #endif #include "../system/export.h" #include "spdlog/async.h" #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/spdlog.h" #include #include #include #include #include #include "spdlog/pattern_formatter.h" namespace fs = std::filesystem; void spdlog_close() { spdlog::shutdown(); } Log_Type::Log_Type(std::vector list) : list(list) { } Log_Type::Log_Type(std::vector> map) : map(map) { } Log_Type::Log_Type(std::vector list, std::vector> map) : list(list), map(map) { } std::string get_current_date_string() { // 获取当前时间 auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); // 使用 std::put_time 格式化时间 std::ostringstream oss; oss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %H:%M:%S"); // 格式化为 "YYYY-MM-DD" return oss.str(); } std::shared_ptr create_rotating_logger(const std::string& key, size_t byte_size, size_t num) { std::string fileName = "@/logs/" + key + ".log"; fileName = Psc::get_abs_path(fileName); fileName = Psc::utf8_2_platform(fileName); Psc::create_file_if_not_exists(fileName); auto rotating_sink = std::make_shared( fileName, byte_size, num ); std::vector sinks = {rotating_sink}; auto logger = std::make_shared( key, // Logger 名称 sinks.begin(), sinks.end(), // Sinks 列表 spdlog::thread_pool(), // 使用初始化的线程池 spdlog::async_overflow_policy::block // 当队列满时,阻塞写入 ); return logger; } std::map> day_log_map; void rotating_log(const std::string& key, const std::string& info, int size, int num) { try { if (day_log_map.find(key) == day_log_map.end()) { day_log_map.insert({key, create_rotating_logger(key, size, num)}); } std::shared_ptr daily_logger = day_log_map[key]; daily_logger->set_pattern("%Y-%m-%d %H:%M:%S [%l] %v"); daily_logger->info(info); daily_logger->flush(); } catch (const spdlog::spdlog_ex& e) { std::cerr << "Log initialization failed: " << e.what() << std::endl; } } void pure_log(const std::string& pure_path, const std::string& info, bool close_after_write) { auto path = Psc::get_abs_path(pure_path); static std::map> file_logger_map; static std::mutex mtx; // 用于保护file_logger_map static std::mutex mtx2; // 用于保护file_logger_map static auto create_pure_logger = [](const std::string& fileName) { Psc::create_file_if_not_exists( fileName); auto c = spdlog::basic_logger_mt(fileName, fileName); auto formatter = std::make_unique("%v", spdlog::pattern_time_type::local, "", spdlog::pattern_formatter::custom_flags()); c->set_formatter(std::move(formatter)); return c; }; if (close_after_write) { // 用完就关:每次都新建,写完就析构 std::lock_guard lock(mtx2); // 加锁以保证线程安全 auto logger = create_pure_logger(path); logger->log(spdlog::level::info, info); logger->flush(); spdlog::drop(path); // 离开作用域后logger自动析构,文件关闭 return; } else { std::lock_guard lock(mtx); // 加锁以保证线程安全 auto iter = file_logger_map.find(path); if (iter == file_logger_map.end()) { file_logger_map.insert({path, create_pure_logger(path)}); } std::shared_ptr logger = file_logger_map[path]; logger->log(spdlog::level::info, info); logger->flush(); } } Log_Type& Log_Type::append(std::string key) { list.push_back(key); return *this; } Log_Type& Log_Type::append(std::string key, std::string val) { map.push_back({key, val}); return *this; } std::string Log_Type::to_string() const{ std::string base; for (const auto& it : list) { base += "[" + it + "] "; } for (const auto& it : map) { if (new_line) { base += "\n"; } base += "[" + it.first + "~" + it.second + "] "; } return base; } Log_Type& Log_Type::set(const std::string& key, std::string val) { append(key, val); return *this; } namespace spdlog { struct my_daily_filename_calculator { // Create filename for the form basename.YYYY-MM-DD static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { filename_t basename, ext; std::tie(basename, ext) = details::file_helper::split_by_extension(filename); return fmt_lib::format( SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext); } }; } BaseLogger::BaseLogger(const std::string& log_path, size_t byte_size, size_t piece_num) : log_path(log_path), byte_size(byte_size), piece_num(piece_num) { std::string path = Psc::get_abs_path(log_path); Psc::create_file_if_not_exists(path); path = Psc::utf8_2_platform(path); auto rotating_sink = std::make_shared( path, byte_size, piece_num ); std::vector sinks = {rotating_sink}; logger = std::make_shared( path, // Logger 名称 sinks.begin(), sinks.end(), // Sinks 列表 spdlog::thread_pool(), // 使用初始化的线程池 spdlog::async_overflow_policy::block // 当队列满时,阻塞写入 ); //logger->set_level(spdlog::level::debug); logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v"); } Base_Logger_Manager::Base_Logger_Manager() { spdlog::set_level(spdlog::level::debug); } Base_Logger_Manager& Base_Logger_Manager::set_thread_num(size_t thread_num) { this->thread_num = thread_num; return *this; } Base_Logger_Manager& Base_Logger_Manager::set_flush_seconds(size_t flush_seconds) { this->flush_seconds = flush_seconds; return *this; } Base_Logger_Manager& Base_Logger_Manager::set_buffer_size(size_t buffer_size) { this->buffer_size = buffer_size; return *this; } void Base_Logger_Manager::init() const { spdlog::init_thread_pool(buffer_size, thread_num); spdlog::flush_every(std::chrono::seconds(flush_seconds)); std::cout << "Base_Logger_Manager sqdlog init thread pool!" + VAR_STR_3(thread_num, flush_seconds, buffer_size) << std::endl; } // 调用 spdlog::shutdown() 会确保: // 所有日志被刷新到磁盘。 // 所有日志器被关闭,相关资源被释放。 Base_Logger_Manager::~Base_Logger_Manager() { std::ostringstream oss; oss << "Base_Logger_Manager::~Base_Logger_Manager()" << VAR_STR_3(buffer_size, flush_seconds, thread_num) << std::flush; spdlog::shutdown(); oss << "spdlog::shutdown()!\n" << std::flush; std::cout << oss.str(); } std::string BaseLogger::to_log(const Log_Info& log_info) { return "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() + log_info.content; } void BaseLogger::log_main(const Log_Info& log_info) const { auto msg = to_log(log_info); if (log_info.console) { std::cerr << msg + "\n" << std::flush; } //logger->log(level, msg); logger->info(msg); if(redirect){ redirect(log_info); } } void BaseLogger::c_debug(const std::string& func_pattern, const Log_Type& log_type, const std::string& content) { log_main({true, spdlog::level::debug, func_pattern, log_type, content}); } void BaseLogger::debug(const std::string& func_pattern, const Log_Type& log_type, const std::string& content) { log_main({false, spdlog::level::debug, func_pattern, log_type, content}); } void BaseLogger::error(const std::string& func_pattern, const Log_Type& log_type, const std::string& content) { log_main({true, spdlog::level::err, func_pattern, log_type, content}); logger->flush(); }