Каковы лучшие практики для включения входа с помощью log4net?

Мне сказали добавить “вход” к моему коду с помощью log4net, проблема, никто не может переместиться вовремя и видеть, какие проблемы реального мира вход должен будет использоваться для решения.

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

Поэтому:

Какие виды входа нужно добавить к приложению, которое было бы полезно позже?

(Код использует много WCF, одна сторона находится в Winforms, другая сторона является “сервером”, которые обычно работают на той же машине),

--

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

19
задан Luke Girvin 26 March 2012 в 11:04
поделиться

8 ответов

Я нашел эту статью очень полезной: http://blog.codinghorror.com/the-problem-with-logging/

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

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

6
ответ дан 30 November 2019 в 04:33
поделиться

Как правило, при ведении журнала я добавляю ведение журнала в следующем порядке:

  1. Вход / выход из функции
  2. Основные логические шаги внутри функции
  3. Подробное ведение журнала для всех промежуточных вычислений

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

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

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

2
ответ дан 30 November 2019 в 04:33
поделиться

Мой любимый источник информации для такого рода вопросов - Release It - книга от ребят из прагматиков. Настоятельно рекомендуется.

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

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

5
ответ дан 30 November 2019 в 04:33
поделиться

Одна из замечательных особенностей log4net - то, что вы можете регистрировать события в разных категориях. Значения по умолчанию: Отладка, Информация, Предупреждение и Ошибка. Мне нравится, когда они означают

Отладка - очень многословная, содержит много отладочной информации. Например, запросы SQL.
Информация - полезная информация, которую полезно знать.
Предупреждение - ничего фатального, но оператор должен знать о проблеме.
Ошибка - приложение теперь нестабильно, журнал содержит диагностическую информацию, такую ​​как сообщение об исключении и трассировку стека.

Используйте их в коде, например,

_log.Info ("Обновление объекта.");

будет написать сообщение уровня INFO любому заинтересованному слушателю.

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

<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
  </layout>
</appender>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
  <file value="c:\temp\servicelog.txt" />
  <appendToFile value="true" />
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline%exception" />
  </layout>
</appender>
<root>
  <level value="ERROR" />
  <appender-ref ref="ConsoleAppender" />
</root>
<logger name="Warehouse.Core">
  <level value="INFO" />
  <appender-ref ref="FileAppender" />
</logger>
</log4net>

Здесь говорится: все сообщения ERROR на консоль, все сообщения INFO из регистратора Warehouse.Core в данный файл.

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


Что касается затрат и выгод от ведения журнала, то определенно существует золотая середина между слишком большим количеством журналов (огромные журналы, которые никто не будет использовать) и недостаточным (одна строка с надписью «сбой»).

Моя политика состоит в том, чтобы регистрировать в INFO то, что может привести к сбою: внешние зависимости (запуск приложения, вызовы служб, соединения SQL), а в DEBUG - более сложные фрагменты мясистого кода (диагностические сообщения в бизнес-логике, отдельные вызовы SQL, некоторые методы призывы).

Необычные ситуации, когда (например) используются значения по умолчанию, которые обычно не выполняются, переходят в WARN, а исключения переходят в ERROR или FATAL.

Также: имейте в виду, что в WCF есть превосходная программа для просмотра трассировки служб, которая позволяет вам «детализировать» отдельные пакеты и то, как они обрабатываются обоими сторонами стека. Это тоже, доступен по конфигурации без изменения кода. Из-за этого я обычно просто веду очень сокращенный журнал вызовов и ответов службы WCF.

1
ответ дан 30 November 2019 в 04:33
поделиться

Записывать события в средство просмотра событий.

Разумно используйте ИНФОРМАЦИЮ ОТЛАДКА ПРЕДУПРЕЖДЕНИЕ и ОШИБКА.

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

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

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

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

0
ответ дан 30 November 2019 в 04:33
поделиться

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

// some kind of loop
// do some operations
Logger.LogDebug(myObject.GetXmlRepresentation());
// end loop

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


