6#if !defined(SIGNET_ENABLE_COMMERCIAL) || !SIGNET_ENABLE_COMMERCIAL
7#error "signet/ai/log_retention.hpp requires SIGNET_ENABLE_COMMERCIAL=ON (AGPL-3.0 commercial tier). See LICENSE_COMMERCIAL."
162 : policy_(std::move(
policy)) {
163 (void)commercial::require_feature(
"LogRetentionManager");
168 archive_cb_ = std::move(cb);
173 pre_delete_cb_ = std::move(cb);
186 const std::string& log_dir, int64_t
now_ns)
const {
190 namespace fs = std::filesystem;
192 if (!fs::exists(log_dir) || !fs::is_directory(log_dir)) {
193 summary.
errors.push_back(
"Directory does not exist: " + log_dir);
203 std::vector<FileInfo> files;
205 for (
const auto& entry : fs::directory_iterator(log_dir)) {
206 if (!entry.is_regular_file())
continue;
208 const auto& path = entry.path();
209 if (!path.string().ends_with(policy_.
file_suffix))
continue;
212 auto mod_time = fs::last_write_time(path, ec);
216 auto sys_time = std::chrono::file_clock::to_sys(mod_time);
217 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
218 sys_time.time_since_epoch()).count();
220 auto fsize = entry.file_size(ec);
223 files.push_back({path.string(),
static_cast<int64_t
>(ns), fsize});
227 std::sort(files.begin(), files.end(),
228 [](
const FileInfo& a,
const FileInfo& b) {
229 return a.mod_time_ns < b.mod_time_ns;
234 for (
const auto& fi : files) {
235 int64_t age_ns =
now_ns - fi.mod_time_ns;
241 if (pre_delete_cb_) {
242 allow = pre_delete_cb_(fi.path);
246 fs::remove(fi.path, ec);
248 summary.
errors.push_back(
"Failed to delete: " + fi.path
249 +
" (" + ec.message() +
")");
268 bool ok = archive_cb_(fi.path);
274 summary.
errors.push_back(
"Archive callback failed: " + fi.path);
314 const std::string& log_dir, int64_t
now_ns)
const {
315 std::vector<FileStatus> result;
316 namespace fs = std::filesystem;
318 if (!fs::exists(log_dir) || !fs::is_directory(log_dir))
return result;
320 for (
const auto& entry : fs::directory_iterator(log_dir)) {
321 if (!entry.is_regular_file())
continue;
322 const auto& path = entry.path();
323 if (!path.string().ends_with(policy_.
file_suffix))
continue;
326 auto mod_time = fs::last_write_time(path, ec);
329 auto sys_time = std::chrono::file_clock::to_sys(mod_time);
330 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
331 sys_time.time_since_epoch()).count();
333 auto fsize = entry.file_size(ec);
336 int64_t age =
now_ns -
static_cast<int64_t
>(ns);
339 fs_entry.
path = path.string();
340 fs_entry.age_ns = age;
341 fs_entry.size_bytes = fsize;
350 result.push_back(std::move(fs_entry));
354 std::sort(result.begin(), result.end(),
356 return a.age_ns > b.age_ns;
Manages log file lifecycle: retention, archival, and deletion.
void set_pre_delete_callback(PreDeleteCallback cb)
Set the pre-deletion callback.
RetentionSummary enforce(const std::string &log_dir, int64_t now_ns) const
Enforce retention policy on a log directory.
std::function< bool(const std::string &source_path)> ArchiveCallback
Callback invoked to archive a file.
LogRetentionManager(RetentionPolicy policy={})
std::function< bool(const std::string &path)> PreDeleteCallback
Callback invoked before deleting a file.
void set_archive_callback(ArchiveCallback cb)
Set the archival callback.
std::vector< FileStatus > list_files(const std::string &log_dir, int64_t now_ns) const
const RetentionPolicy & policy() const noexcept
Get the current retention policy.
int64_t now_ns()
Return the current time as nanoseconds since the Unix epoch (UTC).
List all managed log files in a directory with their age classification.
enum signet::forge::LogRetentionManager::FileStatus::Classification status
Retention policy configuration for log lifecycle management.
std::string file_suffix
File name pattern to match (glob-style suffix).
int64_t max_retention_ns
Maximum retention period in nanoseconds.
uint64_t max_active_files
Maximum number of active log files.
bool enable_deletion
If true, actually delete files past max_retention_ns.
uint64_t max_active_size_bytes
Maximum total size of active (non-archived) log files in bytes.
int64_t archive_after_ns
Archival threshold in nanoseconds.
int64_t min_retention_ns
Minimum retention period in nanoseconds.
bool enable_archival
If true, actually archive files past archive_after_ns.
Summary of a retention enforcement pass.
bool dry_run
Whether the enforcement pass was a dry-run.
std::vector< std::string > deleted_paths
Paths of files that were deleted.
uint64_t deleted_size_bytes
Total size of deleted files in bytes.
std::vector< std::string > errors
Error messages from failed operations.
int64_t files_archived
Number of files archived (or would be archived in dry-run).
uint64_t archived_size_bytes
Total size of archived files in bytes.
int64_t files_scanned
Number of files scanned.
uint64_t active_size_bytes
Total size of active files in bytes.
std::vector< std::string > archived_paths
Paths of files that were archived.
int64_t files_active
Number of files within active retention window.
int64_t files_failed
Number of files that failed archival or deletion.
int64_t files_deleted
Number of files deleted (or would be deleted in dry-run).