103 lines
2.6 KiB
C++
103 lines
2.6 KiB
C++
// logger.cpp
|
||
#include "logger.hpp"
|
||
#include <iomanip>
|
||
#include <ctime>
|
||
#include <fstream>
|
||
#include <cstdio>
|
||
|
||
std::ofstream Logger::log_file;
|
||
std::string Logger::current_log_filename;
|
||
|
||
void Logger::set_log_to_file(const std::string &filename)
|
||
{
|
||
current_log_filename = filename;
|
||
log_file.open(filename, std::ios::app);
|
||
if (!log_file.is_open())
|
||
{
|
||
std::cerr << "[Logger] Failed to open log file: " << filename << std::endl;
|
||
}
|
||
}
|
||
|
||
std::string Logger::get_time_string()
|
||
{
|
||
using namespace std::chrono;
|
||
|
||
// 获取当前时间点
|
||
auto now = system_clock::now();
|
||
auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;
|
||
|
||
// 转换为 time_t(秒)
|
||
auto t = system_clock::to_time_t(now);
|
||
std::tm ltm = *std::localtime(&t);
|
||
|
||
// 拼接格式化字符串
|
||
std::ostringstream oss;
|
||
oss << std::put_time(<m, "%Y-%m-%d %H:%M:%S")
|
||
<< '.' << std::setw(3) << std::setfill('0') << ms.count();
|
||
|
||
return oss.str();
|
||
}
|
||
|
||
void Logger::log(LogLevel level, const std::string &msg)
|
||
{
|
||
std::string level_str;
|
||
switch (level)
|
||
{
|
||
case LogLevel::INFO:
|
||
level_str = "[INFO] ";
|
||
break;
|
||
case LogLevel::WARN:
|
||
level_str = "[WARN] ";
|
||
break;
|
||
case LogLevel::ERROR:
|
||
level_str = "[ERROR]";
|
||
break;
|
||
}
|
||
|
||
std::string full_msg = get_time_string() + " " + level_str + " " + msg;
|
||
|
||
std::cout << full_msg << std::endl;
|
||
|
||
if (log_file.is_open())
|
||
{
|
||
log_file << full_msg << std::endl;
|
||
log_file.flush();
|
||
|
||
// 检查是否需要轮转
|
||
if (get_file_size(current_log_filename) >= MAX_LOG_FILE_SIZE)
|
||
{
|
||
rotate_logs();
|
||
}
|
||
}
|
||
}
|
||
|
||
size_t Logger::get_file_size(const std::string &filename)
|
||
{
|
||
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
|
||
return in.is_open() ? static_cast<size_t>(in.tellg()) : 0;
|
||
}
|
||
|
||
void Logger::rotate_logs()
|
||
{
|
||
log_file.close();
|
||
|
||
// 删除最旧的日志
|
||
std::string oldest = current_log_filename + "." + std::to_string(MAX_LOG_BACKUP_COUNT);
|
||
std::remove(oldest.c_str());
|
||
|
||
// 重命名 *.4 -> *.5, ..., *.1 -> *.2
|
||
for (int i = MAX_LOG_BACKUP_COUNT - 1; i >= 1; --i)
|
||
{
|
||
std::string old_name = current_log_filename + "." + std::to_string(i);
|
||
std::string new_name = current_log_filename + "." + std::to_string(i + 1);
|
||
std::rename(old_name.c_str(), new_name.c_str());
|
||
}
|
||
|
||
// 当前日志 -> .1
|
||
std::string first_backup = current_log_filename + ".1";
|
||
std::rename(current_log_filename.c_str(), first_backup.c_str());
|
||
|
||
// 重新打开新日志
|
||
log_file.open(current_log_filename, std::ios::trunc);
|
||
}
|