У меня возникла проблема с log4net в отношении использования скользящего приложения. Когда у нас есть несколько потоков, мы создаем RollingAppender для записи сообщений в файл журнала по умолчанию, а также в файл журнала для конкретного задания. Мы устанавливаем PropertyFilter в RollingAppender с guid в качестве ключа для используемого потока. Мы также устанавливаем для ThreadContext.Properties[key] тот же ключ.
Мы создаем Appender при запуске задания, затем удаляем Appender в блоке finally кода try/catch/finally.
Проблема в том, что регистратор случайным образом создает подпапки, содержащие AppName.log, а также первую часть фильтра DatePattern в пути к папке. Например, если DatePattern — yyyy\MM\'Today'\'{fileName}.log'", а AppName — SampleApp.exe, то мы случайным образом получим имя папки следующим образом:
SampleApp.log2022\11\Today\AppenderName.log.
Когда он делает это, он создает несколько папок, используя то же самое соглашение об именах. Таким образом, мы получаем такую структуру папок:
SampleApp.log2022\11\Today\SampleApp.log2022\11\Today\SampleApp.log2022\11\Today\SampleApp.log2022\11\Today\SampleApp.log2022\11\Today\AppenderName.log
Ясно, что это проблема.
Вот код приложения
public void CreateRollingFileAppender
(
string appenderName,
string fileName,
PropertyFilter filter = null,
string logPath = ""
)
{
if (logPath == "") logPath = _logConfiguration.LogPath;
if (Root.GetAppender(appenderName) != null) return;
var patternLayout = new PatternLayout(_logConfiguration.Appender.PatternLayout);
var denyAllFilter = new DenyAllFilter();
var appender = new RollingFileAppender
{
Name = appenderName,
File = logPath,
StaticLogFileName = false,
Layout = patternLayout,
ImmediateFlush = true,
AppendToFile = true,
MaxSizeRollBackups = 5,
MaximumFileSize = _logConfiguration.Appender.MaxSize,
RollingStyle = RollingFileAppender.RollingMode.Date,
DatePattern = $@"yyyy\\MM\\'Today'\\'{fileName}.log'",
LockingModel = new FileAppender.MinimalLock()
};
if (filter != null)
{
appender.AddFilter(filter);
appender.AddFilter(denyAllFilter);
}
appender.ActivateOptions();
BasicConfigurator.Configure(Repository, appender);
}
и вот код для создания фильтра, который мы используем:
public PropertyFilter CreateThreadFilter()
{
var guid = Guid.NewGuid().ToString();
ThreadContext.Properties[Key] = guid;
return new PropertyFilter
{
Key = Key,
StringToMatch = guid,
AcceptOnMatch = true
};
}
Вот код удаления приложения:
public void RemoveAppender(string appenderName)
{
var appender = Root.GetAppender(appenderName);
if (appender != null)
{
appender.Close();
Root.RemoveAppender(appenderName);
}
}
и вот пример вызова этого кода:
CreateRollingFileAppender("Test", "Test", CreateThreadFilter())
try
{
...
logger.Info(message);
}
catch (Exception e)
{
logger.Error(e)
}
finally
{
RemoveAppender("Test")
}
Мы определяем Repository и Root следующим образом:
var Repository = LogManager.CreateRepository(Assembly.GetEntryAssembly(), typeof(Hierarchy));
var Root is ((Hierarchy)Repository).Root
Пожалуйста, порекомендуйте.
Спасибо
Таким образом, проблема здесь была связана не с кодом, а с конфигурацией. Предыдущий разработчик использовал файл конфигурации для хранения свойств, используемых для создания любых файлов. Однако он оставил свойство File пустым в файле конфигурации. Поэтому при первом запуске у него не было свойства пути для создания файла.