Подтвердить что ты не робот

Должен ли я объявлять log4net logger один раз для каждого класса или базового класса?

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

хотя может быть несколько проще:

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Изменить: теперь он стал потокобезопасным, спасибо за комментарии.

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

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

Ответ 5

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

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 может быть подвергнут производным классам, чтобы они могли самостоятельно вести журнал.