Правильный решение будет таким:

// some kind of loop
// do some operations
if (Logger.IsDebug)
{
    Logger.LogDebug(myObject.GetXmlRepresentation());
}
// end loop
8
ответ дан 30 November 2019 в 04:33
поделиться

Какие виды ведения журнала нужно добавить в приложение, которое будет полезно позже?

Если вы генерируете исключения из своих собственных классов исключений или, что еще лучше, все ваши классы исключений являются производными от базового класса, добавьте регистрацию уровня ERROR в (базовый) конструктор исключения; избавляет вас от необходимости помнить при каждой ловле / броске. Полезно, если у вас большая кодовая база.

Для исключений CLR или сторонних разработчиков регистрировать Exception.ToString (), а не только сообщение, иначе вы пропустите полную трассировку стека (при условии, что программисты не проглатывают исключения или повторно не генерируют внутреннее исключение). в областях, где вы знаете или подозреваете, что у вас возникнут проблемы (просто спросите QA или службу технической поддержки, где искать; -)

Если вы следуете принципу устойчивости , тогда вам может потребоваться регистрация INFO или WARN, когда вы игнорируете или меняете вводимые данные или ожидаемое поведение. Это может быть полезно, если ваша служба WCF начинает получать неожиданные (но поддающиеся синтаксическому анализу) входные данные.

Чтобы ваше приложение работало хорошо, не отправляйте / не устанавливайте его с включенным по умолчанию ведением журнала уровня DEBUG, ERROR или WARN, вероятно, являются способом go.

Я не согласен с последней частью принятого ответа, потому что log4net имеет потрясающие возможности фильтрации; при условии, что ваши программисты понимают, что ведение журнала обходится дорого (согласно ответу CK), и они (а также QA и техническая поддержка) знают о фильтрах, и что настраивать все в DEBUG - плохая идея. Если вы регистрируете на уровне DEBUG граф больших объектов, xml-документ, db-результат и т. Д., оберните его в некоторый код, который снижает расходы:

if (log.IsDebugEnabled)
{
    log.DebugFormat("Loaded in {0} ms {1}", timer.ElapsedMilliseconds, dataSet.GetXml());
}

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

Если вы следуете этому подходу и желаете получить (довольно небольшое) снижение производительности, вот один способ, который использует трассировку стека для создания объектов ILog для любого класса и обеспечивает подключение файла конфигурации для отслеживания изменений:

public static class LogFactory
{
    /// <summary>
    /// Create log whose name is the calling methods class name.
    /// </summary>
    /// <remarks>
    /// <para>
    /// Configures the log repository if it hasn't been configured before.
    /// </para>
    /// <para>
    /// Creates a debug log message right after getting the logger, this follows
    /// the log4net recommendation to log first message as early as possible.
    /// </para>
    /// </remarks>
    /// <returns>Log ready for work.</returns>
    public static log4net.ILog Create()
    {
        var method = new StackTrace().GetFrame(1).GetMethod();
        var log = log4net.LogManager.GetLogger(method.DeclaringType);

        if (log4net.LogManager.GetRepository().Configured == false)
        {
            try
            {
                new FileIOPermission(FileIOPermissionAccess.Read,
                    AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
                    .Demand();

                var configFile = new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);
                log.DebugFormat("Log4net configured and watching {0}", configFile.FullName);
            }
            catch (System.Security.SecurityException e)
            {
                log.DebugFormat("Unable to watch config file due to security permissions. {0}", e.ToString());
            }
        }

        log.DebugFormat("Logging {0}", log.Logger.Name);

        return log;
    }
}
1
ответ дан 30 November 2019 в 04:33
поделиться

Возможно, есть лучший способ сделать это для WCF; для WinForms вы можете рассмотреть PostSharp . Это позволит вам регистрировать вызовы методов, не загромождая код. За кулисами вы все равно будете использовать отличный log4net.

Предостережение: я сам не использовал его; Я видел очень впечатляющую презентацию об этом в лагере кодов.

0
ответ дан 30 November 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: