【问题标题】:Log4Net: set Max backup files on RollingFileAppender with rolling DateLog4Net:使用滚动日期在 RollingFileAppender 上设置最大备份文件
【发布时间】:2008-09-18 18:24:06
【问题描述】:

我有以下配置,但我找不到任何关于如何设置日期滚动样式的最大备份文件的文档。我知道您可以使用 maxSizeRollBackups 以大小滚动样式来做到这一点。

<appender name="AppLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="mylog.log" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <rollingStyle value="Date" />
    <datePattern value=".yyMMdd.'log'" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%d %-5p %c - %m%n"  />
    </layout>
</appender>

【问题讨论】:

  • +1 正是我要找的东西

标签: .net log4net


【解决方案1】:

你不能。

来自 log4net SDK Reference
RollingFileAppender Class

注意

不支持在日期/时间边界滚动时的最大备份文件数。

【讨论】:

【解决方案2】:

尽管不支持,但我是这样处理这种情况的:

这是我的配置:

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
        <file value="C:\logs\LoggingTest\logfile.txt" />
        <appendToFile value="true" />
        <rollingStyle value="Composite" />
        <datePattern value="yyyyMMdd" />
        <maxSizeRollBackups value="10" />
        <maximumFileSize value="1MB" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date  - %message%newline" />
        </layout>
    </appender>

在应用程序启动时我会这样做:

 XmlConfigurator.Configure();
 var date = DateTime.Now.AddDays(-10);
 var task = new LogFileCleanupTask();
 task.CleanUp(date);

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using log4net;
using log4net.Appender;
using log4net.Config;

    public class LogFileCleanupTask
    {
        #region - Constructor -
        public LogFileCleanupTask()
        {
        }
        #endregion

        #region - Methods -
        /// <summary>
        /// Cleans up. Auto configures the cleanup based on the log4net configuration
        /// </summary>
        /// <param name="date">Anything prior will not be kept.</param>
        public void CleanUp(DateTime date)
        {
            string directory = string.Empty;
            string filePrefix = string.Empty;

            var repo = LogManager.GetAllRepositories().FirstOrDefault(); ;
            if (repo == null)
                throw new NotSupportedException("Log4Net has not been configured yet.");

            var app = repo.GetAppenders().Where(x => x.GetType() == typeof(RollingFileAppender)).FirstOrDefault();
            if (app != null)
            {
                var appender = app as RollingFileAppender;

                directory = Path.GetDirectoryName(appender.File);
                filePrefix = Path.GetFileName(appender.File);

                CleanUp(directory, filePrefix, date);
            }
        }

        /// <summary>
        /// Cleans up.
        /// </summary>
        /// <param name="logDirectory">The log directory.</param>
        /// <param name="logPrefix">The log prefix. Example: logfile dont include the file extension.</param>
        /// <param name="date">Anything prior will not be kept.</param>
        public void CleanUp(string logDirectory, string logPrefix, DateTime date)
        {
            if (string.IsNullOrEmpty(logDirectory))
                throw new ArgumentException("logDirectory is missing");

            if (string.IsNullOrEmpty(logPrefix))
                throw new ArgumentException("logPrefix is missing");

            var dirInfo = new DirectoryInfo(logDirectory);
            if (!dirInfo.Exists)
                return;

            var fileInfos = dirInfo.GetFiles("{0}*.*".Sub(logPrefix));
            if (fileInfos.Length == 0)
                return;

            foreach (var info in fileInfos)
            {
                if (info.CreationTime < date)
                {
                    info.Delete();
                }
            }

        }
        #endregion
    }

Sub 方法是一个扩展方法,它基本上是这样包装 string.format 的:

/// <summary>
/// Extension helper methods for strings
/// </summary>
[DebuggerStepThrough, DebuggerNonUserCode]
public static class StringExtensions
{
    /// <summary>
    /// Formats a string using the <paramref name="format"/> and <paramref name="args"/>.
    /// </summary>
    /// <param name="format">The format.</param>
    /// <param name="args">The args.</param>
    /// <returns>A string with the format placeholders replaced by the args.</returns>
    public static string Sub(this string format, params object[] args)
    {
        return string.Format(format, args);
    }
}

【讨论】:

  • 值得注意的是,“创建日期”可能因此不可靠 - stackoverflow.com/questions/2109152/…
  • 另外值得注意的是,只有满足以下两个条件,该类才能正常工作:1)StaticLogFileName 设置为 true。 2) preserveLogFileNameExtension 设置为 false.
【解决方案3】:

要限制日志的数量,请不要在日期模式中包含年份或月份,例如datePattern value="_dd'.log'"

这将每天创建一个新日志,并在下个月被覆盖。

【讨论】:

  • 这听起来很简单有趣,但我看到了以下问题——每次应用重启都会覆盖当天的现有文件。或者,如果您将其配置为不覆盖文件,而是追加 - 文件将无限增长。你如何准确地配置它?
  • @LukasK 如果您将rollingStyle 设置为复合、maximumFileSizemaxSizeRollbackups,那么您可以限制每个文件的大小。但是,如果一个月内第 6 天有 3 次翻转,而下个月只有 2 次,这可能会令人困惑。上个月的“_06.3”翻转将与当月混合。
【解决方案4】:

几个月前我花了一些时间研究这个问题。 v1.2.10 不支持根据日期滚动删除较旧的日志文件。它在下一个版本的任务列表中。我自己拿了源代码并添加了功能,如果他们有兴趣,我会把它发布给其他人。问题和补丁可以在https://issues.apache.org/jira/browse/LOG4NET-27 找到。

