Alcuni di questi rientrano nella categoria di suggerimenti NLog generali (o di registrazione) piuttosto che in suggerimenti di configurazione.
Ecco alcuni link di registrazione generali da qui a SO (potresti aver già visto alcuni o tutti questi):
log4net vs. Nlog
Registrazione delle migliori pratiche
Qual è il punto di una facciata in legno?
Perché i logger raccomandano di usare un logger per classe?
Utilizzare il modello comune di denominazione del logger in base alla classe Logger logger = LogManager.GetCurrentClassLogger()
. Questo ti dà un alto grado di granularità nei tuoi logger e ti dà una grande flessibilità nella configurazione dei logger (controllo globale, per spazio dei nomi, per nome specifico del logger, ecc.).
Utilizzare i logger non basati sul nome di classe, ove appropriato. Forse hai una funzione per la quale vuoi davvero controllare la registrazione separatamente. Forse hai dei problemi di registrazione trasversale (registrazione delle prestazioni).
Se non si utilizza la registrazione basata su classname, prendere in considerazione la denominazione dei propri logger in una sorta di struttura gerarchica (forse per area funzionale) in modo da poter mantenere una maggiore flessibilità nella configurazione. Ad esempio, potresti avere un'area funzionale "database", un FA "analisi" e un FA "ui". Ognuno di questi potrebbe avere aree secondarie. Quindi, potresti richiedere logger come questo:
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");
E così via. Con i logger gerarchici, è possibile configurare la registrazione a livello globale ("*" o root logger), per FA (Database, Analysis, UI) o per sottoarea (Database.Connect, ecc.).
I logger hanno molte opzioni di configurazione:
<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" />
Consulta la guida di NLog per ulteriori informazioni sul significato esatto di ciascuna opzione. Probabilmente gli elementi più importanti qui sono la possibilità di regole jolly del logger, il concetto che più regole del logger possono "eseguire" per una singola istruzione di registrazione e che una regola del logger può essere contrassegnata come "finale", quindi le regole successive non verranno eseguite per un data dichiarazione di registrazione.
Utilizzare GlobalDiagnosticContext, MappedDiagnosticContext e NestedDiagnosticContext per aggiungere ulteriore contesto all'output.
Usa "variabile" nel tuo file di configurazione per semplificare. Ad esempio, è possibile definire variabili per i layout e quindi fare riferimento alla variabile nella configurazione di destinazione anziché specificare direttamente il layout.
<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>
In alternativa, è possibile creare un set "personalizzato" di proprietà da aggiungere a un layout.
<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}"/>
Oppure, puoi fare cose come creare renderizzatori di layout "giorno" o "mese" rigorosamente tramite la configurazione:
<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>
Puoi anche utilizzare i rendering di layout per definire il tuo nome file:
<variable name="day" value="${date:format=dddd}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${day}.log" />
</targets>
Se arrotoli il tuo file ogni giorno, ogni file potrebbe essere chiamato "Monday.log", "Tuesday.log", ecc.
Non aver paura di scrivere il tuo renderizzatore di layout. È facile e consente di aggiungere le informazioni di contesto al file di registro tramite la configurazione. Ad esempio, ecco un renderer di layout (basato su NLog 1.x, non 2.0) che può aggiungere Trace.CorrelationManager.ActivityId al registro:
[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;
}
}
Indica a NLog dove si trovano le estensioni NLog (quale assembly) in questo modo:
<extensions>
<add assembly="MyNLogExtensions"/>
</extensions>
Usa il renderer di layout personalizzato in questo modo:
<variable name="fmt" value="${longdate} | ${ActivityId} | ${message}"/>
Usa target asincroni:
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
E wrapper target predefiniti:
<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>
ove opportuno. Vedi i documenti NLog per maggiori informazioni su quelli.
Di 'a NLog di guardare e ricaricare automaticamente la configurazione se cambia:
<nlog autoReload="true" />
Esistono diverse opzioni di configurazione per la risoluzione dei problemi di NLog
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
<nlog internalLogToConsole="false|true" />
<nlog internalLogToConsoleError="false|true" />
Vedere la Guida NLog per ulteriori informazioni.
NLog 2.0 aggiunge i wrapper LayoutRenderer che consentono di eseguire ulteriori elaborazioni sull'output di un renderer di layout (come il taglio di spazi bianchi, lettere maiuscole, lettere minuscole, ecc.).
Non aver paura di racchiudere il logger se vuoi isolare il tuo codice da una forte dipendenza da NLog, ma avvolgi correttamente. Ci sono esempi di come eseguire il wrapping nel repository github di NLog. Un altro motivo per concludere potrebbe essere che si desidera aggiungere automaticamente informazioni di contesto specifiche a ciascun messaggio registrato (inserendolo in LogEventInfo.Context).
Ci sono pro e contro nel wrapping (o nell'astrazione) di NLog (o in qualsiasi altro framework di registrazione per quella materia). Con un piccolo sforzo, puoi trovare molte informazioni qui su SO che presentano entrambe le parti.
Se stai pensando di eseguire il wrapping, considera l'utilizzo di Common.Logging . Funziona abbastanza bene e consente di passare facilmente a un altro framework di registrazione se lo si desidera. Inoltre, se stai pensando di eseguire il wrapping, pensa a come gestirai gli oggetti di contesto (GDC, MDC, NDC). Common.Logging non supporta attualmente un'astrazione per loro, ma è presumibilmente nella coda di funzionalità da aggiungere.