diff --git a/Logger.cs b/Logger.cs index f39301b..d0e8b0f 100644 --- a/Logger.cs +++ b/Logger.cs @@ -41,7 +41,9 @@ public static void Initialize(string logDirectory, string version = "Unknown", b } LogFile = Path.Combine(logDirectory, $"{DateTime.Now:yyyy-MM-dd-HHmmss}.log"); - + + PruneExpiredLogs(logDirectory); + // Write session header to log file WriteToFile("=== BootstrapMate Session Started ==="); WriteToFile($"Version: {version}"); @@ -68,6 +70,52 @@ public static void Initialize(string logDirectory, string version = "Unknown", b } } + /// + /// Deletes logs in older than the retention + /// window. Every run writes a new timestamped file and nothing has ever removed + /// one, so on a machine that has been enrolled for a year the directory holds + /// hundreds of them. + /// + /// + /// Age comes from the file's last write time rather than its name: the directory + /// also collects logs written by wrapper scripts, which do not follow the + /// timestamped naming, and those need expiring too. + /// + internal static void PruneExpiredLogs(string logDirectory, int? retentionDays = null) + { + var days = retentionDays ?? BootstrapMate.Core.BootstrapMateConstants.LogRetentionDays; + if (days <= 0) + { + return; + } + + try + { + var cutoff = DateTime.Now.AddDays(-days); + + foreach (var file in Directory.GetFiles(logDirectory, "*.log")) + { + try + { + var info = new FileInfo(file); + if (info.LastWriteTime < cutoff) + { + info.Delete(); + } + } + catch + { + // A log still held open elsewhere throws here. Skip it and try + // again next run rather than aborting the sweep. + } + } + } + catch + { + // Retention is best-effort and must never stop a bootstrap run. + } + } + public static void Debug(string message) { Log(LogLevel.Debug, message); diff --git a/src/BootstrapMate.Core/BootstrapMateConstants.cs b/src/BootstrapMate.Core/BootstrapMateConstants.cs index 3279ac7..d30c8f3 100644 --- a/src/BootstrapMate.Core/BootstrapMateConstants.cs +++ b/src/BootstrapMate.Core/BootstrapMateConstants.cs @@ -29,6 +29,12 @@ public static class BootstrapMateConstants /// Log file directory. public const string LogDirectory = @"C:\ProgramData\ManagedBootstrap\logs"; + /// + /// How long session logs are kept. Every run writes a new timestamped file, so + /// without a window the directory grows for the life of the machine. + /// + public const int LogRetentionDays = 30; + /// Cache directory for downloaded packages. public const string CacheDirectory = @"C:\ProgramData\ManagedBootstrap\cache";