Introduzione a Log4j2 - Appendici, layout e filtri

1. Panoramica

La registrazione degli eventi è un aspetto critico dello sviluppo del software. Sebbene ci siano molti framework disponibili nell'ecosistema Java, Log4J è stato il più popolare da decenni, grazie alla flessibilità e semplicità che fornisce.

Log4j 2 è una versione nuova e migliorata del classico framework Log4j.

In questo articolo, introdurremo gli allegati, i layout e i filtri più comuni tramite esempi pratici.

In Log4J2, un appender è semplicemente una destinazione per gli eventi di registro; può essere semplice come una console e può essere complesso come qualsiasi RDBMS. I layout determinano come verranno presentati i log e i filtri filtrano i dati secondo i vari criteri.

2. Configurazione

Per comprendere diversi componenti di registrazione e la loro configurazione, impostiamo diversi casi d'uso di test, ciascuno costituito da un file di configurazione log4J2.xml e da una classe di test JUnit 4 .

Due dipendenze maven sono comuni a tutti gli esempi:

 org.apache.logging.log4j log4j-core 2.7   org.apache.logging.log4j log4j-core 2.7 test-jar test 

Oltre al pacchetto principale log4j-core , dobbiamo includere il 'test jar' che appartiene al pacchetto per ottenere l'accesso a una regola di contesto necessaria per testare file di configurazione con nomi insoliti.

3. Configurazione predefinita

ConsoleAppender è la configurazione predefinita del pacchetto principale Log4J 2 . Registra i messaggi nella console di sistema in un modello semplice:

Analizziamo i tag in questa semplice configurazione XML:

  • Configurazione : l'elemento radice di un file di configurazione di Log4J 2 e lo stato dell'attributo è il livello degli eventi Log4J interni, che si desidera registrare
  • Appendici : questo elemento contiene una o più appendici. Qui configureremo un appender che trasmette alla console di sistema in uscita standard
  • Logger : Questo elemento può consistere di più configurati Logger elementi. Con lo speciale tag Root , è possibile configurare un logger standard senza nome che riceverà tutti i messaggi di registro dall'applicazione. Ogni logger può essere impostato su un livello di log minimo
  • AppenderRef : questo elemento definisce un riferimento a un elemento dalla sezione Appenders . Pertanto l'attributo " ref " è collegato con un attributo " name " delle appendici

Lo unit test corrispondente sarà altrettanto semplice. Otterremo un riferimento al logger e stamperemo due messaggi:

@Test public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK() throws Exception { Logger logger = LogManager.getLogger(getClass()); Exception e = new RuntimeException("This is only a test!"); logger.info("This is a simple message at INFO level. " + "It will be hidden."); logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e); } 

4. ConsoleAppender con PatternLayout

Definiamo un nuovo appender per console con un modello di colore personalizzato in un file XML separato e includiamolo nella nostra configurazione principale:

Questo file utilizza alcune variabili di pattern che vengono sostituite da Log4J 2 in fase di esecuzione:

  • % style {…} {colorname} : Questo stamperà il testo nella prima coppia di parentesi ( ) in un dato colore ( colorname ).
  • % highlight {…} {FATAL = colorname,…} : è simile alla variabile "style". Ma è possibile assegnare un colore diverso per ogni livello di registro.
  • % date {format} : viene sostituita dalla data corrente nel formato specificato . Qui stiamo usando il formato DateTime "DEFAULT", " yyyy -MM-dd HH: mm: ss, SSS" .
  • % -5level : stampa il livello del messaggio di registro in modo allineato a destra.
  • % messaggio : rappresenta il messaggio di registro non elaborato

Ma esistono molte più variabili e formattazioni nel PatternLayout . Puoi fare riferimento alla documentazione ufficiale di Log4J 2.

Ora includeremo l'appender della console definito nella nostra configurazione principale:

Lo unit test:

@Test public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK() throws Exception { Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); logger.trace("This is a colored message at TRACE level."); ... } 

5. Appender file asincrono con JSONLayout e BurstFilter

A volte è utile scrivere messaggi di log in modo asincrono. Ad esempio, se le prestazioni dell'applicazione hanno la priorità sulla disponibilità dei log.

In questi casi d'uso, possiamo usare un AsyncAppender.

Per il nostro esempio, stiamo configurando un file di log JSON asincrono . Inoltre, includeremo un filtro burst che limita l'output del log a una velocità specificata:

   ...          ...        

