Sei sulla pagina 1di 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 luniversita 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 multimedialita.

pubblicato su WWW.INFOMEDIA.IT stampa digitale da Lulu Enterprises Inc. stores.lulu.com/infomedia


Infomedia
` Infomedia e limpresa editoriale che da quasi venti anni ha raccolto la voce dei programmatori, dei sistemisti, dei professionisti, degli studenti, dei ricercatori e dei professori dinformatica italiani. Sono pi` di 800 gli autori che hanno realizzato per le teu state Computer Programming, Dev, Login, Visual Basic Journal e Java Journal, molte migliaia di articoli tecnici, presentazioni di prodotti, tecnologie, protocolli, strumenti di lavoro, tecniche di sviluppo e semplici trucchi e stratagemmi. Oltre 6 milioni di copie distribuite, trentamila pagine stampate, fanno di questa impresa la pi` grande ed u inuente realt` delleditoria specializzata nel campo della a programmazione e della sistemistica. In tutti questi anni le riviste Infomedia hanno vissuto della passione di quanti vedono nella programmazione non solo la propria professione ma unattivit` vitale e un vero a divertimento. ` Nel 2009, Infomedia e cambiata radicalmente adottando ` un nuovo modello aziendale ed editoriale e si e organizzata attorno ad una idea di Impresa Sociale di Comunit` , a partecipata da programmatori e sistemisti, separando le attivit` di gestione dellinformazione gestite da un board a comunitario professionale e quelle di produzione gesti` te da una impresa strumentale. Questo assetto e in linea con le migliori esperienze internazionali e rende Infomedia ancora di pi` parte della Comunit` nazionale degli u a sviluppatori di software. ` Infomedia e media-partner di manifestazioni ed eventi in ambito informatico, collabora con molti dei pi` imporu tanti editori informatici italiani come partner editoriale e fornitore di servizi di localizzazione in italiano di testi in lingua inglese.

