+ All Categories
Home > Documents > log4net: un framework completo per il logging di applicazioni

log4net: un framework completo per il logging di applicazioni

Date post: 23-Jul-2015
Category:
Upload: infomedia-editori-coop
View: 367 times
Download: 0 times
Share this document with a friend
7
DEV DEVeloping Software Solutions — n. 152 — giugno-agosto 2007 log4net: un framework completo per il logging di applicazioni di Orazio Del Franco Uno strumento che non dovrebbe mai mancare sulla scrivania di uno sviluppatore. Orazio Del Franco Ha conseguito la laurea con lode in Informati- ca presso l’universit ` a degli studi di Salerno si occupa di proget- tazione e sviluppo di applicazioni distribuite in ambiente .NET e di applicazioni ASP , i suoi attuali interessi di ricer- ca sono verso la pro- grammazione distribuita e la multimedialit ` a.
Transcript
Page 1: log4net: un framework completo per il logging di applicazioni

DEV DEVeloping Software Solutions — n. 152 — giugno-agosto 2007

log4net: un framework completoper il logging di applicazionidi Orazio Del Franco

Uno strumento che non dovrebbe mai mancare sulla scrivania di uno sviluppatore.

Orazio Del FrancoHa conseguito la laureacon lode in Informati-ca presso l’universitadegli studi di Salernosi occupa di proget-tazione e sviluppo diapplicazioni distribuitein ambiente .NET e diapplicazioni ASP, i suoiattuali interessi di ricer-ca sono verso la pro-grammazione distribuitae la multimedialita.

Page 2: log4net: un framework completo per il logging di applicazioni

pubblicato suWWW.INFOMEDIA.IT

!stampa digitale da

Lulu Enterprises Inc.stores.lulu.com/infomedia

InfomediaInfomedia e l’impresa editoriale che da quasi venti an-ni ha raccolto la voce dei programmatori, dei sistemi-sti, dei professionisti, degli studenti, dei ricercatori e deiprofessori d’informatica italiani.Sono piu di 800 gli autori che hanno realizzato per le te-state Computer Programming, Dev, Login, Visual BasicJournal e Java Journal, molte migliaia di articoli tecnici,presentazioni di prodotti, tecnologie, protocolli, strumen-ti di lavoro, tecniche di sviluppo e semplici trucchi e stra-tagemmi. Oltre 6 milioni di copie distribuite, trentamilapagine stampate, fanno di questa impresa la piu grande edinfluente realta dell’editoria specializzata nel campo dellaprogrammazione e della sistemistica.In tutti questi anni le riviste Infomedia hanno vissuto del-la passione di quanti vedono nella programmazione nonsolo la propria professione ma un’attivita vitale e un verodivertimento.Nel 2009, Infomedia e cambiata radicalmente adottandoun nuovo modello aziendale ed editoriale e si e organiz-zata attorno ad una idea di Impresa Sociale di Comunita,partecipata da programmatori e sistemisti, separando leattivita di gestione dell’informazione gestite da un boardcomunitario professionale e quelle di produzione gesti-te da una impresa strumentale. Questo assetto e in lineacon le migliori esperienze internazionali e rende Infome-dia ancora di piu parte della Comunita nazionale deglisviluppatori di software.Infomedia e media-partner di manifestazioni ed eventi inambito informatico, collabora con molti dei piu impor-tanti editori informatici italiani come partner editoriale efornitore di servizi di localizzazione in italiano di testi inlingua inglese.

L’impaginazione automatica di questa rivista e realizzata al100% con strumenti Open Source usando OpenOffice,Emacs, BHL, LaTeX, Gimp, Inkscape e i linguaggi Lisp,Python e BASH

For copyright information about the contents of DEV,please see the section “Copyright” at the end of each ar-ticle if exists, otherwise ask authors. Infomedia contentsis© 2007 Infomedia and released as Creative Commons2.5 BY-NC-ND. Turing Club content is © 2007 TuringClub released as Creative Commons 2.5 BY-ND.

Le informazioni di copyright sul contenuto di DEV so-no riportate nella sezione “Copyright” alla fine di cia-scun articolo o vanno richieste direttamente agli autori.Il contenuto Infomedia e © 2007 Infomedia e rilasciatocon Licenza Creative Commons 2.5 BY-NC-ND. Il con-tenuto Turing Club e © 2007 Turing Club e rilasciatocon Licenza Creative Commons 2.5 BY-ND. Si applicanotutte le norme di tutela dei marchi e dei segni distintivi.

