Некоторые из них относятся к категории общих советов по NLog (или ведению журналов), а не только к рекомендациям по конфигурации.
Вот некоторые общие ссылки для регистрации отсюда в SO (вы, возможно, уже видели некоторые или все из них):
log4net против Nlog
Регистрация лучших практик
Какой смысл вырубки фасада?
Почему регистраторы рекомендуют использовать регистратор для каждого класса?
Используйте общий шаблон именования вашего регистратора в зависимости от класса Logger logger = LogManager.GetCurrentClassLogger()
. Это дает вам высокую степень детализации в ваших регистраторах и дает вам большую гибкость в настройке регистраторов (управление глобально, пространством имен, определенным именем регистратора и т. Д.).
При необходимости используйте регистраторы, не основанные на именах классов. Возможно, у вас есть одна функция, для которой вы действительно хотите управлять регистрацией отдельно. Возможно, у вас есть общие проблемы с журналированием (регистрация производительности).
Если вы не используете журналирование на основе имени класса, рассмотрите возможность именования ваших регистраторов в какой-то иерархической структуре (возможно, по функциональной области), чтобы вы могли поддерживать большую гибкость в вашей конфигурации. Например, у вас может быть функциональная область «база данных», FA «анализа» и FA «ui». У каждого из них могут быть подобласти. Итак, вы можете запросить регистраторы, как это:
Logger logger = LogManager.GetLogger("Database.Connect");
Logger logger = LogManager.GetLogger("Database.Query");
Logger logger = LogManager.GetLogger("Database.SQL");
Logger logger = LogManager.GetLogger("Analysis.Financial");
Logger logger = LogManager.GetLogger("Analysis.Personnel");
Logger logger = LogManager.GetLogger("Analysis.Inventory");
И так далее. С помощью иерархических регистраторов вы можете настроить ведение журнала глобально («*» или корневой регистратор), по FA (база данных, анализ, пользовательский интерфейс) или по подрайонам (Database.Connect и т. Д.).
У логгеров есть много опций конфигурации:
<logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" />
<logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" />
<logger name="Name.Space.*" writeTo="f3,f4" />
<logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" />
Смотрите справку NLog для получения дополнительной информации о том, что конкретно означает каждый из параметров. Вероятно, наиболее заметными элементами здесь являются возможность подстановки правил ведения журнала, концепция, что несколько правил ведения журнала могут «выполняться» для одного оператора ведения журнала, и что правило ведения журнала может быть помечено как «окончательное», поэтому последующие правила не будут выполняться для данное заявление о регистрации.
Используйте GlobalDiagnosticContext, MappedDiagnosticContext и NestedDiagnosticContext, чтобы добавить дополнительный контекст к выходным данным.
Используйте «переменную» в вашем конфигурационном файле, чтобы упростить. Например, вы можете определить переменные для ваших макетов, а затем ссылаться на переменную в целевой конфигурации, а не указывать макет напрямую.
<variable name="brief" value="${longdate} | ${level} | ${logger} | ${message}"/>
<variable name="verbose" value="${longdate} | ${machinename} | ${processid} | ${processname} | ${level} | ${logger} | ${message}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${shortdate}.log" />
<target name="console" xsi:type="ColoredConsole" layout="${brief}" />
</targets>
Или вы можете создать «пользовательский» набор свойств для добавления в макет.
<variable name="mycontext" value="${gdc:item=appname} , ${mdc:item=threadprop}"/>
<variable name="fmt1withcontext" value="${longdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>
<variable name="fmt2withcontext" value="${shortdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>
Или, вы можете делать такие вещи, как создание "день" или "месяц" рендеринга макета строго через конфигурацию:
<variable name="day" value="${date:format=dddd}"/>
<variable name="month" value="${date:format=MMMM}"/>
<variable name="fmt" value="${longdate} | ${level} | ${logger} | ${day} | ${month} | ${message}"/>
<targets>
<target name="console" xsi:type="ColoredConsole" layout="${fmt}" />
</targets>
Вы также можете использовать макет рендера для определения вашего имени файла:
<variable name="day" value="${date:format=dddd}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${day}.log" />
</targets>
Если вы прокручиваете свой файл ежедневно, каждый файл может называться «Monday.log», «Tuesday.log» и т. Д.
Не бойтесь написать свой собственный рендер. Это просто и позволяет вам добавить свою собственную контекстную информацию в файл журнала через конфигурацию. Например, вот средство визуализации макета (на основе NLog 1.x, а не 2.0), которое может добавить Trace.CorrelationManager.ActivityId в журнал:
[LayoutRenderer("ActivityId")]
class ActivityIdLayoutRenderer : LayoutRenderer
{
int estimatedSize = Guid.Empty.ToString().Length;
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(Trace.CorrelationManager.ActivityId);
}
protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
{
return estimatedSize;
}
}
Скажите NLog, где ваши расширения NLog (какая сборка) похожи на это:
<extensions>
<add assembly="MyNLogExtensions"/>
</extensions>
Используйте пользовательский макет рендеринга, как это:
<variable name="fmt" value="${longdate} | ${ActivityId} | ${message}"/>
Используйте асинхронные цели:
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
И целевые оболочки по умолчанию:
<nlog>
<targets>
<default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
</targets>
<targets>
<default-wrapper xsi:type="AsyncWrapper">
<wrapper xsi:type="RetryingWrapper"/>
</default-wrapper>
<target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
<target name="n2" xsi:type="Network" address="tcp://localhost:4002"/>
<target name="n3" xsi:type="Network" address="tcp://localhost:4003"/>
</targets>
</nlog>
где уместно. См. Документы NLog для получения дополнительной информации о них.
Скажите NLog, чтобы он посмотрел и автоматически перезагрузил конфигурацию, если она изменилась:
<nlog autoReload="true" />
Есть несколько вариантов конфигурации, которые помогут с устранением неполадок NLog
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
<nlog internalLogToConsole="false|true" />
<nlog internalLogToConsoleError="false|true" />
См. Справку NLog для получения дополнительной информации.
В NLog 2.0 добавлены обертки LayoutRenderer, которые позволяют выполнять дополнительную обработку на выходе средства визуализации макета (например, обрезать пробел, верхний регистр, нижний регистр и т. Д.).
Не бойтесь заворачивать регистратор, если вы хотите изолировать свой код от жесткой зависимости от NLog, но переносите его правильно. В github-репозитории NLog есть примеры того, как оборачиваться. Другая причина для переноса может заключаться в том, что вы хотите автоматически добавлять определенную контекстную информацию к каждому зарегистрированному сообщению (помещая ее в LogEventInfo.Context).
Есть плюсы и минусы в обертывании (или абстрагировании) NLog (или любой другой фреймворк логирования в этом отношении). Приложив немного усилий, вы можете найти много информации здесь на SO, представляющей обе стороны.
Если вы рассматриваете упаковку, подумайте об использовании Common.Logging . Он работает довольно хорошо и позволяет вам легко переключаться на другую структуру ведения журналов, если вы хотите это сделать. Также, если вы рассматриваете упаковку, подумайте, как вы будете обрабатывать объекты контекста (GDC, MDC, NDC). Common.Logging в настоящее время не поддерживает абстракцию для них, но он предположительно находится в очереди возможностей для добавления.