Limpaginazione automatica di questa rivista e realizzata al ` 100% 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 article if exists, otherwise ask authors. Infomedia contents is 2007 Infomedia and released as Creative Commons 2.5 BY-NC-ND. Turing Club content is 2007 Turing Club released as Creative Commons 2.5 BY-ND. Le informazioni di copyright sul contenuto di DEV sono riportate nella sezione Copyright alla ne di ciascun articolo o vanno richieste direttamente agli autori. Il contenuto Infomedia e 2007 Infomedia e rilasciato ` con Licenza Creative Commons 2.5 BY-NC-ND. Il contenuto Turing Club e 2007 Turing Club e rilasciato ` con Licenza Creative Commons 2.5 BY-ND. Si applicano tutte le norme di tutela dei marchi e dei segni distintivi. ` E in ogni caso ammessa la riproduzione parziale o totale dei testi e delle immagini per scopo didattico purch e vengano integralmente citati gli autori e la completa identicazione della testata. Manoscritti e foto originali, anche se non pubblicati, non si restituiscono. Contenuto pubblicitario inferiore al 45%. La biograa dellautore riportata nellarticolo e sul sito www.infomedia.it e di norma quella disponibi` le nella stampa dellarticolo o aggiornata a cura dellautore stesso. Per aggiornarla scrivere a info@infomedia.it o farlo in autonomia allindirizzo http://mags.programmers.net/moduli/biograa

programmazione .NET
di Orazio Del Franco > orazio.delfranco@infomedia.it

log4net: un framework completo per il logging di applicazioni


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

I
>> 16

l logging di applicazioni un problema che prima o poi uno sviluppatore si trova ad affrontare, sia perch 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 lanalogo 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 dellarticolo daremo unocchiata 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 memorizzato 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) utilizzata 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 linterfaccia ILog :
public interface ILog

DEV > n.152 giugno-agosto 2007

programmazione .NET
log4net

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);

FIGURA 1

Esempio di filtraggio dei messaggi di log.

{ 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; } }

La classe permette anche di eseguire un controllo sullesistenza 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 linterfaccia log4net.Appender.IAppender. Nel paragrafo precedente abbiamo parlato dellereditariet dei logger dicendo che dava la possibilit di propagare determinate 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

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

Come possiamo notare esiste un metodo per ogni livello di messaggio di log, ad esempio per il livello INFO esiste il metodo Info(...) nellinterfaccia, 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
DEV > n.152 giugno-agosto 2007

TABELLA 1
Livello OFF FATAL ERROR WARN INFO DEBUG ALL

Livelli di log abbinati con le rispettive priorit. Priorit Alta

Bassa

17 <<

programmazione .NET
log4net

TABELLA 2
Appender

Alcuni Appender con le rispettive descrizioni. Descrizione Scrive i messaggi di log in un databse Scrive i messaggi di log su una finestra di terminale ANSI Scrive i messaggi di log nel trace di ASP Scrive i messaggi di log nella console dellapplicazione Scrive i messaggi di log negli eventi log di Windows Scrive i messaggi di log su un file Scrive i messaggi di log su un buffer residente in memoria Scrive i messaggi di log su un canale di comunicazione remoto utilizzando il remoting di .NET Invia i messaggi di log ad un indirizzo di e-mail Scrive i messaggi di log come SMTP e li memorizza sul file system I client connessi via telnet riceveranno i messaggi di log Invia i messaggi di log come datagrammi UDP Scrive i messaggi di log su uno o pi file (ha una logica di divisione del file)

AdoNetAppender AnsiColorTerminalAppender AspNetTraceAppender ConsoleAppender EventLogAppender FileAppender MemoryAppender RemotingAppender SmtpAppender SmtpPickupDirAppender TelnetAppender UdpAppender RollingFileAppender

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, loutput del messaggio di log.

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 permettono 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

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 dellinvio del messaggio mentre il secondo di come scritto il messagTABELLA 3
Filtri DenyAllFilter LevelMatchFilter LevelRangeFilter LoggerMatchFilter Alcuni Filtri con le rispettive descrizioni. Descrizione In pratica nesun filtro Controlla che il messaggio di log sia dello stessa priorit specificata Controlla che il messaggio di log sia nel range di priorit specificato Controlla che la parte iniziale del nome del logger coincida con la stringa specificata Controlla che la sottostringa specificata sia contenuta nel valore di una propriet Controlla che la sottostringa specificata sia contenuta nel messaggio di log

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 lanno 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 dellevento di log (%newline va semplicemente a capo). Mettiamo concretamente 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.
DEV > n.152 giugno-agosto 2007

PropertyFilter

StringMatchFilter

>> 18

programmazione .NET
log4net

<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 memorizzare il file stesso. Per referenziare un appender da un logger sufficiente inserire il tag <appender-ref> come si vede qui di seguito: FIGURA 2
La schermata principale dellapplicativo di esempio.
<root> <level value=ALL/> <appender-ref ref=AppenderFileRollingRoot/> </root>

La seconda modalit di configurazione prevede il caricamento 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. Supponendo di dover caricare un file di configurazione, di nome log4net.config, nella directory di esecuzione dellapplicativo, possiamo scrivere:
XmlConfigurator.Configure( System.IO.File.Open( AppDomain.CurrentDomain.BaseDirectory + Log4Net.config, System.IO.FileMode.Open ) );

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 lereditariet 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
Lesempio allegato allarticolo mette in pratica le cose descritte 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 lereditariet mentre il quarto ci permette

I messaggi di log creati dai logger vengono gestiti dagli appender

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/>

FIGURA 3

Risultato ottenuto con lereditariet del logger.

DEV > n.152 giugno-agosto 2007

19 <<

programmazione .NET
log4net

FIGURA 4

Risultato ottenuto senza lereditariet del logger.

di vedere come utilizzare pi appender relativi ad un logger. Per dare una dimostrazione sullereditariet, viene caricato il logger LoggerEredita che usa lappender AppenderInFile. Utilizzandolo quindi, dovremo scrivere i messaggi nel file file-di-log.txt per via di AppenderInFile e per lereditariet 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 succede nel logger LoggerNoEredita. Infatti, premendo il tasto Logger Non Eredita dellapplicativo 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 />

FIGURA 5

Risultato ottenuto con appender multipli.

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 allindirizzo http://logging.apache.org/log4net/ dove troverete anche la documentazione in linea e molti esempi interessanti. Alla prossima.

Download del progetto


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

Orazio Del Franco


Ha conseguito la laurea con lode in Informatica presso luniversit 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.

Lultimo 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.

TABELLA 5
Layout ExceptionLayout PatternLayout

Alcuni Layout con le rispettive descrizioni.

Descrizione Rende visibile solo il testo di eccezione del messaggio (deve essere usato solo con appender che utilizzano multipli layout Formatta il messaggio con i flag messi a disposizione Estrae il timestamp dal messaggio Semplice formattazione del messaggio [livello] [messaggio] Formatta il messaggio come un elemento XML Formatta i messaggio come elementi XML in accordo con il dtd di log4j

RawTimeStampLayout SimpleLayout.cs XMLLayout XmlLayoutSchemaLog4j

>> 20

DEV > n.152 giugno-agosto 2007