E in ogni caso ammessa la riproduzione parziale o tota-le dei testi e delle immagini per scopo didattico purchevengano integralmente citati gli autori e la completaidentificazione della testata.

Manoscritti e foto originali, anche se non pubblicati, nonsi restituiscono.

Contenuto pubblicitario inferiore al 45%.

La biografia dell’autore riportata nell’articolo e sulsito www.infomedia.it e di norma quella disponibi-le nella stampa dell’articolo o aggiornata a cu-ra dell’autore stesso. Per aggiornarla scrivere [email protected] o farlo in autonomia all’indirizzohttp://mags.programmers.net/moduli/biografia

Page 3: log4net: un framework completo per il logging di applicazioni

16>> DEV > n.152 giugno-agosto 2007

di Orazio Del Franco > [email protected]

programmazione .NET

17 <<DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

Il logging di applicazioni è un problema che prima o poi uno sviluppatore si trova ad affrontare, sia per-ché in alcune situazioni i debugger degli ambienti di sviluppo non ci aiutano molto, sia per risolvere più efficacemente i problemi che si incontrano una volta che il software è in produzione.

La tentazione di sviluppare una libreria flessibile e nello stesso tempo semplice da utilizzare è molto forte, ma quando si analizza il problema con la dovuta cura ci si rende conto che non è un compito semplice. Il framework che vi presento unisce la semplicità di utilizzo ad altre peculiarità come la possibilità di uso in ambiente multithread, rendendolo uno strumento valido sia per applicazioni monoutente sia per applicazioni più complesse come quelle multithread distribuite. log4net fonda le sue radici su “log4j” l’analogo framework per il logging in ambiente Java, ed è parte del progetto “Apache Logging Services” sotto la licenza “Apache Software License Version 2.0”. Nel resto dell’articolo dare-mo un’occhiata alle principali classi del framework come i Logger, i Layout e gli Appender, per poi soffermarci un istante sulla struttura del file di configurazione.

I logger

Le classi logger sono il cuore vero e proprio del framework

