25 namespace diagnostics {
30 std::lock_guard<std::mutex> lock(mutex_);
32 if (!std::filesystem::exists(filepath)) {
41 std::lock_guard<std::mutex> lock(mutex_);
43 if (!std::filesystem::exists(filepath)) {
52 std::filesystem::rename(filepath, new_filepath);
58 }
catch (
const std::filesystem::filesystem_error&) {
66 std::vector<std::string> log_files =
get_log_files(base_filepath);
69 sort_files_by_time(log_files);
72 if (log_files.size() > config_.
max_files) {
73 for (
size_t i = config_.
max_files; i < log_files.size(); ++i) {
75 std::filesystem::remove(log_files[i]);
76 }
catch (
const std::filesystem::filesystem_error&) {
81 }
catch (
const std::exception&) {
87 std::string base_name = get_base_filename(base_filepath);
88 std::string directory = get_directory(base_filepath);
92 std::vector<std::string> log_files =
get_log_files(base_filepath);
94 for (
const auto& file : log_files) {
95 std::string filename = std::filesystem::path(file).filename().string();
96 int index = get_file_index(filename);
97 if (index > max_index) {
103 int next_index = max_index + 1;
104 std::string next_filename = generate_filename(base_name, next_index);
106 return directory +
"/" + next_filename;
110 std::lock_guard<std::mutex> lock(mutex_);
116 if (std::filesystem::exists(filepath)) {
117 return std::filesystem::file_size(filepath);
119 }
catch (
const std::filesystem::filesystem_error&) {
126 std::vector<std::string> log_files;
129 std::string base_name = std::filesystem::path(base_filepath).stem().string();
130 std::string directory = std::filesystem::path(base_filepath).parent_path().string();
132 if (directory.empty()) {
137 std::regex pattern(base_name +
"\\.\\d+\\.log");
139 for (
const auto& entry : std::filesystem::directory_iterator(directory)) {
140 if (entry.is_regular_file()) {
141 std::string filename = entry.path().filename().string();
142 if (std::regex_match(filename, pattern)) {
143 log_files.push_back(entry.path().string());
147 }
catch (
const std::filesystem::filesystem_error&) {
154 std::string LogRotation::get_base_filename(
const std::string& filepath)
const {
155 std::filesystem::path path(filepath);
156 return path.stem().string();
159 std::string LogRotation::get_directory(
const std::string& filepath)
const {
160 std::filesystem::path path(filepath);
161 std::string dir = path.parent_path().string();
162 return dir.empty() ?
"." : dir;
165 int LogRotation::get_file_index(
const std::string& filename)
const {
167 std::regex pattern(R
"((\d+)\.log$)");
170 if (std::regex_search(filename, match, pattern)) {
171 return std::stoi(match[1].str());
177 std::string LogRotation::generate_filename(
const std::string& base_name,
int index)
const {
178 std::ostringstream oss;
179 oss << base_name <<
"." << index <<
".log";
183 void LogRotation::sort_files_by_time(std::vector<std::string>& files)
const {
184 std::sort(files.begin(), files.end(), [](
const std::string& a,
const std::string& b) {
186 auto time_a = std::filesystem::last_write_time(a);
187 auto time_b = std::filesystem::last_write_time(b);
188 return time_a > time_b;
189 } catch (
const std::filesystem::filesystem_error&) {
LogRotation(const LogRotationConfig &config=LogRotationConfig{})
Constructor.
void cleanup_old_files(const std::string &base_filepath)
Clean up old log files.
void update_config(const LogRotationConfig &config)
Update rotation configuration.
static std::vector< std::string > get_log_files(const std::string &base_filepath)
Get all log files matching pattern.
std::string rotate(const std::string &filepath)
Perform log rotation.
bool should_rotate(const std::string &filepath) const
Check if current log file needs rotation.
static size_t get_file_size(const std::string &filepath)
Get file size in bytes.
std::string get_next_file_path(const std::string &base_filepath) const
Get next available log file path.
Log rotation configuration.
size_t max_file_size_bytes