System.out.println vs Logger

1. Perché logger?

Durante la scrittura di un programma o lo sviluppo di un'applicazione di produzione aziendale, l'utilizzo di System.out.println sembra essere l'opzione più semplice e facile. Non ci sono librerie extra da aggiungere al classpath e nessuna configurazione aggiuntiva da fare.

Ma l'utilizzo di System.out.println presenta diversi svantaggi che influiscono sulla sua usabilità in molte situazioni. In questo tutorial, discuteremo perché e quando vorremmo utilizzare un Logger sul semplice vecchio System.out e System.err . Mostreremo anche alcuni rapidi esempi utilizzando il framework di registrazione Log4J2.

2. Configurazione

Prima di iniziare, esaminiamo le dipendenze e le configurazioni di Maven richieste.

2.1. Dipendenze di Maven

Cominciamo aggiungendo la dipendenza Log4J2 al nostro pom.xml :

 org.apache.logging.log4j log4j-api 2.12.1   org.apache.logging.log4j log4j-core 2.12.1 

Possiamo trovare le ultime versioni di log4j-api e log4j-core su Maven Central.

2.2. Configurazione Log4J2

L'utilizzo di System.out non richiede alcuna configurazione aggiuntiva. Tuttavia, per utilizzare Log4J2, abbiamo bisogno di un file di configurazione log4j.xml :

Quasi tutti i framework di logger richiedono un certo livello di configurazione, a livello di programmazione o tramite un file di configurazione esterno, come il file XML mostrato qui.

3. Separazione dell'output del registro

3.1. System.out e System.err

Quando distribuiamo la nostra applicazione su un server come Tomcat, il server utilizza il proprio logger. Se usiamo System.out , i log finiscono in catalina.out . È molto più facile eseguire il debug della nostra applicazione se i log vengono inseriti in un file separato. Con Log4j2, dobbiamo includere un appender di file nella configurazione per salvare i log dell'applicazione in un file separato.

Inoltre, con System.out.println , non è possibile controllare o filtrare i registri da stampare. L'unico modo possibile per separare i registri è utilizzare System.out.println per i registri delle informazioni e System.err.println per i registri degli errori:

System.out.println("This is an informational message"); System.err.println("This is an error message");

3.2. Livelli di registrazione Log4J2

Negli ambienti di debug o di sviluppo, vogliamo vedere tutte le informazioni che l'applicazione sta stampando. Ma in un'applicazione aziendale live, più log significano un aumento della latenza. I framework di registrazione come Log4J2 forniscono più controlli a livello di registro:

  • FATALE
  • ERRORE
  • AVVISARE
  • INFORMAZIONI
  • DEBUG
  • TRACCIA
  • TUTTI

Utilizzando questi livelli, possiamo facilmente filtrare quando e dove stampare quali informazioni :

logger.trace("Trace log message"); logger.debug("Debug log message"); logger.info("Info log message"); logger.error("Error log message"); logger.warn("Warn log message"); logger.fatal("Fatal log message");

Possiamo anche configurare individualmente i livelli per ogni pacchetto di codice sorgente. Per maggiori dettagli sulla configurazione a livello di log, fare riferimento al nostro articolo sul log Java.

4. Scrittura di registri su file

4.1. Reindirizzamento di System.out e System.err

È possibile instradare System.out.println a un file utilizzando il metodo System.setOut () :

PrintStream outStream = new PrintStream(new File("outFile.txt")); System.setOut(outStream); System.out.println("This is a baeldung article");

E in caso di System.err :

PrintStream errStream = new PrintStream(new File("errFile.txt")); System.setErr(errStream); System.err.println("This is a baeldung article error");

Quando si reindirizza l'output a un file utilizzando System.out o System.err , non possiamo controllare la dimensione del file , quindi il file continua a crescere per la durata dell'esecuzione dell'applicazione.

Man mano che la dimensione del file aumenta, potrebbe essere difficile aprire o analizzare questi registri più grandi.

4.2. Accesso ai file con Log4J2

Log4J2 fornisce un meccanismo per scrivere sistematicamente i log nei file e anche eseguire il roll dei file in base a determinate politiche. Ad esempio, possiamo configurare il rollover dei file in base a uno schema data / ora :

Oppure possiamo eseguire il roll dei file in base alle dimensioni una volta raggiunta una determinata soglia :

...   %d{yyyy-MM-dd HH:mm:ss} %p %m%n      

5. Accesso a sistemi esterni

Come abbiamo visto nella sezione precedente, i framework di logger consentono di scrivere i log in un file. Allo stesso modo, forniscono anche appendici per inviare log ad altri sistemi e applicazioni . Ciò rende possibile inviare i log a un Kafka Stream o un database Elasticsearch utilizzando gli allegati Log4J anziché utilizzare System.out.println.

Fare riferimento al nostro articolo sull'appender Log4j per maggiori dettagli su come utilizzare tali appendici.

6. Personalizzazione dell'output del registro

Con l'uso dei logger, possiamo personalizzare quali informazioni devono essere stampate insieme al messaggio effettivo. Le informazioni che possiamo stampare includono il nome del pacchetto, il livello di log, il numero di riga, la data e l'ora, il nome del metodo, ecc.

While this would be possible with System.out.println, it would require a lot of manual work, while logging frameworks provide this functionality out of the box. With loggers, we can simply define a pattern in the logger configuration:

If we consider Log4J2 for our logger framework, there are several patterns that we can choose from or customize. Refer to the official Log4J2 documentation to learn more about them.

7. Conclusion

This article explains various reasons why to use a logger framework and why not to rely only on System.out.println for our application logs. While it is justifiable to use System.out.println for small test programs, we'd prefer not to use it as our main source of logging for an enterprise production application.

As always, the code examples in the article are available over on GitHub.