Niektóre z nich należą do kategorii ogólnych wskazówek dotyczących NLog (lub rejestrowania), a nie wyłącznie sugestii dotyczących konfiguracji.
Oto kilka ogólnych linków do rejestrowania stąd w SO (niektóre lub wszystkie już widziałeś):
log4net vs. Nlog
Rejestrowanie najlepszych praktyk
Jaki jest sens fasady zrębowej?
Dlaczego rejestratorzy zalecają używanie rejestratora dla poszczególnych klas?
Użyj wspólnego wzorca nazewnictwa rejestratora na podstawie klasy Logger logger = LogManager.GetCurrentClassLogger()
. Daje to wysoki stopień szczegółowości rejestratorów i daje dużą elastyczność w konfiguracji rejestratorów (sterowanie globalnie, według przestrzeni nazw, według konkretnej nazwy rejestratora itp.).
W razie potrzeby używaj rejestratorów nie opartych na nazwie klasy. Być może masz jedną funkcję, dla której naprawdę chcesz kontrolować rejestrowanie osobno. Być może masz jakieś przekrojowe problemy z rejestrowaniem (rejestrowanie wydajności).
Jeśli nie korzystasz z rejestrowania opartego na nazwie klasy, rozważ nazwanie programów rejestrujących w jakiejś strukturze hierarchicznej (być może według obszaru funkcjonalnego), aby zachować większą elastyczność konfiguracji. Na przykład, możesz mieć obszar funkcjonalny „bazy danych”, FA „analizy” i FA „ui”. Każdy z nich może mieć podobszary. Możesz więc poprosić o rejestratory w następujący sposób:
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");
I tak dalej. Za pomocą hierarchicznych programów rejestrujących można skonfigurować rejestrowanie globalnie („*” lub root logger), według FA (baza danych, analiza, interfejs użytkownika) lub według podobszaru (Database.Connect itp.).
Rejestratory mają wiele opcji konfiguracji:
<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" />
Zobacz pomoc NLog, aby uzyskać więcej informacji o tym, co dokładnie oznacza każda z opcji. Prawdopodobnie najbardziej znaczącymi elementami są tutaj zdolność do rejestrowania symboli rejestrujących z użyciem symboli wieloznacznych, koncepcja, że wiele reguł rejestrujących może „wykonać” dla pojedynczej instrukcji rejestrowania oraz że reguła rejestrująca może być oznaczona jako „ostateczna”, więc kolejne reguły nie będą wykonywane dla podana instrukcja logowania.
Użyj GlobalDiagnosticContext, MappedDiagnosticContext i NestedDiagnosticContext, aby dodać dodatkowy kontekst do wyników.
Aby uprościć, użyj „zmiennej” w pliku konfiguracyjnym. Na przykład możesz zdefiniować zmienne dla swoich układów, a następnie odwoływać się do zmiennej w konfiguracji docelowej zamiast określać układ bezpośrednio.
<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>
Możesz też utworzyć „niestandardowy” zestaw właściwości, aby dodać go do układu.
<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}"/>
Lub możesz robić takie rzeczy, jak tworzenie rendererów układu „dzień” lub „miesiąc” ściśle poprzez konfigurację:
<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>
Możesz także użyć renderowania układu, aby zdefiniować swoją nazwę pliku:
<variable name="day" value="${date:format=dddd}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${day}.log" />
</targets>
Jeśli codziennie rzutujesz swój plik, każdy plik może mieć nazwę „Monday.log”, „Tuesday.log” itp.
Nie bój się napisać własnego renderera układu. Jest to łatwe i pozwala na dodanie własnych informacji kontekstowych do pliku dziennika poprzez konfigurację. Na przykład tutaj jest mechanizm renderowania układu (oparty na NLog 1.x, a nie 2.0), który może dodać Trace.CorrelationManager.ActivityId do dziennika:
[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;
}
}
Powiedz NLog, gdzie są twoje rozszerzenia NLog (jaki zestaw):
<extensions>
<add assembly="MyNLogExtensions"/>
</extensions>
Użyj mechanizmu renderującego układ niestandardowy w następujący sposób:
<variable name="fmt" value="${longdate} | ${ActivityId} | ${message}"/>
Użyj asynchronicznych celów:
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
I domyślne opakowania docelowe:
<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>
w stosownych przypadkach. Zobacz dokumentację NLog, aby uzyskać więcej informacji na ich temat.
Poinformuj NLog, aby obejrzał i automatycznie przeładował konfigurację, jeśli się zmieni:
<nlog autoReload="true" />
Istnieje kilka opcji konfiguracji, które pomogą rozwiązać problemy z NLog
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
<nlog internalLogToConsole="false|true" />
<nlog internalLogToConsoleError="false|true" />
Aby uzyskać więcej informacji, zobacz Pomoc NLog.
NLog 2.0 dodaje opakowania LayoutRenderer, które pozwalają na dodatkowe przetwarzanie danych wyjściowych renderera układu (takie jak przycinanie białych znaków, górnej i dolnej itd.).
Nie bój się owinąć programu rejestrującego, jeśli chcesz odizolować swój kod od twardej zależności od NLog, ale poprawnie go zawiń. Istnieją przykłady tego, jak owinąć w repozytorium github NLog. Innym powodem zawijania może być to, że chcesz automatycznie dodawać określone informacje kontekstowe do każdej zarejestrowanej wiadomości (umieszczając ją w LogEventInfo.Context).
Istnieje wiele zalet i wad zawijania (lub wyodrębniania) NLog (lub innych ram rejestrowania w tym zakresie). Przy odrobinie wysiłku możesz znaleźć wiele informacji tutaj na SO prezentujących obie strony.
Jeśli rozważasz owijanie, rozważ użycie Common.Logging . Działa całkiem dobrze i pozwala łatwo przejść do innej struktury rejestrowania, jeśli chcesz. Również jeśli rozważasz zawijanie, zastanów się, jak poradzisz sobie z obiektami kontekstowymi (GDC, MDC, NDC). Common.Logging obecnie nie obsługuje dla nich abstrakcji, ale podobno jest w kolejce możliwości dodawania.