Регистрация общего и сопоставленного диагностического контекста - PullRequest
2 голосов
/ 24 декабря 2008

Что сделали другие, чтобы обойти тот факт, что проект ведения журнала Commons (как для .NET, так и для Java), насколько я знаю, не поддерживает сопоставленные или вложенные диагностические контексты?

Ответы [ 4 ]

2 голосов
/ 28 декабря 2008

Это не прямой ответ на ваш вопрос, но есть ли у вас возможность использовать что-то кроме Commons Logging? Если вы открыты для этого, SLF4J (Simple Logging Facade - http://www.slf4j.org/)) - это еще один API абстракции журнала, который, по-видимому, поддерживает сопоставленный диагностический контекст.

Я должен отметить, что лично я не использовал его, но искал возможность использовать его для моего следующего крупного проекта, поскольку они утверждают, что он намного лучше, чем Commons Logging. Многие новые крупные проекты с открытым исходным кодом, похоже, также используют его (Hibernate, Spring Modules, несколько проектов Apache).

2 голосов
/ 28 декабря 2008

Краткое содержание:

Мы решили использовать каркас ведения журнала разработчика (в нашем случае, log4j).

Длинный ответ:

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

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

  • Что дает мне NDC и другие специальные функции?
  • какова вероятность того, что придется сменить разработчика журналирования, и сколько это будет стоить?

и возможно:

  • Нужно ли поддерживать разных разработчиков журналов при одновременном развертывании?

В нашем случае, если нам когда-либо потребуется изменить разработчиков журналирования, у нас будет какой-то рефакторинг, но со всем, что есть в пакете org.apache.log4j, это не является ни сложным, ни очень рискованным рефакторингом 1 . Плагин log4e Eclipes автоматически преобразует фактические операторы регистрации; объект NDC может быть проблемой, потому что не все каркасы журналирования поддерживают такую ​​вещь. Вы можете подумать о том, чтобы скрыть методы NDC.enter () и NDC.leave () внутри служебного класса под своим собственным контролем, мы не беспокоились.

<ч /> 1 ) знаменитые последние слова

0 голосов
/ 20 сентября 2010

Это поздно по сравнению с исходным вопросом и самым последним (принятым) ответом, но я опубликую его для будущих пользователей.

Согласно веб-сайту Common.Logging (NET) , следующая версия (текущая версия 2.0) должна иметь поддержку именно этой вещи. Однако неясно, когда планируется этот релиз. 2.0 был выпущен в апреле 2009 года. На сайте говорится, что следующий релиз запланирован на «июнь». Год не указан. Июнь 2009 и июнь 2010 пришли и ушли.

Сказав это, по крайней мере, реализация абстракции "context" log4net / NLog существует в репозитории исходного кода git проекта Castle. Запустите здесь и посмотрите на ExtendedLog4netLogger, GlobalContextProperties, ThreadContextProperties, ThreadContextStack и ThreadContextStacks, чтобы увидеть, как Castle предоставляет NDC и MDC. Аналогичная реализация существует в Castle для NLog.

Если бы Common.Logging for NET реализовывал подобную абстракцию, вы могли бы установить значения контекста через экземпляр регистратора, который вы возвращаете из LogManager, следующим образом:

ILog logger = LogManager.GetCurrentClassLogger();
logger.ThreadContextProperties["EventID"] = 123;
logger.GlobalContextPropeties["USER"] = GetUser();

В дополнение к этому, если у вас был определенный контекст, который вы хотите установить для всех сообщений журнала (скажем, из своего собственного контекста, который вы передаете в своем коде), вы можете написать свою собственную абстракцию log4net и / или NLog в подключитесь к Common.Logging, чтобы заполнить эту информацию автоматически. Например, предположим, что ваше приложение имеет «контекст», который передается, который помогает отслеживать информацию для данной «транзакции». Также, для простоты, предположим, что вы можете получить к нему доступ через статический класс, такой как «MyContext».

Ваш WriteInternal (то, что вы реализуете, когда пишете абстракцию логгера для подключения к Common.Logging), может выглядеть примерно так (это для NLog. Log4net может немного отличаться):

protected override void WriteInternal(CommonLoggingLogLevel logLevel, object message, Exception exception)
{
  LogLevelNLog level = GetLevel(logLevel);
  LogEventInfo logEvent = new LogEventInfo(level, _logger.Name, null, "{0}", new object[] { message }, exception);

  //Access these context values for output formatting using the event-context:item token
  logEvent.Context["ActivityID"] = MyContext.ActivityID;
  logEvent.Context["SessionID"] = MyContext.SessionID;
  logEvent.Context["TransactionStartTime"] = MyContext.TransactionStartTime;

  //Note that you can also set NDC and/or MDC here:
  NLog.MDC.Set("SoftwareVersion", MyContext.Version.ToString());
  _logger.Log(declaringType, logEvent);
}

Если вы (или кто-то еще) используете Common.Logging (NET), необходимо предоставить свойства контекста log4net / NLog, вы можете сделать нечто подобное тому, что сделал Castle, чтобы показать их через интерфейс абстракции логирования. Если вы хотите установить контекст автоматически с информацией, которую вы можете получить из журнала вызовов, вы можете сделать что-то похожее на то, что я предлагаю выше.

0 голосов
/ 05 ноября 2009

Ради полноты я написал свой собственный очень простой универсальный интерфейс:

public interface IDiagnosticContextHandler
{
    void Set(string name, string value);
}

затем внедрил специальную версию Log4Net:

public class Log4NetDiagnosticContextHandler : IDiagnosticContextHandler
{
    private readonly Assembly assembly;

    private readonly Type mdcType;

    public Log4NetDiagnosticContextHandler()
    {
        this.assembly = Assembly.Load("log4net");
        this.mdcType = this.assembly.GetType("log4net.MDC", true);
    }

    public void Set(string name, string value)
    {
        this.mdcType.InvokeMember("Set", BindingFlags.InvokeMethod, null, null, new object[] { name, value });
    }
}

Затем я использовал контейнер IoC (Spring.Net) для правильной реализации. Если позже потребовалась другая структура ведения журнала, было бы просто написать другую реализацию этого интерфейса, изменив конфигурацию IoC.

...