Как отключить создание пустого файла журнала при запуске приложения? - PullRequest
15 голосов
/ 28 марта 2010

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

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

Ответы [ 7 ]

14 голосов
/ 11 февраля 2011

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

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

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

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

7 голосов
/ 29 августа 2012

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

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

Мы решили эту проблему, создав следующий пользовательский класс 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 и проверка длины файла будут вызываться после каждого события журнала, которое записывается в файл журнала. Используйте его только в том случае, если ожидается, что ошибок будет очень мало, и это бизнес-требование, чтобы файл журнала не существовал при отсутствии ошибок.
  • Файлы журнала создаются и удаляются, когда они пусты. Это может быть проблемой, если у вас есть другие инструменты, отслеживающие каталог журналов на предмет изменений файловой системы. Однако в нашей ситуации это не было проблемой.
4 голосов
/ 29 февраля 2016

Следующее сработало для меня. Первый вызов 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 () вызывает виртуальный PrepareWriter , если файл еще не открыт.
  • PrepareWriter () FileAppender вызывает SafeOpenFile (), который inturn вызывает OpenFile ()
3 голосов
/ 28 марта 2010

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

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

2 голосов
/ 09 февраля 2012

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

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

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

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

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

0 голосов
/ 09 октября 2014

Метод 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
0 голосов
/ 16 октября 2013
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;
    }
}
...