Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

CSharp:NLog

From Aino Wiki

Jump to: navigation, search

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"/>
Per inserire ritorni accapo: ${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 aggiungere autoReload="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


Visual Studio

Author