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

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

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

Ответы

Ответ 1

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

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" />

Я использую это с скользящим файловым приложением.

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

Ответ 2

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

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

Мы решили это, создав следующий пользовательский класс 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, гарантируя, что ведение журнала работает до того, как начнется остальная часть приложения. Однако файл журнала немедленно удаляется.
  • Не требуется отключать ведение журнала в вашем конфигурационном файле, установив пороговое значение в положение "ВЫКЛ", а позже включите ведение журнала программно, прежде чем записывать свое первое событие журнала.

против

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

Ответ 3

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

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

Ответ 4

Следующие выполняли для меня. Первый вызов 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.
  • Когда создается сообщение журнала, AppenderSkeleton DoAppend() вызывает PreAppendCheck()
  • PreAppendCheck() переопределяется в TextWriterAppender, базе FileAppender.
  • Переопределенный PreAppendCheck() вызывает виртуальный PrepareWriter , если файл еще не открыт.
  • PrepareWriter() FileAppender вызывает SafeOpenFile(), который вызывает вызовы OpenFile()

Ответ 5

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

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

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 с атрибутом сборки, который автоматически настраивает журнал (таким образом создавая файл журнала) и простой getter для журнала:

[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);

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

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

Ответ 6

Метод 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 empty
  var f = new FileInfo(filename);
  if (f.Exists && f.Length <= 0)
  {
    f.Delete();
  }
} // RemoveEmptyLogFile

Ответ 7

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;
    }
}