deviceAccessLayer/src/common/daily_and_size_sink.cpp

141 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}
}