Log4J è una libreria Java sviluppata dalla Apache Software Foundation che permette di mettere a punto un ottimo sistema di logging per tenere sotto controllo il comportamento di una applicazione, sia in fase di sviluppo che in fase di test e messa in opera del prodotto finale. L'ultima versione stabile disponibile è la 1.2.15.
Il modo migliore per configurare la libreria, ed utilizzarla in un'applicazione, è scrivere un file di properties. Il file può anche essere scritto in formato xml.
La struttura tipica di un file di configurazione è la seguente:
Listato 1. Struttura tipica di un file di configurazione
#LOGGER
log4j.rootCategory=DEBUG, APPENDER_OUT, APPENDER_FILE
#APPENDER_OUT
log4j.appender.APPENDER_OUT=org.apache.log4j.ConsoleAppender
log4j.appender.APPENDER_OUT.layout=org.apache.log4j.PatternLayout
log4j.appender.APPENDER_OUT.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
#APPENDER_FILE
log4j.appender.APPENDER_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.APPENDER_FILE.File=mioLog.log
log4j.appender.APPENDER_FILE.MaxFileSize=100KB
log4j.appender.APPENDER_FILE.MaxBackupIndex=1
log4j.appender.APPENDER_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.APPENDER_FILE.layout.ConversionPattern=%p %t %c - %m%n
Questa configurazione permette di scrivere i log sia sulla console che su di un file di testo.
Il file di configurazione è costituito da due componenti principali: Logger e Appender.
Ciascun Logger viene associato ad un livello di log. I livelli disponibili, in ordine gerarchico, sono i seguenti: DEBUG, INFO, WARN, ERROR, FATAL.
Nell'esempio il Logger viene impostato con livello DEBUG e gli vengono associati due Appender: APPENDER_OUT e APPENDER_FILE. Ciascun Appender definisce un indirizzamento del flusso.
Log4j mette a disposizione diversi Appender. I più utilizzati sono i seguenti:
- ConsoleAppender che permette di scrivere sulla console dell'applicazione;
- FileAppender che permette di scrivere su file;
- RollingFileAppender che permette di scrivere su un file di testo definendone la lunghezza massima. Quando la lunghezza massima è raggiunta, il file è rinominato aggiungendo un numero progressivo al nome del file;
- DailyRollingFileAppender che permette di scrivere su un file di testo definendone un intervallo di tempo massimo. Quando il tempo scade, viene creato un altro file;
- SocketAppender che permette di scrivere su un socket utilizzando il protocollo TCP/IP;
- JMSAppender che permette di scrivere su una coda JMS;
- SMTPAppender che permette di inviare mail utilizzando il protocollo SMTP e JavaMail.
Ciascun Appender naturalmente ha bisogno di alcuni parametri di configurazione specifici. Ad esempio, il FileAppender ha bisogno della directory e del nome del file di log sul quale scrivere, mentre l'SMTPAppender ha bisogno dell'indirizzo del server SMTP.
Nell'esempio il LOGGER_OUT è di tipo Console mentre il LOGGER_OUT è di tipo RollingFile.
A ciascun Appender è possibile associare un Layout mediante il quale è possibile specificare il modo in cui le informazioni devono essere formattate.
Log4J mette a disposizione diverse tipologie di Layout predefinite. Le principali sono le seguenti:
- SimpleLayout che produce stringhe di testo semplice;
- PatternLayout che produce stringhe di testo formattate secondo un pattern definito nel file di configurazione;
- HTMLLayout che produce un layout in formato HTML;
- XMLLayout che produce un layout in formato XML.
Se il layout non viene specificato, log4j utilizza il SimpleLayout.
Ora che abbiamo scritto il file di configurazione, vediamo con un semplicissimo esempio come è possibile utilizzare log4j nella nostra applicazione.
Listato 2. Esempio di utilizzo di Log4J
public class MyLog4J {
public static void main(String[] args) {
//carico il file di configurazione
PropertyConfigurator.configure("myLog.properties");
//ottengo instanza del log
Logger log = Logger.getLogger(MyLog4J.class);
log.debug("Test Livello DEBUG");
log.info("Test Livello INFO");
log.warn("Test Livello WARNING");
log.error("Test Livello ERROR");
log.fatal("Test Livello FATAL");
}
}
Mediante il metodo statico configure
, della classe PropertyConfigurator
, viene caricato il file di configurazione. Quest'operazione deve essere fatta solo una volta all'avvio dell'applicazione e non è necessaria qualora il file viene chiamato con il nome di default log4j.properties, poiché log4j si occupa automaticamente di invocare il metodo.
Con il metodo statico getLogger
della classe Logger otteniamo un'istanza della classe mediante la quale possiamo invocare uno dei metodi disponibili corrispondenti ai diversi livelli di log predefiniti.
In entrambi i casi log4j utilizza il pattern Singleton
per cui, se in vari punti della applicazione si invoca un Logger con lo stesso nome, si otterrà sempre la stessa istanza.
Ad esempio scrivendo:
Logger log1 = Logger.getLogger("myLog");
Logger log2 = Logger.getLogger("myLog");
otteniamo due variabili che puntano alla stessa istanza.
Se eseguiamo l'esempio notiamo che sia sulla console, sia sul file di log, vengono stampate le 5 voci perché il livello definito nel file di configurazione è DEBUG che si trova al gradino più basso della gerarchia. Se impostiamo il livello ad ERROR, ad esempio, noteremo come vengano stampati esclusivamente i messaggi di ERROR e FATAL.
Molto spesso il log viene utilizzato in fase di sviluppo per analizzare il corretto funzionamento dell'applicazione. Quando l'applicazione è terminata, è opportuno monitorare esclusivamente gli eventi più gravi.
Con log4j ciò è possibile semplicemente modificando il file di configurazione.
Ad esempio, nella nostra applicazione, potremo prevedere log di livello DEBUG per tenere traccia di alcune informazioni utili durante lo sviluppo, come il valore di particolari variabili, e log di livello ERROR per tenere traccia di informazioni utili quando l'applicazione è finita.
Nel momento in cui l'applicazione è pronta per essere utilizzata basta soltanto modificare il livello di log (sostituire DEBUG con ERROR) nel file di configurazione e tutto continua a funzionare senza dover modificare i sorgenti e ricompilarli.