141 lines
4.8 KiB
C++
141 lines
4.8 KiB
C++
#include "daily_and_size_sink.h"
|
||
#include <charconv>
|
||
#include <regex>
|
||
|
||
#include "date_util.h"
|
||
|
||
namespace zsy
|
||
{
|
||
DailyAndSizeSink::DailyAndSizeSink(const std::string &filename, uintmax_t maxSize, int32_t maxDays)
|
||
: maxSize(maxSize)
|
||
, maxDays(maxDays)
|
||
{
|
||
std::filesystem::path base_path(filename);
|
||
auto paths = base_path.parent_path();
|
||
basePath = paths.string();
|
||
baseFilename = base_path.stem().string();
|
||
baseExt = base_path.extension().string();
|
||
std::filesystem::create_directories(paths);
|
||
currentDate = DateUtil::format(Ymd_);
|
||
currentIndex = lastIndex();
|
||
currentSize = lastSize();
|
||
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
|
||
}
|
||
|
||
void DailyAndSizeSink::rotateFile()
|
||
{
|
||
auto current_date = DateUtil::format(Ymd_);
|
||
|
||
if (current_date != currentDate)
|
||
{
|
||
fileHelper.flush();
|
||
fileHelper.close();
|
||
std::filesystem::rename(basePath + "\\" + baseFilename + baseExt, basePath + "\\" + baseFilename + "." + currentDate + "." + std::to_string(currentIndex) + baseExt);
|
||
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
|
||
currentDate = current_date;
|
||
currentIndex = 1;
|
||
} else
|
||
{
|
||
if (currentSize >= maxSize)
|
||
{
|
||
fileHelper.flush();
|
||
fileHelper.close();
|
||
std::filesystem::rename(basePath + "\\" + baseFilename + baseExt, basePath + "\\" + baseFilename + "." + currentDate + "." + std::to_string(currentIndex) + baseExt);
|
||
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
|
||
currentIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void DailyAndSizeSink::cleanOldFiles()
|
||
{
|
||
try
|
||
{
|
||
if (maxDays <= 0) return;
|
||
|
||
auto now = std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now());
|
||
auto cutoff_time = now - std::chrono::days(maxDays);
|
||
|
||
// 正则表达式模式:baseName.YYYY-MM-DD(.index)?.ext
|
||
std::regex file_pattern(baseFilename + R"(\.(\d{4}-\d{2}-\d{2})(\.\d+)?)" + baseExt);
|
||
|
||
std::filesystem::path paths(basePath);
|
||
for (const auto &entry: std::filesystem::directory_iterator(paths))
|
||
{
|
||
if (entry.is_regular_file())
|
||
{
|
||
std::string filename = entry.path().filename().string();
|
||
std::smatch match;
|
||
|
||
if (std::regex_match(filename, match, file_pattern))
|
||
{
|
||
std::string date_str = match[1].str();
|
||
std::chrono::sys_days date;
|
||
std::istringstream tstr(date_str);
|
||
tstr >> std::chrono::parse("%F", date);
|
||
if (date < cutoff_time)
|
||
{
|
||
std::filesystem::remove(entry.path());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (const std::exception &e)
|
||
{
|
||
// 清理失败
|
||
}
|
||
}
|
||
|
||
void DailyAndSizeSink::sink_it_(const spdlog::details::log_msg &msg)
|
||
{
|
||
spdlog::memory_buf_t formatted;
|
||
formatter_->format(msg, formatted);
|
||
std::string formatted_str(formatted.data(), formatted.size());
|
||
rotateFile();
|
||
fileHelper.write(formatted);
|
||
currentSize = fileHelper.size();
|
||
cleanOldFiles();
|
||
}
|
||
|
||
void DailyAndSizeSink::flush_()
|
||
{
|
||
fileHelper.flush();
|
||
}
|
||
|
||
uint32_t DailyAndSizeSink::lastIndex()
|
||
{
|
||
uint32_t index = 0;
|
||
std::regex file_pattern(baseFilename + R"(\.\d{4}-\d{2}-\d{2}\.(\d+))" + baseExt);
|
||
std::filesystem::path paths(basePath);
|
||
for (const auto &entry: std::filesystem::directory_iterator(paths))
|
||
{
|
||
if (entry.is_regular_file())
|
||
{
|
||
std::string filename = entry.path().filename().string();
|
||
std::smatch match;
|
||
|
||
if (std::regex_match(filename, match, file_pattern))
|
||
{
|
||
std::string index_str = match[1].str();
|
||
auto index_chp = index_str.data();
|
||
int index_{};
|
||
std::from_chars(index_chp, index_chp + index_str.size(), index_);
|
||
if (index_ > index) index = index_;
|
||
}
|
||
}
|
||
}
|
||
return index + 1;
|
||
}
|
||
|
||
uintmax_t DailyAndSizeSink::lastSize()
|
||
{
|
||
uintmax_t size = 0;
|
||
std::filesystem::path filePath(basePath + "\\" + baseFilename + baseExt);
|
||
if (std::filesystem::exists(filePath))
|
||
{
|
||
size = std::filesystem::file_size(filePath);
|
||
}
|
||
return size;
|
||
}
|
||
}
|