agentmux_common/
log_retention.rs1use std::path::Path;
8use std::time::{Duration, SystemTime};
9
10pub fn cleanup_old_logs(log_dir: &Path, days: u64) {
13 let cutoff = SystemTime::now() - Duration::from_secs(days * 86400);
14 let Ok(entries) = std::fs::read_dir(log_dir) else { return };
15 for entry in entries.flatten() {
16 let path = entry.path();
17 if !path.to_string_lossy().contains(".log.") {
18 continue;
19 }
20 if let Ok(meta) = entry.metadata() {
21 if let Ok(modified) = meta.modified() {
22 if modified < cutoff {
23 let _ = std::fs::remove_file(&path);
24 }
25 }
26 }
27 }
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use std::fs::{File, FileTimes};
34
35 fn aged(dir: &Path, name: &str, age_days: u64) -> std::path::PathBuf {
36 let p = dir.join(name);
37 let f = File::create(&p).unwrap();
38 let t = SystemTime::now() - Duration::from_secs(age_days * 86400);
39 f.set_times(FileTimes::new().set_modified(t)).unwrap();
40 p
41 }
42
43 #[test]
44 fn deletes_only_old_rotated_logs() {
45 let tmp = tempfile::tempdir().unwrap();
46 let dir = tmp.path();
47 let old_log = aged(dir, "srv.log.2026-09-01", 30);
48 let new_log = aged(dir, "srv.log.2026-09-29", 1);
49 let old_other = aged(dir, "current.txt", 30);
50 cleanup_old_logs(dir, 7);
51 assert!(!old_log.exists(), "an old rotated log is deleted");
52 assert!(new_log.exists(), "a recent rotated log stays");
53 assert!(old_other.exists(), "a file without `.log.` in its name is never touched");
54 }
55
56 #[test]
57 fn a_missing_directory_is_not_an_error() {
58 cleanup_old_logs(Path::new("/nonexistent/agentmux-log-retention-test"), 7);
59 }
60}