Пространство имен System.Diagnostics.Debug и другие решения для ведения журналов (log4net, MS Enterprise Library и т. Д.)

В настоящее время я изучаю различные возможности ведения журналов для проектов.net, и я не могу выбирать между функциями System.Diagnostics.Debug/Trace и сторонними библиотеками, такими как log4net, MS Enterprise Library, NLog и т. Д.
На данный момент я узнал это:

  • System.Diagnostics довольно сложно настроить и использовать, так как вам нужно явно настроить все прослушиватели, фильтры, источники и т. Д. Кажется, что в ней также отсутствует массовая вставка в БД (подумайте о записи 100'000 записей в журнале с его собственная Вставка, ужасающая, не так ли?) Но некоторые люди считают "круто" не использовать дополнительные библиотеки для такой "рудиментарной" вещи, как Logging (конечно, в какой-то момент имеет смысл уменьшить количество сторонних библиотек, на которые опирается ваш проект, но не в этот раз, я полагаю)
  • Сторонние разработчики гораздо более мощные, часто более быстрые, гораздо более простые в использовании, но конфигурация иногда может быть также болезненной, и часто эти библиотеки менее надежны (например, загадочная внезапная остановка регистрации EntLib и т. Д.)
  • как насчет Common.Logging? стоит ли пытаться (поскольку, как я слышал, он предлагает подключать различные каркасы журналирования и действует как интерфейс между приложением и желаемой библиотекой)?


Я был бы очень признателен, если бы кто-то мог указать мне правильное направление или исправить (или добавить что-то) мое сравнение, данное выше! Возможно, если вы порекомендуете мне использовать сторонние организации, вы можете посоветовать какую-то конкретную (учитывая, что нашим приложениям, скорее всего, не понадобятся какие-то модные вещи, такие как UDP, переходящие файлы и т. Д.- просто обычный файл, электронная почта, БД и Журнал событий)?
Заранее спасибо!

4 ответа

Решение

Вы можете найти много информации о log4net и NLog либо здесь, на Stackru, по более общему поиску в Google.

Вы также можете найти много информации о System.Diagnostics. Стоит отметить одну вещь о System.Diagnostics, я думаю, что вы найдете здесь много ссылок на Stackru об использовании Debug.Write/WriteLine и Trace.Write/WriteLine. Возможно, "лучшим" способом является использование TraceSources. TraceSources аналогичны регистраторам в log4net и NLog. TraceSources позволяет вам иметь более высокую степень детализации для ваших сообщений, что облегчает включение и отключение некоторых записей (по классу или категории, в дополнение к уровню). У TraceSources есть недостаток по сравнению с log4net и NLog, заключающийся в том, что каждый TraceSource, который вы создаете в своем коде, должен быть явно настроен в app.config (если вы хотите, чтобы он действительно регистрировался).

log4net и NLog имеют иерархическую концепцию, в которой, если точный регистратор, который вы запрашивали, не настроен явно, проверяется его "происхождение", чтобы увидеть, настроены ли какие-либо "предки", и, если это так, запрошенный регистратор "наследует" эти параметры. Предки - это просто части имени регистратора, разделенные символом ".". (Итак, если вы запрашиваете регистратор под названием "ABC.DEF.GHI"предки будут "ABC.DEF", а также "ABC"). Также возможно (требуется?) Иметь конфигурацию "корневого" логгера в app.config, к которой будут обращаться ВСЕ запросы логгера, если они не сконфигурированы явно и не настроены предки. Таким образом, вы можете настроить только "корневой" регистратор для регистрации на определенном уровне, и все ваши регистраторы в вашем коде будут регистрировать на этом уровне. В качестве альтернативы, вы можете настроить "корневой" регистратор как "выключенный", а затем явно включить один или несколько регистраторов (или путем настройки предка). Таким образом, никакие регистраторы не будут регистрировать, ИСКЛЮЧИТЬ тех, которые настроены.

Если вы посмотрите здесь, вы найдете интересную оболочку вокруг System.Diagnostics TraceSources, которая обеспечивает возможность наследования, очень похожую на log4net и NLog.

Проиллюстрировать:

Распространенный шаблон использования для регистраторов в log4net и NLog - это получить регистратор, подобный этому:

//log4net
static ILog logger = LogManager.GetLogger(
                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

//NLog
static Logger logger = LogManager.GetCurrentClassLogger();

В обоих случаях имя регистратора будет полным именем типа.

В файле app.config вы можете, при желании, настроить только "корневой" регистратор, и оба регистратора будут наследовать настройки корневого регистратора (уровень, appenders / target и т. Д.). В качестве альтернативы вы можете настроить регистратор для некоторого пространства имен. Любые регистраторы, тип которых определен в этом пространстве имен, наследуют эти настройки регистратора.

Достаточно log4net и NLog, вы, наверное, уже знаете, как они работают.

Ссылка выше иллюстрирует оболочку на основе TraceSource, которая допускает аналогичную конфигурацию. Итак, если вы хотите, вы можете сделать что-то подобное в ваших классах:

static TraceSource ts = new TraceSource(
               System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

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

Итак, если ваше полное имя типа выглядит примерно так: ABC.DEF.GHI, то вы можете настроить TraceSource для ABC или ABC.DEF (уровень пространства имен), и класс "GHI" будет наследовать настройки. Это может реально уменьшить количество настроек, которые вы должны выполнить.

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

Итак, вы можете запросить регистраторы в вашем коде, как это:

ILog logger = LogManager.GetLogger("Communication.Receive");
ILog logger = LogManager.GetLogger("Communication.Send");

Logger logger = LogManager.GetLogger("Communication.Receive");
Logger logger = LogManager.GetLogger("Communication.Send");

TraceSource ts = new TraceSource("Communication.Receive");
TraceSource ts = new TraceSource("Communication.Send");

Если вы настроите только "Связь" в файле app.config, то все регистраторы будут наследовать эти настройки (так как они являются потомками "Связь"). Если вы настроите только "Commuincation.Receive", то будут регистрироваться только журналы "Communication.Receive". Регистраторы "Communication.Send" будут отключены. Если вы настроите и "Связь", и "Связь. Получение", то регистраторы "Связь. Получение" будут регистрироваться с настройками "Связь. Получение", а регистраторы "Связь. Отправитель" будут регистрироваться с настройками "Связь". В log4net и NLog наследование может быть чем-то большим, но я не знаю достаточно, чтобы вдаваться в подробности.

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

Я использовал Common.Logging некоторые. В основном в прототипировании, но я мог бы использовать его в нашем следующем проекте. Он работает довольно хорошо, и относительно легко написать собственную абстракцию журналирования, чтобы подключиться к ней (например, если вы хотите написать абстракцию TraceSource, похожую на ту, что я связал выше). Две важные вещи, которые отсутствуют в Common.Logging прямо сейчас (хотя их веб-сайт сообщает, что они запланированы на "следующий" выпуск), - это контексты журналирования (такие как объекты log4net и NLog /MDC/GDC NLog и System.Diagnostics.CorrelationManger.LogicalOperationStack) и совместимость с Silverlight. Вы можете по-прежнему взаимодействовать с объектами контекста log4net или NLog в своем коде, когда используете Common.Logging, но такого рода это противоречит цели, не так ли.

Я не знаю, помог мне или нет!

Вот некоторые основные моменты, которые я хотел бы сделать в отношении log4net, NLog и TraceSource:

log4net - очень популярный, вероятно, нуждается в некоторых обновлениях - по крайней мере, построенный на.NET 4.0, последний выпуск несколько лет назад, очень гибкий.

NLog - очень похож на log4net во многих отношениях, теперь новая версия (только что вышла бета-версия NLog 2.0)

TraceSource - без сторонней зависимости, без каких-либо усилий с вашей стороны (или чьих-либо), не таких мощных, как log4net или NLog (ключевые недостатки - иерархия регистратора, форматирование вывода - оба легко адресуемы по ссылкам выше), Microsoft оснащает многие из своих компонентов с System.Diagnostics, так что вы можете получить результаты журналирования Microsoft и чередования результатов журналирования. (Как правило, захватить System.Diagnostics в других системах журналирования достаточно просто, поэтому это может не быть большой проблемой).

Хотя я не использовал ни log4net, ни NLog, между двумя я склонялся к NLog, в основном из-за новой версии (бета). Я думаю, что TraceSource также является разумным, хотя и более элементарным, выбором, особенно если вы реализуете иерархию логгеров и используете связанный с ним библиотека Ukadc.Diagnostics.

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

Я знаю, что это старый, но System.Diagnostics.Trace довольно прост в настройке, если оставить его простым. Я годами использовал простой конфигурационный блок для записи текста, скопированный прямо из документации MSDN.

Никто не упоминает об этом очень часто, но в вашем коде вы можете использовать встроенные Trace.TraceInformation, Trace.TraceWarning и Trace.TraceError, чтобы легко разделить 3 уровня вывода трассировки, а затем в файле конфигурации выбрать, какой уровень выводить (см. конфигурацию ниже). Если вы выберете "Информация" в конфиге "EventTypeFilter", вы получите все 3 в своем выводе. Если вы выберете "Ошибка", вы получите только сообщения TraceError. Большую часть времени я просто оставляю свой на Error, поэтому, если что-то случится в моем приложении, у меня уже будет этот вывод в моем файле трассировки. Внутри моих блоков Catch я добавлю код TraceError для вывода полезной информации. TraceInformation хороша для вывода таких вещей, как время или места в коде, через который вы прошли, и выгрузки значений переменных по пути. TraceWarning хорош для вещей, которые можно обрабатывать, но не желательно - например, веб-сервису требуется много времени для завершения, или количество возвращаемых записей данных превышает пороговое значение, которое может вызвать будущие проблемы.

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

<system.diagnostics>
  <sharedListeners>
    <add name="MyTraceListener" traceOutputOptions="DateTime" type="System.Diagnostics.TextWriterTraceListener, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="MyApplicationName_Trace.log">
     <!--
        Off - Does not allow any events through. 
        Error - Allows Error events through. 
        Warning - Allows Error, and Warning events through. 
        Information - Allows Error, Warning, and Information events through. 
     -->
     <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
    </add>
  </sharedListeners>
  <trace autoflush="true" indentsize="4">
    <listeners>
       <add name="MyTraceListener" />
    </listeners>
  </trace>
</system.diagnostics>

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

Мои личные предпочтения - это log4net, но это зависит от ваших потребностей. Мой лучший совет - взгляните на документацию таких решений, как log4net или EntLib Logging Application Block, и примите решение о том, что лучше для вас.

Регистрация и отслеживание - разные проблемы. Регистрация относится к оперативной обратной связи. Трассировка (в том числе предоставляемая методами Debug) относится к разработке и тестированию. Код трассировки не должен быть скомпилирован в сборки выпуска. Классы Trace и Debug достигают этого с помощью аннотаций компилятора (ConditionalAttribute). Такой код должен быть оптимизирован для сбора большого количества данных, а не для производительности. С другой стороны, операционное ведение журнала должно быть оптимизировано для повышения производительности и для более широкого спектра механизмов хранения, как того требует команда sysadmin/ Operations Team.

Поэтому я рекомендую использовать как Trace/Debug для разработки, так и более надежные пакеты регистрации для операций.

Другие вопросы по тегам