先上日志配置定义
struct logger_config {
std::string name = "run_logger";
spdlog::level::level_enum level = spdlog::level::trace;
std::string format = "[%Y-%m-%d %H:%M:%S.%f] [%P] [%^%l%$] [%s:%# %!()] %v";
std::string file_name = "../log/run.log";
// by_size按大小分割 by_day按天分割 by_hour按小时分割
std::string roll_type = "by_day";
unsigned int reserve_count = 10;
unsigned int roll_size = 1024 * 1024 * 100; // 默认100 MB
// 表示按天切割的时刻,具体是时刻通过rotation_hour:rotation_minute指定
unsigned int rotation_hour = 0;
unsigned int rotation_minute = 0;
// 异步日志线程池大小
unsigned int async_thread_pool_size = 1;
};
关于format的格式定义可以参考这里https://spdlog.docsforge.com/master/3.custom-formatting/#pattern-flags
定义自己的日志类logger
// log.h
class logger {
public:
logger();
~logger();
int set_config(const logger_config& config);
void log(const char* file_name_in, int line_in, const char* func_name_in, spdlog::level::level_enum level,
const std::string& msg);
private:
std::shared_ptr<spdlog::logger> run_logger_;
std::shared_ptr<spdlog::details::thread_pool> thread_pool_;
};
// log.cpp
logger::logger() {
// 设置打印日志时异常处理函数
spdlog::set_error_handler([](const std::string& msg) {
std::cout << fmt::format("[{}:{} {}()] {}", __FILE__, __LINE__, __FUNCTION__, msg) << std::endl;
});
}
logger::~logger() { spdlog::drop_all(); }
int logger::set_config(const logger_config& config) {
int ret = 0;
do {
try {
std::shared_ptr<spdlog::sinks::sink> sink_;
if (config.roll_type == "by_size") {
sink_ = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(config.file_name, config.roll_size,
config.reserve_count, true);
} else if (config.roll_type == "by_day") {
sink_ = std::make_shared<spdlog::sinks::daily_file_sink_mt>(config.file_name, config.rotation_hour,
config.rotation_minute, false, config.reserve_count);
} else if (config.roll_type == "by_hour") {
sink_ = std::make_shared<spdlog::sinks::hourly_file_sink_mt>(config.file_name, false, config.reserve_count);
} else {
ret = 1;
LOG_ERROR("invalid roll_type: {}", config.roll_type.c_str());
break;
}
auto formatter = std::make_unique<spdlog::pattern_formatter>(config.format, spdlog::pattern_time_type::local,
spdlog::details::os::default_eol);
// unique_ptr不能复制,无法通过值传递调用set_formatter,只能使用move
sink_->set_formatter(std::move(formatter));
thread_pool_ = std::make_shared<spdlog::details::thread_pool>(config.async_thread_pool_size, 1);
run_logger_ = std::make_shared<spdlog::async_logger>(config.name, std::move(sink_), thread_pool_,
spdlog::async_overflow_policy::block);
// 设置默认刷新级别和打印级别
run_logger_->flush_on(spdlog::level::trace);
run_logger_->set_level(config.level);
// 注册到spdlog
spdlog::register_logger(run_logger_);
} catch (const std::exception& ex) {
ret = -1;
LOG_ERROR("{}", ex.what());
} catch (...) {
ret = -1;
LOG_ERROR("unknow exception");
}
} while (0);
return ret;
}
void logger::log(const char* file_name_in, int line_in, const char* func_name_in, spdlog::level::level_enum level,
const std::string& msg) {
try {
run_logger_->log(spdlog::source_loc{file_name_in, line_in, func_name_in}, level, msg);
} catch (const std::exception& ex) {
LOG_ERROR("{}", ex.what());
} catch (...) {
LOG_ERROR("unknow exception");
}
}