You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:10:09