NLog配置maxArchiveDays后无法自动删除旧归档文件夹问题
NLog归档文件夹无法自动删除的解决办法
你的NLog File目标配置如下:
<target xsi:type="File" async="true" name="jsonFileTrace" keepFileOpen="true" OpenFileCacheTimeout="60" archiveAboveSize="5242880" maxArchiveFiles="20" maxArchiveDays="10" archiveNumbering="DateAndSequence" AutoFlush="false" openFileFlushTimeout="5" ConcurrentWrites="false" archiveFileName="${basedir}/logs/trace/archive/${shortdate}/trace.{#}.log" fileName="${basedir}/logs/trace/${shortdate}.log"> <layout xsi:type="JsonLayout" includeAllProperties="true"> <attribute name="time" layout="${longdate}" /> .......//other attributes </layout> </target>
问题原因
maxArchiveDays参数仅负责自动删除过期的归档文件,不会处理归档文件所在的日期文件夹。因为你把${shortdate}放在了归档路径的文件夹层级里,NLog只会扫描文件夹内的文件是否过期并删除,不会识别路径中的日期来删除整个文件夹。
解决办法
方法1:调整归档路径结构(推荐)
把日期从文件夹层级移到文件名里,让NLog能直接识别并清理过期文件,同时无需手动维护文件夹:
修改archiveFileName为:
archiveFileName="${basedir}/logs/trace/archive/trace.${shortdate}.{#}.log"
所有归档文件会直接放在archive目录下,文件名包含日期和序列号,NLog会自动删除超过10天的文件,不需要额外处理。
方法2:保留日期文件夹,手动实现清理逻辑
如果必须按日期分文件夹归档,需要自己添加定时清理逻辑:
- 在应用中添加定时任务(比如.NET里用
IHostedService),定期扫描${basedir}/logs/trace/archive目录下的子文件夹。 - 解析文件夹名称(比如
2022-09-20),判断是否超过10天,若是则删除整个文件夹及其内部文件。
示例代码(.NET 6+):
using System.Globalization; using System.IO; public class LogCleanupService : BackgroundService { private readonly string _archiveDir = Path.Combine(AppContext.BaseDirectory, "logs", "trace", "archive"); private readonly int _maxArchiveDays = 10; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { CleanupOldFolders(); // 每天执行一次清理 await Task.Delay(TimeSpan.FromDays(1), stoppingToken); } } private void CleanupOldFolders() { if (!Directory.Exists(_archiveDir)) return; var cutoffDate = DateTime.Now.AddDays(-_maxArchiveDays); foreach (var folder in Directory.GetDirectories(_archiveDir)) { var folderName = Path.GetFileName(folder); if (DateTime.TryParseExact(folderName, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var folderDate)) { if (folderDate < cutoffDate) { try { Directory.Delete(folder, recursive: true); } catch (Exception ex) { // 记录删除失败的日志,避免影响其他逻辑 Console.WriteLine($"Failed to delete old log folder {folder}: {ex.Message}"); } } } } } }
记得在Program.cs里注册这个服务:
builder.Services.AddHostedService<LogCleanupService>();
内容的提问来源于stack exchange,提问作者user17785356
相关产品推荐
相关产品推荐

