创建基于日期的Log4net滚动文件

时间:2019-02-25 12:33:00

标签: date dynamic log4net

我需要为45个单独的位置创建文件(例如:波士顿,伦敦等)。这些文件名必须基于日期。另外,我可以提供要滚动的最大文件大小和要滚动的最大文件数。

基本上文件名必须类似于:Info_Boston_(2019.02.25).txt

到目前为止,我想出了以下代码来按日期获取。但是我不能将文件大小限制为1MB。该文件的大小超过1MB,并且不会创建新的滚动文件。请协助

    <appender name="MyAppenderInfo" type="log4net.Appender.RollingFileAppender">
  <param name="File" value="C:\\ProgramData\\Service\\Org\\Info"/>
  <param name="RollingStyle" value="Date"/>
  <param name="DatePattern" value="_(yyyy.MM.dd).\tx\t"/>
  <param name="StaticLogFileName" value="false"/>
  <maxSizeRollBackups value="10" />
  <maximumFileSize value="1MB" />
  <appendToFile value="true" />
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date %message%n" />
  </layout>
  <filter type="log4net.Filter.LevelRangeFilter">
    <levelMin value="DEBUG" />
    <levelMax value="INFO" />
  </filter>
</appender>

1 个答案:

答案 0 :(得分:0)

要解决您的特定帖子,我不会使用基于配置的方法来执行此操作,因为我认为它会很麻烦地进行管理。一种更具编程性的方法是动态生成日志记录实例。

编辑:我删除了原件,以根据此SO帖子log4net: different logs on different file appenders at runtime

来发布此修改后的示例。

EDIT-2:我不得不再次进行此修改,因为我意识到我省略了一些必需的部分,并且在修改之后出现了一些错误。这已经过测试并且可以正常工作。但是,需要注意一些事项,您将需要在控制器上为您创建的日志记录类提供using语句。接下来,您将需要像我一样在自己的日志目录中创建DI,或者想出另一种提供日志文件输出列表的方法。

这将使您可以非常干净地动态生成所需的任意数量的日志记录实例,并生成任意数量的独立位置。我从所做的项目中提取了此示例,并对其进行了一些修改以满足您的需求。让我知道你是否有疑问。

创建一个动态记录器类,该类继承自层次结构中的基本记录器:

using log4net;
using log4net.Repository.Hierarchy;

public sealed class DynamicLogger : Logger
{
    private const string REPOSITORY_NAME = "somename";
    internal DynamicLogger(string name) : base(name)
    {
        try
        {
            // try and find an existing repository
            base.Hierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository(REPOSITORY_NAME);
        }   // try
        catch
        {
            // it doesnt exist, make it.
            base.Hierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.CreateRepository(REPOSITORY_NAME);
        }   // catch
    }   // ctor(string)
}   // DynamicLogger

然后,构建一个类来管理日志记录实例,并构建新的记录器:

using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Filter;
using log4net.Layout;
using log4net.Repository;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;

public class LogFactory
{
    private static List<ILog> _Loggers = new List<ILog>();
    private static LoggingConfig _Settings;
    private static ILoggerRepository _Repository;

    public LogFactory(IOptions<LoggingConfig> configuration)
    {
        _Settings = configuration.Value;
        ConfigureRepository(REPOSITORY_NAME);
    }   // ctor(IOptions<LoggingConfig>)

    /// <summary>
    /// Configures the primary logging repository.
    /// </summary>
    /// <param name="repositoryName">The name of the repository.</param>
    private void ConfigureRepository(string repositoryName)
    {
        if(_Repository == null)
        {
            try
            {
                _Repository = LogManager.CreateRepository(repositoryName);
            }
            catch
            {
                // repository already exists.
                _Repository = LogManager.GetRepository(repositoryName);
            }   // catch
        }   // if
    }   // ConfigureRepository(string)

