Должен ли я объявить log4net logger один раз для каждого класса или в базовом классе? - PullRequest
21 голосов
/ 31 января 2012

Кажется более понятным объявить регистратор и вызвать LogManager.GetLogger в базовом классе, чтобы его могли использовать все, кто наследует.Однако на сайте log4net и в других блогах, таких как в этом сообщении , говорится, что лучше объявить по одному регистратору на класс, потому что:

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

Означает ли это, что если я помещу его в базовый класс, это сделает этот регистратор узким местом?

Если да, есть ли другие решения или мне просто нужно создать регистратор для каждого класса?

Ответы [ 5 ]

23 голосов
/ 31 января 2012

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

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

Кроме того, статья создает экземпляр регистратора следующим образом:

static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType );

, в то время как можно использовать несколько более простой способ:

static readonly ILog Log = LogManager.GetLogger(typeof(YourClass));

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

5 голосов
/ 31 января 2012

Обычная практика - иметь одного регистратора на класс, а НЕ базовый класс.Таким образом, вы можете включить / отключить ведение журнала для каждого класса.

Я также мог бы предложить рассмотреть использование Common Logging 2.0, http://netcommon.sourceforge.net/.

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

Библиотека Common.Logging представляет простую абстракцию, позволяющую выбрать конкретныйведение журнала во время выполнения.Таким образом, вы можете отложить принятие решения о том, какую именно библиотеку журналов использовать до развертывания.Адаптеры используются для подключения конкретной системы ведения журнала к Common.Logging.

1 голос
/ 31 января 2012

Предоставленное утверждение не относится к узким местам.Объявление вашего регистратора в базовом классе ограничивает контроль над ведением журнала в производных классах.Если у вас есть классы A и B, происходящие из одного и того же базового класса, содержащего регистратор, вы застряли с одинаковыми настройками журналирования для всех журналов, выполненных в классах A и B.

log4net позволяет вам настроить регистраторы на основекласс или пространство имен, для которого они созданы, что дает вам очень жесткий контроль над тем, что регистрируется.Например, наличие журнала класса A на информационном уровне и журнала класса B на уровне отладки.

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

0 голосов
/ 04 февраля 2014

Я использую статический словарь в базовом классе, используя имя типа:

private static readonly Dictionary<string, ILog> _loggers = new Dictionary<string, ILog>();

С методом (в базовом классе), чтобы вернуть регистратор:

    private ILog GetLogger(){
        var tn = this.GetType().FullName;
        if (!_loggers.ContainsKey(tn)) {
            _loggers.Add(tn,LogManager.GetLogger(this.GetType()));
        }
        return _loggers[tn];
    }

У меня также есть методы ведения журнала в базовом классе:

    public void Log(string msg, params object[] args) {
        GetLogger().InfoFormat(msg, args);
    }

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

0 голосов
/ 31 января 2012

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

Редактировать: теперь это стало безопасным, спасибо за комментарии.

    public class Logger
    { 
      private static object syncRoot = new Object();
      private static Logger instance=null;
      // private constructor
      private Logger()
      {
      }
      /// <summary>
    /// Gets an instance with default parameters based upon the caller
    /// </summary>
    /// <returns></returns>
    public static Logger GetInstance()
    {
       // make sure you return single instance
       if (instance == null)
        {
           lock (syncRoot) 
           { 
            instance=new Logger();
           } 
        }
        return instance;
    }
   }

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...