【讨论】:

  • 如何使用它?是否必须下载 log4net 源代码,添加它,然后重新编译并获取新的程序集文件?
  • 据我所知,是的
【解决方案5】:

不确定您到底需要什么。以下是我的 lo4net.config 文件之一的摘录:

  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="App_Data\log"/>
    <param name="DatePattern" value=".yyyy-MM-dd-tt&quot;.log&quot;"/>
    <param name="AppendToFile" value="true"/>
    <param name="RollingStyle" value="Date"/>
    <param name="StaticLogFileName" value="false"/>
    <param name="maxSizeRollBackups" value="60" />
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%r %d [%t] %-5p %c - %m%n"/>
    </layout>
  </appender>

【讨论】:

  • 不知道为什么投反对票。它被认为是解释原因的好形式,以便我们都可以学习。
  • 似乎没有抓住问题的重点。 maxSizeRollBackups 不允许您例如删除超过 10 天的文件。我相信这就是 OP 正在努力实现的目标。
  • 我认为你是对的,这就是 OP 想要的。我有点不清楚他当时想要完成什么。我的回答很简单,并试图向他展示我的代码。我仍然会以同样的方式回答问题以提供帮助,但我可以看到你的反对意见来自哪里。
【解决方案6】:

我最近在尝试根据传递给我的服务的 maxAgeInDays 配置值清理日志日志时遇到了这种需求...正如我之前的许多人一样,我接触到了 NTFS“功能”隧道,这使得使用 FileInfo .CreationDate 有问题(尽管我也已经解决了这个问题)......

由于我有一个模式要摆脱,我决定只推出自己的清理方法...我的记录器是通过编程方式配置的,所以我只需在记录器设置完成后调用以下命令...

    //.........................
    //Log Config Stuff Above...

    log4net.Config.BasicConfigurator.Configure(fileAppender);
    if(logConfig.DaysToKeep > 0)
       CleanupLogs(logConfig.LogFilePath, logConfig.DaysToKeep);
}

static void CleanupLogs(string logPath, int maxAgeInDays)
{
    if (File.Exists(logPath))
    {
        var datePattern = "yyyy.MM.dd";
        List<string> logPatternsToKeep = new List<string>();
        for (var i = 0; i <= maxAgeInDays; i++)
        {
            logPatternsToKeep.Add(DateTime.Now.AddDays(-i).ToString(datePattern));
        }

        FileInfo fi = new FileInfo(logPath);

        var logFiles = fi.Directory.GetFiles(fi.Name + "*")
            .Where(x => logPatternsToKeep.All(y => !x.Name.Contains(y) && x.Name != fi.Name));

        foreach (var log in logFiles)
        {
            if (File.Exists(log.FullName)) File.Delete(log.FullName);
        }
    }
}

可能不是最漂亮的方法,但对我们的目的来说工作得很好......

【讨论】:

    【解决方案7】:

    NLog 的设置方式与 Log4Net 几乎相同(并且正在积极维护 - 甚至支持 .NET Core),支持基于日期滚动日志。

    【讨论】:

    • 你能举个例子吗?我在其WIKI 中找不到如何配置它
    【解决方案8】:

    从 log4net appender 继承并添加你自己的覆盖方法来执行文件清理是相当容易的。我覆盖了 OpenFile 来执行此操作。这是一个自定义 log4net 附加程序的示例,可帮助您入门:https://stackoverflow.com/a/2385874/74585

    【讨论】:

      【解决方案9】:

      不再担心每个日期更复杂的 x 和只是指定和任意文件计数,只是将这个放在一起。小心 [SecurityAction.Demand]

      public string LogPath { get; set; }
      public int MaxFileCount { get; set; } = 10;
      
      private FileSystemWatcher _fileSystemWatcher;
      
      [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
      public async Task StartAsync()
      {
          await Task.Yield();
      
          if (!Directory.Exists(LogPath))
          { Directory.CreateDirectory(LogPath); }
      
          _fileSystemWatcher = new FileSystemWatcher
          {
              Filter = "*.*",
              Path = LogPath,
              EnableRaisingEvents = true,
              NotifyFilter = NotifyFilters.FileName
                  | NotifyFilters.LastAccess
                  | NotifyFilters.LastWrite
                  | NotifyFilters.Security
                  | NotifyFilters.Size
          };
      
          _fileSystemWatcher.Created += OnCreated;
      }
      
      public async Task StopAsync()
      {
          await Task.Yield();
      
          _fileSystemWatcher.Created -= OnCreated; // prevents a resource / memory leak.
          _fileSystemWatcher = null; // not using dispose allows us to re-start if necessary.
      }
      
      private void OnCreated(object sender, FileSystemEventArgs e)
      {
          var fileInfos = Directory
              .GetFiles(LogPath)
              .Select(filePath => new FileInfo(filePath))
              .OrderBy(fileInfo => fileInfo.LastWriteTime)
              .ToArray();
      
          if (fileInfos.Length <= MaxFileCount)
          { return; }
      
          // For every file (over MaxFileCount) delete, starting with the oldest file.
          for (var i = 0; i < fileInfos.Length - MaxFileCount; i++)
          {
              try
              {
                  fileInfos[i].Delete();
              }
              catch (Exception ex)
              {
                  /* Handle */
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-19
        • 2015-03-10
        • 1970-01-01
        • 1970-01-01
        • 2016-11-08
        • 1970-01-01
        • 2013-11-06
        • 1970-01-01
        相关资源
        最近更新 更多