Non sono a conoscenza di un modo per farlo molto facilmente. Detto questo, tutti gli esempi che date sono disponibili (o abbastanza facilmente disponibili con qualche codice personalizzato) da aggiungere a ciascun messaggio di registro. Cioè, ogni messaggio registrato può essere taggato con il nome dell'eseguibile, la versione del file, la data di rilascio, l'id utente di Windows, ecc. Tramite Layout e LayoutRenderers.
Questo ovviamente non equivale alla creazione di un'intestazione nella parte superiore del file di registro, quindi potrebbe non essere utile.
D'altra parte, è possibile utilizzare una tecnica menzionata nella risposta di Pat in this post per associare più renderizzatori di layout con lo stesso obiettivo. È possibile definire un layout che contenga i campi desiderati nell'intestazione e impostare il filtro in FilteringWrapper per applicare solo quel layout per il primo messaggio di una sessione (oppure si potrebbe utilizzare qualche altra tecnica che viene aggiunta al file di output solo una volta).
Utilizzando il file NLog.config, ecco un modo per ottenere ciò che si desidera. Nota che non ho provato questo, quindi non so se questo file di configurazione è valido o, se lo è, se genererà i risultati che vuoi.
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.mono2.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Warn"
internalLogFile="nlog log.log"
>
<variable name="HeaderLayout" value="${processname} ${gdc:item=version} ${gdc:item=releasedate} ${windows-identity}" />
<variable name="NormalLayout" value="${longdate} ${logger} ${level} ${message} />
<targets async="true">
<target name="file" xsi:type="File" fileName="log.log"
layout="${NormalLayout}">
</target>
<target name="fileHeader" xsi:type="File" fileName="log.log"
layout="${HeaderLayout}">
</target>
</targets>
<rules>
<logger name="HeaderLogger" minlevel="Trace" writeTo="fileHeader" final="true" />
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
Nel codice, la logica di avvio potrebbe essere simile a questo:
public void Main()
{
AddHeaderToLogFile();
}
public void AddHeaderToLogFile()
{
Logger headerlogger = LogManager.GetLogger("HeaderLogger");
//Use GlobalDiagnosticContext in 2.0, GDC in pre-2.0
GlobalDiagnosticContext["releasedate"] = GetReleaseDate();
GlobalDiagnosticContext["version"] = GetFileVersion();
GlobalDiagnosticContext["someotherproperty"] = GetSomeOtherProperty();
headerlogger.Info("message doesn't matter since it is not specified in the layout");
//Log file should now have the header as defined by the HeaderLayout
//You could remove the global properties now if you are not going to log them in any
//more messages.
}
L'idea è che si dovrebbe mettere la versione del file, data di uscita, ecc nella GDC all'avvio del programma. Registra un messaggio con il registratore "HeaderLogger". Questo messaggio verrebbe scritto nel file di registro utilizzando "HeaderLayout" poiché "HeaderLogger" è associato alla destinazione "fileHeader" associata a "HeaderLayout". I campi definiti nel layout dell'intestazione sono scritti nel file di registro. I messaggi di log successivi, dato che non useranno il "HeaderLogger", useranno il layout "root" (*). Andranno allo stesso file poiché entrambi gli obiettivi "file" e "fileHeader" alla fine puntano allo stesso nome file.
Prima di iniziare a digitare questa risposta non ero sicuro di quanto facilmente si possa ottenere l'aggiunta di un'intestazione al file di registro. Dopo aver digitato questo, penso che potrebbe essere davvero piuttosto semplice!
Buona fortuna!
[EDIT] Qualcosa di simile potrebbe funzionare per cambiare il layout in base al livello. Nella prima sezione ho definito diverse variabili, ognuna delle quali definisce un layout. Nella prossima sezione ho definito diversi target ognuno dei quali usa lo stesso file, ma viene filtrato per consentire solo la scrittura di messaggi di un livello specifico. Nella sezione finale definisco una singola regola che invierà tutti i messaggi (da cui il nome del logger "*") a tutti i target.Poiché ogni target viene filtrato per livello, il target "trace" scriverà solo i messaggi "trace" ecc. Quindi, i messaggi "trace" verranno scritti usando il layout "trace", i messaggi "debug" verranno scritti usando il "debug" layout, ecc. Dal momento che tutti i target scrivono sullo stesso file, tutti i messaggi finiranno nello stesso file. Non ho provato questo, ma penso che probabilmente funzionerà.
<variable name="TraceLayout" value="THIS IS A TRACE: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="DebugLayout" value="THIS IS A DEBUG: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="InfoLayout" value="THIS IS AN INFO: ${longdate} ${level:upperCase=true} ${message}" />
<targets async="true">
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="log.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="log.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="log.log" layout="${InfoLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace, fileAsDebug, fileAsInfo" />
</rules>
(Nota che ho incluso solo 3 livelli qui).
Dopo aver mostrato come (se funziona, comunque) per applicare un layout diverso in base al livello, sembra che si tratti di un caso di utilizzo insolito. Non sto dicendo che sia una buona idea o una cattiva idea, ma non posso dire di averlo visto davvero molto. A seconda del modo in cui vuoi che il tuo output finale appaia, quello che ti ho mostrato potrebbe essere o non essere il modo migliore per ottenerlo. Forse potresti pubblicare alcuni esempi di come vuoi che il tuo output appaia.
Si potrebbe anche considerare di accettare la mia risposta originale e quindi di fare una nuova domanda sulla variazione del layout di output per livello in modo da poter concentrare la discussione in quella domanda sul problema del livello/layout. Spetta a te se ciò ti sembra utile o meno.
Questo funziona:
<variable name="TraceLayout" value="This is a TRACE - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="DebugLayout" value="This is a DEBUG - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="InfoLayout" value="This is an INFO - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="WarnLayout" value="This is a WARN - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="ErrorLayout" value="This is an ERROR - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="FatalLayout" value="This is a FATAL - ${longdate} | ${logger} | ${level} | ${message}"/>
<targets>
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="xxx.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="xxx.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" />
</target>
<target name="fileAsWarn" xsi:type="FilteringWrapper" condition="level==LogLevel.Warn">
<target xsi:type="File" fileName="xxx.log" layout="${WarnLayout}" />
</target>
<target name="fileAsError" xsi:type="FilteringWrapper" condition="level==LogLevel.Error">
<target xsi:type="File" fileName="xxx.log" layout="${ErrorLayout}" />
</target>
<target name="fileAsFatal" xsi:type="FilteringWrapper" condition="level==LogLevel.Fatal">
<target xsi:type="File" fileName="xxx.log" layout="${FatalLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace,fileAsDebug,fileAsInfo,fileAsWarn,fileAsError,fileAsFatal" />
<logger name="*" minlevel="Info" writeTo="dbg" />
</rules>
ho creato un layout per ciascun livello di registrazione, l'aggiunta di una stringa letterale all'inizio che descrive il livello del messaggio (questo è quello di dimostrare che un formato diverso viene utilizzato per ogni livello). Ogni Layout è associato a un FilteringWrapper che filtra in base al livello del messaggio e indirizza i messaggi che passano al filtro da registrare nel file di output. Ogni FilteringWrapper include lo stesso file di output, quindi tutti i messaggi di log verranno registrati nello stesso file.
Ecco una sezione di codice che ho usato per la prova:
logger.Trace("Trace msg");
logger.Debug("Debug msg");
logger.Info("Info msg");
logger.Warn("Warn msg");
logger.Error("Error msg");
logger.Fatal("Fatal msg");
E qui è ciò che l'output appare come:
This is a TRACE - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Trace | Trace msg
This is a DEBUG - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Debug | Debug msg
This is an INFO - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Info | Info msg
This is a WARN - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Warn | Warn msg
This is an ERROR - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Error | Error msg
This is a FATAL - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Fatal | Fatal msg
A quanto pare il problema nel mio precedente informazioni di configurazione era lo spazio tra i valori "writeTo"
. Immagino che NLog sia sensibile a questo. Avevo qualcosa come "writeTo=blah1, blah2, blah3".
Quando ho cambiato quello a "writeTo=blah1,blah2,blah3"
l'errore è andato via. Buona fortuna!
Molti grazie wageoghe, che ha funzionato bene. Tuttavia, come sempre, essendo riuscito a far funzionare le funzionalità di base, ora ho bisogno di mettere a punto le cose :-) Fondamentalmente ho bisogno di avere layout diversi per i diversi livelli di registrazione, come si fa a condizionare il layout sul livello selezionato? –
Cosa vuoi che siano i diversi layout? Vuoi avere campi diversi nei layout per i diversi livelli di registrazione? Ad ogni modo, potresti probabilmente usare la tecnica mostrata da Pat nel link qui sopra. Definisce un target di file per i suoi messaggi di registrazione "normali" e definisce un target "filter wrapper" per utilizzare un layout diverso per i messaggi che contengono un'eccezione. Proverò ad aggiungere un esempio di qualcosa che potrebbe aiutarti. – wageoghe
Utilizzando la tecnica suggerita, per il seguente: Ricevo il seguente errore nel file di configurazione: 'L'attributo' writeTo 'non è valido ....' per –