Как отключить создание пустого файла журнала при запуске приложения?

Я успешно настроил log4net в своем приложении, но одна вещь немного раздражает меня.

файл журнала создается (пустой) после запуска моего приложения, даже если ошибка не возникает. Я хотел бы, чтобы файл журнала был создан только после некоторой ошибки.

7 ответов


Я действительно нашел способ сделать это в этой теме:

http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/postid/18271/view/topic/Default.aspx

я протестировал первый метод, и он работает. На всякий случай, если эта ссылка больше не будет хорошей, я воспроизведу код здесь. В основном автор утверждает, что есть два способа сделать это.

Первый способ:

создайте новую модель блокировки, которая получает только блокировку (и создает файл) , если соответствующий порог для этого регистратора работает.

public class MyLock : log4net.Appender.FileAppender.MinimalLock
{
      public override Stream AcquireLock()
      {
            if (CurrentAppender.Threshold == log4net.Core.Level.Off)
                  return null;

            return base.AcquireLock();
      }
}

Теперь в файле конфигурации установите порог, чтобы начать как:

<threshold value="OFF" />

и убедитесь, что вы установили эту новую LockingModel как модель:

<lockingModel type="Namespace.MyLock" />

Я использую это с rolling file appender.

второй метод указан по ссылке. Я не пробовал эту технику, но она кажется технически обоснованной.


Я знаю, это старый вопрос, но я думаю это может быть полезно для кого-то другого.

мы столкнулись с аналогичной ситуацией, когда требовалось, чтобы приложение не оставляло пустой файл журнала, если никаких ошибок не произошло.

мы решили это, создав следующий пользовательский класс LockingModel:

public class MinimalLockDeleteEmpty : FileAppender.MinimalLock
{
    public override void ReleaseLock()
    {
        base.ReleaseLock();

        var logFile = new FileInfo(CurrentAppender.File);
        if (logFile.Exists && logFile.Length <= 0)
        {
            logFile.Delete();
        }
    }
}

он является производным от FileAppender.Класс MinimalLock, который освободит блокировку файла журнала после записи каждого журнала сообщение.

мы добавили дополнительные функции, которые удалят файл журнала, если он все еще пуст после освобождения блокировки. Это предотвращает приложение от оставления пустых файлов журнала ошибок, если приложения работает и выходит без каких-либо ошибок.

плюсы

  • он по-прежнему будет создавать пустой файл журнала на этапе конфигурации Log4Net, гарантируя, что ведение журнала работает до запуска остальной части приложения. Однако файл журнала удаляется немедленно.
  • он не требует, чтобы вы отключили вход в файл конфигурации, установив пороговое значение "OFF" и, чем позже, включите ведение журнала программно перед записью первого события журнала.

минусы

  • это, скорее всего, медленный метод управления файлами журнала, потому что метод ReleaseLock и проверка длины файла будут вызываться после каждый событие журнала, записанное в файл журнала. Используйте его только тогда, когда ожидается очень мало ошибок, и это бизнес-требование, чтобы файл журнала не существовал, когда ошибок нет.
  • файлы журнала создаются и удаляются, когда пустые. Это может быть проблемой, если у вас есть другие инструменты мониторинга каталога журналов для изменения файловой системы. Однако в нашей ситуации это не было проблемой.

проблема с этим подходом заключается в том, что тогда, если файл существует, но доступен только для чтения, или находится в каталоге, который не существует и т. д., Вы не узнаете, пока другая ошибка не вызовет проблемы. Вы действительно хотите быть уверены, что регистрация работает до запуска приложения.

здесь мая быть способом сделать это в любом случае, но если нет, я подозреваю, что это причина.


следующее сработало для меня.Первый вызов OpenFile () происходит при настройке регистратора. Последующие вызовы-это когда создается фактическое сообщение журнала.

class CustomFileAppender : RollingFileAppender
{
    private bool isFirstTime = true;
    protected override void OpenFile(string fileName, bool append)
    {
        if (isFirstTime)
        {
            isFirstTime = false;
            return;
        }

        base.OpenFile(fileName, append);
    }

}

и в конфигурационном файле измените appender

<log4net>
<appender name="RollingFile" type="<your namespace>.CustomFileAppender">
...
</log4net>

последовательность из источника log4Net выглядит следующим образом:


  • первый вызов OpenFile() из-за ActivateOptions () вызывается из конструктора FileAppender.
  • при входе сообщение генерируется, DoAppend() AppenderSkeleton вызывает PreAppendCheck()
  • PreAppendCheck () переопределяется в TextWriterAppender, базе FileAppender.
  • переопределенный PreAppendCheck () вызывает virtual PrepareWriter если файл еще не открыт.
  • PrepareWriter() FileAppender вызывает SafeOpenFile (), который inturn вызывает OpenFile ()

другой довольно простой метод описан в это сообщение архива списка рассылки

в основном, с log4net, файл журнала создается, когда регистратор настроен. Чтобы настроить его, чтобы сделать иначе, немного hacky. Решение отложить выполнение конфигурации. В приведенном выше сообщении предлагается сделать следующее При настройке регистратора:

private static ILog _log = LogManager.GetLogger(typeof(Program));
public static ILog Log
{
    get
    {
        if(!log4net.LogManager.GetRepository().Configured)
            log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
        return _log;
    }
}

обычно я настраиваю log4net с помощью сборка атрибут, который настраивает регистратор автоматически (таким образом, создавая файл журнала), и простой геттер для журнала:

[assembly: log4net.Config.XmlConfigurator(Watch = true)]
...
public static log4net.ILog Log { get { return _log; } }
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

но удаление этого и добавление в вышеуказанный геттер с дополнительной логикой вместо этого решили проблему для меня.

Примечание: В целом я согласен, что в большинстве случаев было бы лучше, чтобы настроить регистратор и создать файл (и даже писать) при запуске приложения.


метод AcquireLock и ReleaseLock работал для меня, но меня беспокоило, что файл был создан/удален столько раз. Вот еще один аналогичный параметр, который выключает регистратор и удаляет пустой файл журнала по завершении программы. Просто вызовите RemoveEmptyLogFile, когда вы закончите ведение журнала.

/// <summary>
/// Sets the logging level for log4net.
/// </summary>
private static void RemoveEmptyLogFile()
{
  //Get the logfilename before we shut it down
  log4net.Appender.FileAppender rootAppender = (log4net.Appender.FileAppender)((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root.Appenders[0];
  string filename = rootAppender.File;

  //Shut down all of the repositories to release lock on logfile
  log4net.Repository.ILoggerRepository[] repositories = log4net.LogManager.GetAllRepositories();
  foreach (log4net.Repository.ILoggerRepository repository in repositories)
  {
    repository.Shutdown();
  }

  //Delete log file if it's empty
  var f = new FileInfo(filename);
  if (f.Exists && f.Length <= 0)
  {
    f.Delete();
  }
} // RemoveEmptyLogFile

private static ILog _log = LogManager.GetLogger(typeof(Program));
public static ILog Log
{
    get
    {
        if(!log4net.LogManager.GetRepository().Configured)
        log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
        return _log;
    }
}