为什么记录到log4net.ILog追加到多个日志?

时间:2018-09-05 11:54:40

标签: c# log4net

我正在为第三方应用程序开发一个插件,为此插件的每个“运行”都需要一个独占日志文件。

我建立了以下课程。

public class LogFileRepository
{
    private readonly Common.Configuration.Settings _configSettings;
    private const string InstanceName = "AutomationPlugin.Logging";
    private readonly ILoggerRepository _repository;


    public LogFileRepository (Common.Configuration.Settings configSettings)
    {
        _configSettings = configSettings;

        var repositoryName = $"{InstanceName}.Repository";
        _repository = LoggerManager.CreateRepository(repositoryName);
    }


    public ILog GetLog(string name)
    {
        var logger = LogManager.Exists(_repository.Name, name);
        if (logger != null)
        {
            return logger;
        }

        var filter = new LevelMatchFilter {LevelToMatch = Level.All};
        filter.ActivateOptions();
        var appender = new RollingFileAppender
                       {
                           AppendToFile = false,
                           DatePattern = "yyyy-MM-dd",
                           File = String.Format(_configSettings.Paths.LogFileTemplate, name),
                           ImmediateFlush = true,
                           Layout = new PatternLayout("%n%date{ABSOLUTE} | %-7p | %m"),
                           LockingModel = new FileAppender.MinimalLock(),
                           MaxSizeRollBackups = 1,
                           Name = $"{InstanceName}.{name}.Appender",
                           PreserveLogFileNameExtension = false,
                           RollingStyle = RollingFileAppender.RollingMode.Once
                       };
        appender.AddFilter(filter);
        appender.ActivateOptions();

        BasicConfigurator.Configure(_repository, appender);

        return LogManager.GetLogger(_repository.Name, name);
    }
}

此功能的目的是使GetLog方法返回一个日志文件(具有指定名称)(如果LogManager已经存在);如果没有现有的日志文件,则应实例化并返回它。

确实发生。在第一次运行插件时,将创建一个日志文件并将其写入;在插件的第二次运行中,将创建一个新的日志文件并将其写入,但所有消息也会写入第一个日志文件。在第三次运行时,所有消息都将写入新的第三个日志文件中。

为什么? RollingFileAppender中是否有我似乎误解/错误配置的内容?我需要每个name参数的独占日志文件。

1 个答案:

答案 0 :(得分:2)

假设您使用_repository创建了LogManager.CreateRepository(),则实际上创建了一个Hierarchy,并且当您通过BasicConfigurator.Configure(_repository, appender);用新的附加程序配置它时,会将附加程序添加到层次结构的Root附加程序集合。

然后从存储库中创建的所有记录器都是“根”的子记录器,并且被配置为“加性”,因为它们会附加到直接针对它们,其父级定义的所有附加器中记录器,一直到根。在您的情况下,记录器本身没有自己的附加器,因此只是从Root中拾取附加器,而Root在您的情况下包含 all 个附加器。结果,所有消息都会记录到每个文件中。

您要做的是将附加程序附加到其特定的记录器,并禁用可加性,这样它就不会再登录到层次结构中较高的附加程序。似乎没有一种“不错”的方法来执行此操作,但是以下在我的测试中起作用:

...
appender.AddFilter(filter);
appender.ActivateOptions();

// Add the appender directly to the logger and prevent it picking up parent appenders
if (LoggerManager.GetLogger(_repository.Name, name) is Logger loggerImpl)
{
    loggerImpl.Additivity = false;
    loggerImpl.AddAppender(appender);
}

BasicConfigurator.Configure(_repository, appender);
return LogManager.GetLogger(_repository.Name, name);
相关问题