NLog归档日志仅删除文件未删文件夹,如何启用文件夹删除功能?
解决NLog归档后保留空日志文件夹的问题
NLog的FileTarget默认仅会归档并删除过期日志文件,但不会自动清理空的日志目录。要实现归档时删除空文件夹,需要额外添加目录清理逻辑,以下是两种可行的实现方式:
方式一:订阅归档事件,实时清理空目录
在你的FileTarget配置代码中,添加归档事件的处理逻辑,在日志文件被归档删除后,检查对应的日期文件夹是否为空,若为空则删除:
var target = new FileTarget { Name = LogFileName, FileName = Path.Combine(logDirectoryPath, @"${date:format=yyyyMMdd}", LogFileName + ".log"), Layout = @"${date}|${level:uppercase=true}|${message} ${exception:format=ToString}", ArchiveFileName = Path.Combine(logArchievePath, LogFileName + @"_${date:format=HHmmssfff}.zip"), ArchiveAboveSize = 10* 1024 * 1024, EnableArchiveFileCompression = true, ArchiveEvery = FileArchivePeriod.Day, ArchiveNumbering = ArchiveNumberingMode.DateAndSequence, MaxArchiveDays = ConfiguredAdminSetting.MaxLogRetentionDay, EnableFileDelete = true, }; // 添加归档事件处理,清理空文件夹 target.Archive += (sender, args) => { var logDateFolder = Path.GetDirectoryName(args.FileName); if (!Directory.Exists(logDateFolder)) return; // 检查文件夹是否为空(包含所有文件,包括隐藏文件) var filesInFolder = Directory.GetFiles(logDateFolder, "*.*", SearchOption.TopDirectoryOnly); if (filesInFolder.Length == 0) { try { Directory.Delete(logDateFolder); } catch (Exception ex) { LogManager.GetCurrentClassLogger().Warn(ex, "Failed to delete empty log directory: {0}", logDateFolder); } } }; LogManager.Configuration.Variables["baseDataPath"] = path; LogManager.Configuration.AddTarget(LogFileName, target);
方式二:定时扫描,清理过期空目录
如果担心归档事件覆盖不全(比如日志文件直接被删除未触发归档),可以添加定时任务,定期扫描日志根目录,删除超过保留期限的空文件夹:
// 在项目启动时初始化定时清理任务 var cleanupTimer = new Timer(async (state) => { var logRootDir = logDirectoryPath; if (!Directory.Exists(logRootDir)) return; var maxRetentionDays = ConfiguredAdminSetting.MaxLogRetentionDay; var cutoffDate = DateTime.Now.AddDays(-maxRetentionDays); foreach (var dirPath in Directory.GetDirectories(logRootDir)) { var dirName = Path.GetFileName(dirPath); // 解析文件夹名称为日期(需与日志文件夹格式yyyyMMdd匹配) if (DateTime.TryParseExact(dirName, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dirDate)) { if (dirDate < cutoffDate) { if (Directory.GetFiles(dirPath).Length == 0) { try { Directory.Delete(dirPath); } catch (Exception ex) { LogManager.GetCurrentClassLogger().Warn(ex, "Failed to delete expired empty log directory: {0}", dirPath); } } } } } }, null, TimeSpan.Zero, TimeSpan.FromDays(1)); // 应用关闭时释放定时器(示例:在ASP.NET Core中可在HostedService的StopAsync方法处理) // cleanupTimer.Dispose();
注意事项
- 异常处理:删除文件夹时需捕获权限不足、文件被占用等异常,避免影响主程序运行。
- 格式匹配:确保日期文件夹的名称格式与
${date:format=yyyyMMdd}完全一致,否则无法正确识别过期目录。 - 定时时机:定时任务建议在系统低峰时段执行,减少资源占用。
内容的提问来源于stack exchange,提问作者Akbar Badhusha
相关产品推荐
相关产品推荐