Notare che:

  • Il JSONLayout è configurato in modo tale da scrivere un evento di log per riga
  • Il BurstFilter scenderà ogni evento con il livello 'INFO' e, soprattutto, se ci sono più di due di loro, ma ad un massimo di 10 eventi caduto
  • L'AsyncAppender è impostato su un buffer di 80 messaggi di log; successivamente, il buffer viene scaricato nel file di registro

Diamo un'occhiata allo unit test corrispondente. Stiamo riempiendo il buffer aggiunto in un ciclo, lasciamo che scriva su disco e ispezioniamo il conteggio delle righe del file di registro:

@Test public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER"); final int count = 88; for (int i = 0; i  0 && logEventsCount <= count); }

6. RollingFile Appender e XMLLayout

Successivamente, creeremo un file di registro a rotazione. Dopo una dimensione di file configurata, il file di registro viene compresso e ruotato.

Questa volta stiamo usando un layout XML :

Notare che:

  • L' appender RollingFile ha un attributo 'filePattern', che viene utilizzato per denominare i file di registro ruotati e può essere configurato con variabili segnaposto. Nel nostro esempio, dovrebbe contenere una data e un contatore prima del suffisso del file.
  • La configurazione predefinita di XMLLayout scriverà oggetti evento a log singolo senza l'elemento root.
  • Stiamo utilizzando una politica basata sulle dimensioni per ruotare i nostri file di registro.

La nostra classe di unit test sarà simile a quella della sezione precedente:

@Test public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER"); final int count = 88; for (int i = 0; i < count; i++) { logger.info( "This is rolling file XML message #{} at INFO level.", i); } }

7. Syslog Appender

Diciamo che dobbiamo inviare gli eventi registrati a una macchina remota sulla rete. Il modo più semplice per farlo usando Log4J2 sarebbe usare il suo Syslog Appender:

   ...     ...        

Gli attributi nel tag Syslog :

  • nome : definisce il nome dell'appender e deve essere univoco. Poiché possiamo avere più appenders Syslog per la stessa applicazione e configurazione
  • formato : può essere impostato su BSD o RFC5424 e i record Syslog verrebbero formattati di conseguenza
  • host e porta : il nome host e la porta della macchina server Syslog remota
  • protocollo : se utilizzare TCP o UPD
  • facility : in quale struttura Syslog verrà scritto l'evento
  • connectTimeoutMillis : periodo di tempo di attesa per una connessione stabilita, il valore predefinito è zero
  • reconnectionDelayMillis : tempo di attesa prima di ritentare la connessione

8. FailoverAppender

Now there may be instances where one appender fails to process the log events and we do not want to lose the data. In such cases, the FailoverAppender comes handy.

For example, if the Syslog appender fails to send events to the remote machine, instead of losing that data we might fall back to FileAppender temporarily.

The FailoverAppender takes a primary appender and number of secondary appenders. In case the primary fails, it tries to process the log event with secondary ones in order until one succeeds or there aren't any secondaries to try:

Let's test it:

@Test public void givenLoggerWithFailoverConfig_whenLog_thanOK() throws Exception { Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER"); Exception e = new RuntimeException("This is only a test!"); logger.trace("This is a syslog message at TRACE level."); logger.debug("This is a syslog message at DEBUG level."); logger.info("This is a syslog message at INFO level. This is the minimum visible level."); logger.warn("This is a syslog message at WARN level."); logger.error("This is a syslog message at ERROR level.", e); logger.fatal("This is a syslog message at FATAL level."); }

9. JDBC Appender

L'appender JDBC invia gli eventi di log a un RDBMS, utilizzando JDBC standard. La connessione può essere ottenuta utilizzando qualsiasi origine dati JNDI o qualsiasi factory di connessione.

La configurazione di base è costituita da DataSource o ConnectionFactory , ColumnConfigs e tableName :

Ora proviamo:

@Test public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK() throws Exception { Logger logger = LogManager.getLogger("JDBC_APPENDER"); final int count = 88; for (int i = 0; i < count; i++) { logger.info("This is JDBC message #{} at INFO level.", count); } Connection connection = ConnectionFactory.getConnection(); ResultSet resultSet = connection.createStatement() .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); int logCount = 0; if (resultSet.next()) { logCount = resultSet.getInt("ROW_COUNT"); } assertTrue(logCount == count); }

10. Conclusione

Questo articolo mostra esempi molto semplici di come è possibile utilizzare appendici di registrazione, filtri e layout diversi con Log4J2 e modi per configurarli.

Gli esempi che accompagnano l'articolo sono disponibili su GitHub.