in quanto generano i messaggi di log che successivamente saranno visualizzati in varie forme (file di testo, e-mail, ecc.). Dobbiamo evidenziare una netta distinzione tra il messaggio di log generato ed il modo in cui viene memo-rizzato o visualizzato permanentemente, caratteristica che ci permette di estendere ulteriormente le potenzialità del framework. Ogni messaggio di log ha un livello con una determinata priorità (come è visibile nella Tabella 1) uti-lizzata dai logger per capire quali messaggi scartare e quali no, secondo regole che espliciteremo successivamente. I logger sono identificati dal loro nome (la distinzione avviene facendo differenza tra le maiuscole e le minuscole, come avviene per il C#) ed è possibile definirne più di uno per una determinata applicazione.Per tutti i logger presenti esiste una sorta di gerarchia (nello stesso modo come avviene nei namespace di .NET) che permette il trasferimento degli attributi da un logger padre ad un logger figlio. Ad esempio, supponiamo di avere un logger con nome “padre” ed un secondo logger con il nome “padre.figlio”; il secondo logger (“padre.figlio”) erediterà tutti gli attributi del primo logger (“padre”). Per definizione esiste un logger di base chiamato root da cui discendono tutti gli altri e non può essere ritrovato utilizzando il suo nome.Tutti i logger devono implementare l’interfaccia ILog :

public interface ILog

Uno strumento che non dovrebbe mai mancare sulla scrivania di uno sviluppatore.

log4net: un framework completo per il logging di applicazioni

Page 4: log4net: un framework completo per il logging di applicazioni

16>> DEV > n.152 giugno-agosto 2007

di Orazio Del Franco > [email protected]

programmazione .NET

17 <<DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

{

void Debug(object message);

void Info(object message);

void Warn(object message);

void Error(object message);

void Fatal(object message);

bool IsInfoEnabled { get; }

bool IsWarnEnabled { get; }

bool IsErrorEnabled { get; }

bool IsFatalEnabled { get; }

}

Come possiamo notare esiste un metodo per ogni livello di messaggio di log, ad esempio per il livello INFO esi-ste il metodo Info(...) nell’interfaccia, in più le proprietà IsXXXXXEnabled ci permettono di capire se quel dato logger è abilitato a quel livello. Come avete già intuito, anche ad ogni logger è collegato un livello (ereditato da un antenato se non specificato esplicitamente) che gli permette di decidere quali messaggi di log prendere in considerazione: infatti, accetterà solo i messaggi di priorità superiore o uguale a quella del livello a cui esso appartiene. Un esempio di questa logica è visibile nella Figura 1, ed è anche evidente come mai il livello OFF ha priorità massima mentre il livello ALL ha quella minima.Prima di passare alla descrizione della successiva classe, ci

resta da capire come ottenere una o più istanze della classe logger; il compito è egregiamente eseguito dai membri statici della classe LogManager:

public sealed class LogManager

{

public static ILog Exists(string name){…}

public static ILog[] GetCurrentLoggers(){…}

public static ILog GetLogger(string name){…}

}

Possiamo quindi avere una istanza di un logger nel seguente modo:

ILog log = LogManager.GetLogger(“nome del logger”);

La classe permette anche di eseguire un controllo sull’esi-stenza di un determinato logger tramite il metodo Exists(…) e di ritrovare tutti i logger con il metodo GetCurrentLoggers(). Nel prossimo paragrafo parleremo del layer successivo esplorandone le principali funzionalità.

Gli appender

I messaggi di log creati dai logger vengono gestiti dagli appender. In parole povere, gli appender scrivono fisicamente i messaggi di log in una determinata forma. Ogni logger può avere più di un appender dando la possibilità ad un unico messaggio di log di essere scritto su più destinazioni. Il framework contiene già delle implementazioni molto interessanti di appender sotto il namespace “log4net.Appender”, per una lista di alcuni di essi si faccia riferimento alla Tabella 2. Ovviamente, non è negata la possibilità di estendere quelli già presenti implementando l’interfaccia log4net.Appender.IAppender. Nel paragrafo precedente abbiamo parlato dell’ereditarietà dei logger dicendo che dava la possibilità di propagare determi-nate proprietà ai figli della gerarchia; gli appender, infatti, rientrano in quelle proprietà ereditate dando la possibilità ad un messaggio di log valido di essere propagato a tutti gli appender dei logger antenati; per evitare che questo accada è possibile comunque impostare il flag additivity dei logger

Esempio di filtraggio dei messaggi di log.FIGURA 1

Livelli di log abbinati con le rispettive priorità.TABELLA 1

Livello Priorità

OFF Alta

FATAL

ERROR

WARN

INFO

DEBUG

ALL Bassa

Il logging è un problema che prima o poi uno sviluppatore si trova ad

affrontare

Page 5: log4net: un framework completo per il logging di applicazioni

18>> DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

19 <<DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

Filtri Descrizione

DenyAllFilter In pratica nesun filtro

LevelMatchFilter Controlla che il messaggio di log sia dello stessa priorità specificata

LevelRangeFilter Controlla che il messaggio di log sia nel range di priorità specificato

LoggerMatchFilter Controlla che la parte iniziale del nome del logger coincida con la stringa specificata

PropertyFilter Controlla che la sottostringa specificata sia contenuta nel valore di una proprietà

StringMatchFilter Controlla che la sottostringa specificata sia contenuta nel messaggio di log

a false (per default il loro valore è impostato a true) tramite codice oppure nel file di configurazione, come è evidenziato qui di seguito:

<logger name=”Log4NetApplication_1” additivity=”false”>

In aggiunta, è possibile specificare dei filtri per ogni appender per limitare ulteriormente i messaggi di log che verranno successivamente scritti in uscita. I filtri sono implementati nel namespace log4net.Filter. Nella Tabella 3 sono riportati alcuni filtri con la logica ad essi collegata. Nel paragrafo successivo vedremo come è possibile personalizzare, per ogni singolo appender, l’output del messaggio di log.

I layout

Oltre a poter decidere dove inviare i messaggi di log, possiamo anche decidere il formato del messaggio stesso, utilizzando le classi layout. La sostanziale differenza tra un appender ed un layout è che il primo si occupa dell’invio del messaggio mentre il secondo di come è scritto il messag-

gio. Il framework contiene già dei layout predefiniti sotto il namespace log4net.Layout. Nella Tabella 4 sono riportati alcuni layout con una breve descrizione di ciò che ci per-mettono di fare. Ad esempio, se volessimo usare il layout log4net.Layout.PatternLayout possiamo formattare il testo in uscita in vari modi, visto che la classe supporta vari pattern. Infatti, volendo scrivere il nostro messaggio secondo questa formattazione:

[data] ([livello]) [nome logger] [messaggio]

dovremo scrivere la stringa di pattern come segue:

%date{dd MMM yyyy} (%level) %logger %message%newline

Con il pattern %date verrà stampata la data e il timestamp di creazione del messaggio, e tra parentesi graffe è possibile specificare la formattazione sia della data che del timestamp. Nel nostro caso verrà visualizzato il giorno (dd), il mese (MMM), e l’anno espresso a quattro cifre (yyyy).Il pattern %level stamperà il livello del messaggio di log (DEBUG, INFO, ecc.), mentre il pattern %logger stampa il nome del logger istanziato.Non ultimo, in termini di importanza, è il pattern %message che stampa il messaggio vero e proprio dell’evento di log (%newline va semplicemente a capo). Mettiamo concreta-mente mano ai file di configurazione per vedere con i nostri occhi come funziona il framework.

Il file di configurazione

La configurazione di log4net può avvenire in due modalità. La prima è configurarlo completamente via codice sorgente, rinunciando però alla flessibilità (tenendo in considerazione che è necessaria una ricompilazione del prodotto per ogni modifica della configurazione stessa). Un esempio banale, che mette in risalto il problema, è il dover aggiungere un altro logger alla nostra applicazione.

Alcuni Appender con le rispettive descrizioni.TABELLA 2

Appender Descrizione

AdoNetAppender Scrive i messaggi di log in un databse

AnsiColorTerminalAppender Scrive i messaggi di log su una finestra di terminale ANSI

AspNetTraceAppender Scrive i messaggi di log nel trace di ASP

ConsoleAppender Scrive i messaggi di log nella console dell’applicazione

EventLogAppender Scrive i messaggi di log negli eventi log di Windows

FileAppender Scrive i messaggi di log su un file

MemoryAppender Scrive i messaggi di log su un buffer residente in memoria

RemotingAppender Scrive i messaggi di log su un canale di comunicazione remoto utilizzando il remoting di .NET

SmtpAppender Invia i messaggi di log ad un indirizzo di e-mail

SmtpPickupDirAppender Scrive i messaggi di log come SMTP e li memorizza sul file system

TelnetAppender I client connessi via telnet riceveranno i messaggi di log

UdpAppender Invia i messaggi di log come datagrammi UDP

RollingFileAppender Scrive i messaggi di log su uno o più file (ha una logica di divisione del file)

Alcuni Filtri con le rispettive descrizioni.TABELLA 3

Page 6: log4net: un framework completo per il logging di applicazioni

18>> DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

19 <<DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

FIGURA 2La schermata principale dell’applicativo di esempio.

La seconda modalità di configurazione prevede il cari-camento a run-time di un file XML contenente tutti i parametri di configurazione. Ed è di questa soluzione che ci occuperemo. Per caricare un file di configurazione ci viene in aiuto il membro statico Configure della classe XmlConfigurator. Sup-ponendo di dover caricare un file di configurazione, di nome log4net.config, nella directory di esecuzione dell’applicativo, possiamo scrivere:

XmlConfigurator.Configure(

System.IO.File.Open(

AppDomain.CurrentDomain.BaseDirectory +

“Log4Net.config”,

System.IO.FileMode.Open

)

);

Il tag XML che il framework utilizza per la configurazione è <log4net>

<?xml version=”1.0” encoding=”utf-8” ?>

<log4net>

</log4net>

Gli appender possono essere definiti prima e referenziati dopo dai logger; volendo costruire un appender per il logger root che scriva in un file distinto in base alla data, inseriamo:

<appender name=”AppenderFileRollingRoot”

type=”log4net.Appender.RollingFileAppender”>

<param name=”File” value=”LogFileRollingRoot.”/>

<param name=”AppendToFile” value=”true”/>

<param name=”RollingStyle” value=”Date”/>

<param name=”DatePattern” value=”yyyyMMdd”/>

<param name=”StaticLogFileName” value=”false”/>

</appender>

Il parametro RollingStyle indica come eseguire la suddivisione del file. In questo caso la discriminante è la data, mentre DatePattern è usato per la generazione del nome del file di log e il parametro File specifica il path dove andare a me-morizzare il file stesso. Per referenziare un appender da un logger è sufficiente inserire il tag <appender-ref> come si vede qui di seguito:

<root>

<level value=”ALL”/>

<appender-ref ref=”AppenderFileRollingRoot”/>

</root>

In questo caso viene anche specificato il livello dei messaggi di log trattati da root (impostato ad ALL): cioè non effettua nessun filtro sui messaggi. Per default il valore è impostato su DEBUG. Il logger che segue, invece, evita l’ereditarietà da parte di root impostando la proprietà additivity a false.

<logger name=”LoggerNoEredita” additivity=”false”>

<level value=”ERROR” />

<appender-ref ref=”AppenderInFile”/>

</logger>

Il progetto di esempio

L’esempio allegato all’articolo mette in pratica le cose de-scritte fino ad ora. La schermata principale è composta da quattro tasti (vedi Figura 2), il primo serve per caricare il file di configurazione, il secondo dà una dimostrazione della proprietà di ereditarietà dei logger, il terzo evidenzia come è possibile eliminare l’ereditarietà mentre il quarto ci permette

I messaggi di log creati dai logger vengono gestiti dagli appender

FIGURA 3 Risultato ottenuto con l’ereditarietà del logger.

Page 7: log4net: un framework completo per il logging di applicazioni

20>> DEV > n.152 giugno-agosto 2007

log4net

programmazione .NET

Alcuni Layout con le rispettive descrizioni.TABELLA 5

di vedere come utilizzare più appender relativi ad un logger. Per dare una dimostrazione sull’ereditarietà, viene carica-to il logger LoggerEredita che usa l’appender AppenderInFile. Utilizzandolo quindi, dovremo scrivere i messaggi nel file “file-di-log.txt” per via di AppenderInFile e per l’ereditarie-tà da root nel file che inizia per “LogFileRollingRoot”. Ed infatti è quello che succede in Figura 3. Per far in modo che la caratteristica dei logger non sia attivata, è sufficiente impostare la proprietà additivity a false: è quello che succe-de nel logger LoggerNoEredita. Infatti, premendo il tasto “Logger Non Eredita” dell’applicativo di prova otteniamo la scrittura del file “file-di-log.txt”, mentre il file che inizia per “LogFileRollingRoot” non viene scritto, come è visibile nella Figura 4. Dalla stessa Figura 4 notiamo anche che i messaggi di log del livello inferiore a ERROR non sono stati scritti nel file. Ciò accade perché al logger LoggerNoEredita è stato impostato un livello sui messaggi.

<logger name=”LoggerNoEredita” additivity=”false”>

<level value=”ERROR” />

L’ultimo esempio che vedremo è quello di un logger che ha due appender, il che significa che generando una sola volta i messaggi di log riusciamo a scrivere (in questo caso) su due file differenti, come si vede dalla Figura 5.

Conclusioni

Abbiamo dato uno sguardo alle potenzialità della libreria sia dal punto di vista di espandibilità sia di utilizzo vero e proprio. Vi ricordo che è possibile scaricare la libreria all’indirizzo http://logging.apache.org/log4net/ dove troverete anche la documentazione in linea e molti esempi interes-santi. Alla prossima.

Layout Descrizione

ExceptionLayout Rende visibile solo il testo di eccezione del messaggio (deve essere usato solo con appender che utilizzano multipli layout

PatternLayout Formatta il messaggio con i flag messi a disposizione

RawTimeStampLayout Estrae il timestamp dal messaggio

SimpleLayout.cs Semplice formattazione del messaggio [livello] – [messaggio]

XMLLayout Formatta il messaggio come un elemento XML

XmlLayoutSchemaLog4j Formatta i messaggio come elementi XML in accordo con il dtd di log4j

FIGURA 4Risultato ottenuto senza l’ereditarietà del logger.

FIGURA 5 Risultato ottenuto con appender multipli.

Orazio Del Franco

Ha conseguito la laurea con lode in Informatica presso l’università degli studi di Salerno si occupa di progettazione e sviluppo di applicazioni distribuite in ambiente .NET e di applicazioni ASP, i suoi attuali interessi di ricerca sono verso la programmazione distribuita e la multimedialità.

Download del progetto

Scarica il progetto completo di questo articolo all'indirizzo:ftp://ftp.infomedia.it/pub/DEV./Listati/Dev152/log4net.zip


Recommended