我正在为第三方应用程序开发一个插件,为此插件的每个“运行”都需要一个独占日志文件。
我建立了以下课程。
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
参数的独占日志文件。
答案 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);