Files
CPP_Core/Core/spdlog/export.cpp
T
2026-06-16 10:56:40 +08:00

292 lines
8.9 KiB
C++

#include "export.h"
#include "../system/export.h"
#include <filesystem>
#include <fstream>
#include <map>
#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 <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "spdlog/pattern_formatter.h"
namespace fs = std::filesystem;
void spdlog_close() {
spdlog::shutdown();
}
Log_Type::Log_Type(std::vector<std::string> list) : list(list) {
}
Log_Type::Log_Type(std::vector<std::pair<std::string, std::string>> map) : map(map) {
}
Log_Type::Log_Type(std::vector<std::string> list, std::vector<std::pair<std::string, std::string>> 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<spdlog::logger> 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<spdlog::sinks::rotating_file_sink_mt>(
fileName,
byte_size,
num
);
std::vector<spdlog::sink_ptr> sinks = {rotating_sink};
auto logger = std::make_shared<spdlog::async_logger>(
key, // Logger 名称
sinks.begin(), sinks.end(), // Sinks 列表
spdlog::thread_pool(), // 使用初始化的线程池
spdlog::async_overflow_policy::block // 当队列满时,阻塞写入
);
return logger;
}
std::map<std::string, std::shared_ptr<spdlog::logger>> 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<spdlog::logger> 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<std::string, std::shared_ptr<spdlog::logger>> 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<spdlog::pattern_formatter>("%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<std::mutex> 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<std::mutex> 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<spdlog::logger> 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<spdlog::sinks::rotating_file_sink_mt>(
path,
byte_size,
piece_num
);
std::vector<spdlog::sink_ptr> sinks = {rotating_sink};
logger = std::make_shared<spdlog::async_logger>(
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();
}