Каркас логирования внедряется в классы - PullRequest
4 голосов
/ 21 августа 2009

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

Ответы [ 6 ]

2 голосов
/ 21 августа 2009

Впрыск более гибок в долгосрочной перспективе, поскольку вы можете легко выборочно вводить в определенные места и выборочно отключать ведение журнала и т. Д.

1 голос
/ 21 августа 2009

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

Возьмите CommonLogging (см. этот ответ Stackoverflow для краткого описания того, что такое Common.Logging), например: Ваш класс общается напрямую с фабрикой (LoggerManager), но вы не привязан к конкретной реализации логгера.

1 голос
/ 21 августа 2009

Если производительность памяти не такая большая проблема, вы могли бы рассмотреть AOP, например используя PostSharp . Таким образом, ваши классы не должны знать регистратор вообще. Вы в основном вставляете IL-код прямо в вашу сборку как шаг пост-сборки. PostSharp использует атрибуты для маркировки методов, классов и даже целых сборок. Есть даже плагин для использования log4net для ведения журнала.

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

1 голос
/ 21 августа 2009

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

0 голосов
/ 16 августа 2010

CSharpAtl

Мне интересно, как именно вы вводите Log4net? Смотрите мой вопрос / сообщество вики здесь .

Я также видел ваш ответ на вопрос DI / Log4net здесь .

В большинстве примеров внедрения журналирования, которые я видел, показан класс с внедренным «регистратором», что-то вроде этого:

public class Foo
{
  private ILogger logger;

  public Foo(ILogger logger) //Injection via constructor
  {
    //Which "named" logger is this anyway?  Is it Foo's?  If so, how is it Foo's?
    this.logger = logger;
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

Используя что-то вроде Log4net (и NLog, а может и других), вы обычно создаете регистратор, подобный этому:

public class Foo
{
  private static ILogger logger = 
          LogManager.GetLogger(
              System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  public Foo()
  {
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

Итак, как мой класс, Foo, получает правильный логгер, если я ввожу зависимость? Кроме того, возможно я не называю свои регистраторы, основанные строго на классе. Скорее, я мог бы назвать их в зависимости от функциональной области (например, «DatabaseAccess», «AppStartup», «AppShutdown» и т. Д.), Которая может не быть производной от типа.

Вы вводите "Logger" (который соответствует названному logger) или "LogManager" (который соответствует LogManager Log4net), или вы делаете что-то еще? Используете ли вы возможность конфигурации платформы DI для связи «именованных экземпляров» внедренных зависимостей? Я думаю, что Unity поддерживает что-то вроде этого, хотя я не совсем уверен.

Вот как я мог бы представить введение LogManager:

public class Foo
{
  private static ILogger logger;

  public Foo(ILogManager logManager) //Injection via constructor
  {
    logger = logManager.GetLogger
                    (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    //Since logger is (should it be?) static, maybe should be like this:

    if (logger = null)
    {
      logManager.GetLogger
                 (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    }
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

Мне кажется, что внедрение чего-то вроде ILogManager (реализация которого обернула бы LogManager Log4net) было бы проще, чем внедрение ILogger, из-за вопроса о том, как платформа DI узнает, какой ILogger ввести.

Я новичок в платформах регистрации DI и .NET (и вообще, довольно плохо знаком с C # и .NET в целом). Подавляющее большинство моего опыта за последние много лет это VB6 + VC ++ 6.

Спасибо за ЛЮБУЮ информацию ...

Начать редактирование ...

Я еще раз посмотрел на SO и обнаружил, что вы также спрашивали об AutoFac, поэтому я предполагаю, что вы используете это для своего DI. Если это правда, то я думаю, что вы также делаете что-то вроде this или, видимо, даже лучше, например this для разрешения вашего регистратора (по типу класса). Я предполагаю, что это отвечает на вопрос, как, по крайней мере в AutoFac, вводить именованные регистраторы (например, из Log4Net или NLog).

Конец редактирования ...

0 голосов
/ 22 августа 2009

Если вы говорите о внедрении зависимостей (скажем, в смысле Spring.NET), то это не имеет большого значения - хотя вы не получаете большого значения от нескольких копий экземпляров регистратора. Как правило, каждый экземпляр регистратора, возвращаемый платформой с определенным классом / именем, в любом случае будет одиночным, поэтому вопрос заключается в том, хотите ли вы загромождать каждый экземпляр ссылкой на регистратор, а не на одну статическую ссылку на класс. Если вас беспокоит изменение реализаций регистратора, то войдите в интерфейс (CommonLogging, упомянутый в другом ответе, делает это и поддерживает реализации как log4net, так и Enterprise Library).

Если вы говорите об инъекции с использованием АОП, то я не уверен, что после определенного момента инъекция АОП более гибкая. Вы в значительной степени ограничены регистрацией входов, выходов и исключений с уровнем детализации на уровне метода. AOP Injection - это скорее простой подход, даже если вы используете AOP для выборочного внедрения в части вашего кода. Несмотря на то, что ведение журнала рекламируется как междисциплинарная проблема, которая идеально подходит для АОП, я никогда не обнаруживал, что ведение журнала на основе АОП будет широко использоваться на практике (конечно, YMMV).

...