Difference between revisions of "CSharp:NLog"
From Aino Wiki
(→Livello di log) |
(No difference)
|
Latest revision as of 17:59, 13 March 2020
Contents
Configurazione Easy
In una versione minimale si devono includere le due DLL: NLog.dll NLog.Extended.dll
Si può scegliere di configurarlo aggiungendo un file di config nella root dell'applicazione chiamandolo NLog.config
il cui contenuto (per settare il logging SOLO su file) potrebbe essere:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true"> <targets> <target name="webLogfile" xsi:type="File" fileName="C:\Zighine\LOGS\HTSMSWebApi\Logfile.txt" layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" ConcurrentWrites ="false" archiveEvery = "Hour" archiveNumbering="Rolling" archiveFileName="C:\Zighine\LOGS\HTSMSWebApi\Logfile.{#####}.txt"> </target> </targets> <rules> <logger name="*" minLevel="Info" writeTo="webLogfile" /> </rules> </nlog>
A regime, nella classe dove usarlo:
using NLog; //..etc //..etc public class Test { private static Logger logger = LogManager.GetCurrentClassLogger(); //..etc //..etc logger.Error(string.Format("Get Error, the ships list of the meteo info request is mandatory.")); //oppure logger.Warn(string.Format("Get Warning, no ships values for the requested ships list."));
Configurazioni Realistiche
Es. 1
Nell'esempio che segue ci sono solo due target di tipo file per il primo s'è definita una regola (TAG ) che visualizza dagli Item di tipo Info in su che è la normale attività di monitoraggio mentre nel secondo target si definisce un file con una regola che consenta di inserirci le sole info di debug.
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true"> <!-- Per la documentazione du NLog: http://nlog-project.org/ https://github.com/nlog/NLog/wiki/Configuration-file --> <targets> <target name="webLogfile" xsi:type="File" fileName="C:\Costa\LOGS\HTSMSWebApi\Logfile.txt" layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" ConcurrentWrites ="false" maxArchiveFiles="12" archiveEvery = "Hour" archiveNumbering="Rolling" archiveFileName="C:\Costa\LOGS\HTSMSWebApi\Logfile.{#####}.txt"> </target> <target name="webLogfile_debug" xsi:type="File" fileName="C:\Costa\LOGS\HTSMSWebApi\Logfile_Debug.txt" layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" ConcurrentWrites ="false" archiveEvery = "Hour" archiveNumbering="Rolling" archiveFileName="C:\Costa\LOGS\HTSMSWebApi\Logfile_Debug.{#####}.txt"> </target> </targets> <rules> <!-- La seguente include la visualizzazione a partire degli Info escludendo i Debug --> <logger name="*" minLevel="Info" writeTo="webLogfile" /> <logger name="*" levels="Debug" writeTo="webLogfile_debug" /> <!-- La seguente include la visualizzazione a partire dai records di Debug <logger name="*" minLevel="Debug" writeTo="webLogfile" /> --> <!-- La sequenza d'ordine nella visualizzazione è: Trace, Debug, Info, Warn, Error, Fatal --> </rules> </nlog>
Layout del file di Log
Il seguente per richiedere il Thread Id (ID del Thread da cui si chiede la scrittura, vedi la chiave: "${threadid}") e nome del metodo (vedi chiave: "${callsite}").La sezione è quella denominata layout.
<target name="OPCUA_UAAcquisitor" type="File" fileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\OPCUA_UAAcquisitor.log" archiveFileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\archives\OPCUA_UAAcquisitor.{#}.log" layout="${longdate} [${threadid}]|${level:uppercase=true}|${logger}|[${callsite}] - ${message} ${exception:format=tostring}" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="3" concurrentWrites="true" keepFileOpen="false"/>
${newline}
Parametri importanti
File Target
Parametri importanti
archiveAboveSize
Dimensione del file di log espresso in byte, es:
<target name="Error" xsi:type="File" fileName="${logDirectory}/ERROR_ALL.txt" archiveFileName="${logDirectory}/archives/Errors.{#####}.txt" layout="${longdate:universalTime=true} [${threadid}] [${level}] [${callsite}] ${newline} ${message}${newline} ${exception:format=tostring}" maxArchiveFiles="10" archiveAboveSize="10485760" archiveNumbering="Sequence" concurrentWrites="true" deleteOldFileOnStartup="true" />
Dove 10485760 bytes sono 10 MegaBytes.
Layout
Quel che viene scritto ad es. nel file può essere parametrizzato. Cosa importante ad es. per la segnalazione degli errori si può scegliere cosa rappresentare della Exception che scatta (vedere qui esempi exceptions). Segue estratto dalla DOC uffficiale:
Layouts provide a way to format the contents of the logs as it is written to a file. There are 2 main kinds of layouts: simple layout - which is composed of Layout Renderers structural layouts - which can output XML, CSV, and other complex formats Simple layout is just a string, with special tags embedded between ${ and }. For example the following declaration will cause each log message to be prefixed with date formatted as yyyyMMddHHmmss:
Vedere renders, per esempi.
Utente corrente
Nel caso l'applicazione da loggare sia in multiutenza è utile capire tracciare, per ciascun item di log, ad es. l'utente windows, nella sezione layout usare ${windows-identity}
come nel seguente esempio
<target name="FormLogTarget" type="File" fileName="D:\KT\Logs\MultiPrepareKTUpdater\FormLog.log" layout="${newline}${longdate:universalTime=true} [${windows-identity}|${threadid}]|${level:uppercase=true}|[${callsite}]${newline}${message}" archiveFileName="D:\KT\Logs\MultiPrepareKTUpdater\archives\FormLog.{#}.log" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="30" concurrentWrites="true" keepFileOpen="false" deleteOldFileOnStartup="false" />
Formato data
Per rappresentare la data in UTC orario universale (vedi: github):Usare la direttiva seguente nell'attributo layout
${longdate:universalTime=true}Esempio realistico:
<target name="OPCUA_AcquisCrucialInfo" type="File" fileName="D:\KT\Logs\KTUnifiedDataCollector\OPCUA_AcquisCrucialInfo.log" layout="${newline}${longdate:universalTime=true} [${threadid}]|${level:uppercase=true}|[${callsite}]${newline}${message}" archiveFileName="D:\KT\Logs\KTUnifiedDataCollector\archives\OPCUA_AcquisCrucialInfo.{#}.log" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="30" concurrentWrites="true" keepFileOpen="false" deleteOldFileOnStartup="false"/>
Archiviazione
Dopo riavvio
Dell'elemento Target è possibile impostare la cancellazione dei vecchi files ad ogni riavvio. Ciò consente di avere una situazione pulita ad ogni ciclo di esecuzione del servizio o applicativo.Il parametro\attributo è '
deleteOldFileOnStartup
'. Esempio:<target name="acquisitors" type="File" fileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\FailbackTcpPersistorLog.log" archiveFileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\archives\FailbackTcpPersistorLog.{#}.log" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="3" concurrentWrites="true" keepFileOpen="false" deleteOldFileOnStartup="true"/>
Oltre max dimensione
L'attributo è 'archiveAboveSize="10485760"
':<target name="acquisitors" type="File" fileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\FailbackTcpPersistorLog.log" archiveFileName="D:\KT\Logs\KTUnifiedDataCollector_OPCUA\archives\FailbackTcpPersistorLog.{#}.log" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="3" concurrentWrites="true" keepFileOpen="false" archiveAboveSize="10485760" />
Se non funziona
Attenzione potrebbe capitare che il file di Log non venga creato. Il problema potrebbe essere nel fatto che il file di configurazione NLog.config non venga copiato nella cartella dove sono gli eseguibili es la .\bin\Debug.Ciò può esser dovuto ad un parametro della risorsa inserita al progetto ovvero il "Copy to Output Directory", darci un'occhiata prima di pensare ad altro.
Uso di Variabili
<nlog autoReload="true" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <variable name="logDirectory" value="" /> <targets> <target name="Error" xsi:type="File" fileName="${logDirectory}/ERROR_ALL.txt" archiveFileName="${logDirectory}/archives/Errors.{#####}.txt" layout="${longdate} [${threadid}] [${level}] [${callsite}] ${newline} ${message} ${newline} ${exception:format=tostring}" maxArchiveFiles="10" archiveAboveSize="10485760" archiveNumbering="Sequence" concurrentWrites="true" deleteOldFileOnStartup="true" /> ...
Modifiche dinamiche
Configurazione
Segue esempio da github NLog:
using NLog; using NLog.Targets; using NLog.Config; using NLog.Win32.Targets; class Example { static void Main(string[] args) { // Step 1. Create configuration object var config = new LoggingConfiguration(); // Step 2. Create targets and add them to the configuration var consoleTarget = new ColoredConsoleTarget(); config.AddTarget("console", consoleTarget); var fileTarget = new FileTarget(); config.AddTarget("file", fileTarget); // Step 3. Set target properties consoleTarget.Layout = @"${date:format=HH\:mm\:ss} ${logger} ${message}"; fileTarget.FileName = "${basedir}/file.txt"; fileTarget.Layout = "${message}"; // Step 4. Define rules var rule1 = new LoggingRule("*", LogLevel.Debug, consoleTarget); config.LoggingRules.Add(rule1); var rule2 = new LoggingRule("*", LogLevel.Debug, fileTarget); config.LoggingRules.Add(rule2); // Step 5. Activate the configuration LogManager.Configuration = config; // Example usage Logger logger = LogManager.GetLogger("Example"); logger.Trace("trace log message"); logger.Debug("debug log message"); logger.Info("info log message"); logger.Warn("warn log message"); logger.Error("error log message"); logger.Fatal("fatal log message"); } }
Livello di log
The log levels, in descending order, are as follows:
Level | Typical Use |
---|---|
Fatal | Something bad happened; application is going down |
Error | Something failed; application may or may not continue |
Warn | Something unexpected; application will continue |
Info | Normal behavior like mail sent, user updated profile etc. |
Debug | For debugging; executed query, user authenticated, session expired |
Trace | For trace debugging; begin method X, end method X |
Da file configurazione
Come da documentazione github auto Reconfiguration, è possibile che la configurazione sia ricaricata al primo caricamento dell'eseguibile e durante l'esecuzione stessa, in quest'ultimo caso basta aggiungereautoReload="true"
al file di configurazione. Es.:<nlog autoReload="true"> ... </nlog>
Programmaticamente
Fonte: stackoverflowE' possibile cambiare runtime il livello di log, ad es impostando esternamente che si passi da livello Error a Debug.
- Non c'è bisogno di cambiare il file di configurazione che rimarrà nell'impostazione ritenuta di default;
- Runtime un metodo legge periodicamente il file di configurazione e di conseguenza si adeguerà il livello del Log.
Segue un metodo che imposta in modo fisso a Debug il livello del logging:
private void ReconfigureNLog() { try { foreach (var rule in LogManager.Configuration.LoggingRules) { rule.EnableLoggingForLevel(LogLevel.Debug); } //Call to update existing Loggers created with GetLogger() or //GetCurrentClassLogger() LogManager.ReconfigExistingLoggers(); } catch (Exception ex) { logger.Error("Ex.: {0}\r\n\r\n{1}", ex.Message, ex.StackTrace); } }
Schede valori parametri
Doc: [[1]]
Parametro: archiveEvery
Chiave | Significato |
Day | |
Hour | |
Minute | |
Month | |
None | |
Year |
Mappa e Links
C# | Librerie di terze parti PlugIn | Logging