    /// <summary>
    /// Gets a named logging instance, if it exists, and creates it if it doesnt.
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public ILog GetLogger(string name)
    {
        string filePath = string.Empty;

        switch (name)
        {
            case "core":
                filePath = _Settings.CoreLoggingDirectory;
                break;
            case "image":
                filePath = _Settings.ImageProcessorLoggingDirectory;
                break;
        }   // switch

        if (_Loggers.SingleOrDefault(a => a.Logger.Name == name) == null)
        {
            BuildLogger(name, filePath);
        }   // if

        return _Loggers.SingleOrDefault(a => a.Logger.Name == name);
    }   // GetLogger(string)

    /// <summary>
    /// Dynamically build a new logging instance.
    /// </summary>
    /// <param name="name">The name of the logger (Not file name)</param>
    /// <param name="filePath">The file path you want to log to.</param>
    /// <returns></returns>
    private ILog BuildLogger(string name, string filePath)
    {
        // Create a new filter to include all logging levels, debug, info, error, etc.
        var filter = new LevelMatchFilter();
        filter.LevelToMatch = Level.All;
        filter.ActivateOptions();

        // Create a new pattern layout to determine the format of the log entry.
        var pattern = new PatternLayout("%d %-5p %c %m%n");
        pattern.ActivateOptions();

        // Dynamic logger inherits from the hierarchy logger object, allowing us to create dynamically generated logging instances.
        var logger = new DynamicLogger(name);
        logger.Level = Level.All;

        // Create a new rolling file appender
        var rollingAppender = new RollingFileAppender();
        // ensures it will not create a new file each time it is called.
        rollingAppender.AppendToFile = true;
        rollingAppender.Name = name;
        rollingAppender.File = filePath;
        rollingAppender.Layout = pattern;
        rollingAppender.AddFilter(filter);
        // allows us to dynamically generate the file name, ie C:\temp\log_{date}.log
        rollingAppender.StaticLogFileName = false;
        // ensures that the file extension is not lost in the renaming for the rolling file
        rollingAppender.PreserveLogFileNameExtension = true;
        rollingAppender.DatePattern = "yyyy-MM-dd";
        rollingAppender.RollingStyle = RollingFileAppender.RollingMode.Date;
        // must be called on all attached objects before the logger can use it.
        rollingAppender.ActivateOptions();
        logger.AddAppender(rollingAppender);

        // Sets the logger to not inherit old appenders, or the core appender.
        logger.Additivity = false;
        // sets the loggers effective level, determining what level it will catch log requests for and log them appropriately.
        logger.Level = Level.Info;
        // ensures the new logger does not inherit the appenders of the previous loggers.
        logger.Additivity = false;

        // The very last thing that we need to do is tell the repository it is configured, so it can bind the values.
        _Repository.Configured = true;

        // bind the values.
        BasicConfigurator.Configure(_Repository, rollingAppender);

        LogImpl newLog = new LogImpl(logger);


        _Loggers.Add(newLog);

        return newLog;
    }   // BuildLogger(string, string)
}   // LogFactory

然后,在依赖注入中,您可以注入日志工厂。您可以使用以下方法做到这一点:

services.AddSingleton<LogFactory>();

然后在您的控制器或任何实际的构造函数中,您可以执行以下操作:

    private LogFactory _LogFactory;

    public HomeController(LogFactory logFactory){
        _LogFactory = logFactory;
    }

    public async Task<IActionResult> Index()
    {
        ILog logger1 = _LogFactory.GetLogger("core");
        ILog logger2 = _LogFactory.GetLogger("image");
        logger1.Info("SomethingHappened on logger 1");
        logger2.Info("SomethingHappened on logger 2");
        return View();
    }

此示例将输出:

2019-03-07 10:41:21,338 INFO  core SomethingHappened on logger 1

在自己的名为Core_2019-03-07.log

的文件中

还有:

2019-03-07 11:06:29,155 INFO  image SomethingHappened on logger 2

在自己的名为Image_2019-03-07

的文件中

希望更有意义!