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."
163 : policy_(std::move(
policy)) {
164 auto gate = commercial::require_feature(
"LogRetentionManager");
165 if (!gate)
throw std::runtime_error(gate.error().message);
170 archive_cb_ = std::move(cb);
175 pre_delete_cb_ = std::move(cb);
188 const std::string& log_dir, int64_t
now_ns)
const {
192 namespace fs = std::filesystem;
194 if (!fs::exists(log_dir) || !fs::is_directory(log_dir)) {
195 summary.
errors.push_back(
"Directory does not exist: " + log_dir);
205 std::vector<FileInfo> files;
207 for (
const auto& entry : fs::directory_iterator(log_dir)) {
208 if (!entry.is_regular_file())
continue;
210 const auto& path = entry.path();
211 if (!path.string().ends_with(policy_.
file_suffix))
continue;
214 auto mod_time = fs::last_write_time(path, ec);
218 auto sys_time = std::chrono::file_clock::to_sys(mod_time);
219 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
220 sys_time.time_since_epoch()).count();
222 auto fsize = entry.file_size(ec);
225 files.push_back({path.string(),
static_cast<int64_t
>(ns), fsize});
229 std::sort(files.begin(), files.end(),
230 [](
const FileInfo& a,
const FileInfo& b) {
231 return a.mod_time_ns < b.mod_time_ns;
236 for (
const auto& fi : files) {
237 int64_t age_ns =
now_ns - fi.mod_time_ns;
243 if (pre_delete_cb_) {
244 allow = pre_delete_cb_(fi.path);
248 fs::remove(fi.path, ec);
250 summary.
errors.push_back(
"Failed to delete: " + fi.path
251 +
" (" + ec.message() +
")");
270 bool ok = archive_cb_(fi.path);
276 summary.
errors.push_back(
"Archive callback failed: " + fi.path);
316 const std::string& log_dir, int64_t
now_ns)
const {
317 std::vector<FileStatus> result;
318 namespace fs = std::filesystem;
320 if (!fs::exists(log_dir) || !fs::is_directory(log_dir))
return result;
322 for (
const auto& entry : fs::directory_iterator(log_dir)) {
323 if (!entry.is_regular_file())
continue;
324 const auto& path = entry.path();
325 if (!path.string().ends_with(policy_.
file_suffix))
continue;
328 auto mod_time = fs::last_write_time(path, ec);
331 auto sys_time = std::chrono::file_clock::to_sys(mod_time);
332 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
333 sys_time.time_since_epoch()).count();
335 auto fsize = entry.file_size(ec);
338 int64_t age =
now_ns -
static_cast<int64_t
>(ns);
341 fs_entry.
path = path.string();
342 fs_entry.age_ns = age;
343 fs_entry.size_bytes = fsize;
352 result.push_back(std::move(fs_entry));
356 std::sort(result.begin(), result.end(),
358 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).