Articles

Come funziona Log4J2: 10 Modi per ottenere il massimo da esso

Log4j2 è la versione aggiornata della libreria log4j popolare e influente, ampiamente utilizzato in tutto l’ecosistema Java per tanti anni. Versione 2.x mantiene tutte le funzionalità di registrazione del suo predecessore e si basa su tale base con alcuni miglioramenti significativi, specialmente nell’area delle prestazioni.

E, naturalmente, dato quanto la registrazione strumentale sia per qualsiasi applicazione, sia per scopi di audit che di debug, scegliere una libreria di registrazione solida è una decisione abbastanza importante.

Nelle sezioni seguenti, daremo un’occhiata al motivo per cui la libreria log4j2 è un’ottima scelta per questa decisione e come possiamo usarla in un’applicazione.

Configurazione di base Log4j2

Per iniziare a utilizzare log4j2 nel progetto, è sufficiente aggiungere la dipendenza log4j-core. Se stai usando Maven, puoi aggiungere la seguente dipendenza al tuo pom.file xml:

E se stai lavorando con Gradle, devi aggiungere la dipendenza alla build.file gradle:

dependencies { compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.8.2'}

Fuori dalla scatola, log4j2 fornirà automaticamente una configurazione semplice, se non ne definisci esplicitamente uno tu stesso. La configurazione predefinita registra alla console a un livello di livello di ERRORE o superiore.

Per avviare la registrazione dei messaggi utilizzando questa configurazione di base, tutto ciò che devi fare è ottenere un’istanza di Logger utilizzando la classe LogManager:

private static Logger logger = LogManager.getLogger(MyService.class);

Quindi è possibile utilizzare l’oggetto logger con metodi corrispondenti al livello di log desiderato:

logger.error("This is an error message");

Personalizzazione della configurazione Log4j2

Una configurazione log4j2 personalizzata può essere creata a livello di codice o tramite un file di configurazione.

La libreria supporta i file di configurazione scritti in XML, JSON, YAML, così come il .formato delle proprietà. Qui, useremo XML per discutere principalmente tutti gli esempi.

In primo luogo, è possibile ignorare la configurazione predefinita semplicemente creando un log4j2.file xml sul percorso di classe:

diamo uno sguardo più da vicino il tag utilizzato in questa configurazione semplice:

  • Configurazione: l’elemento principale di un log4j2 file di configurazione; l’attributo di stato rappresenta il livello al cui interno log4j eventi devono essere registrati
  • Appender: questo elemento contiene un elenco di appender; nel nostro esempio, un appender corrispondente alla console di Sistema è definito
  • Logger: questo elemento contiene un elenco di Logger istanze. L’elemento Root è un logger standard che emette tutti i messaggi

È importante capire che il logger Root è obbligatorio in ogni configurazione. Come discusso, se non ne fornisci uno, verrà automaticamente configurato di default con un appender della console e il livello di log degli errori.

Configurazione degli appender

Nell’architettura log4j2, un appender è fondamentalmente responsabile dell’invio di messaggi di log a una determinata destinazione di output.

Ecco alcuni dei tipi più utili di appenders forniti dalla libreria:

  • ConsoleAppender – registra i messaggi della console di Sistema
  • FileAppender – scrive messaggi di log in un file
  • RollingFileAppender – scrive i messaggi in sequenza del file di log
  • JDBCAppender – utilizza un database relazionale, per i registri
  • AsyncAppender – contiene un elenco di altri appender e determina i registri per questi per essere scritto in un thread separato

Per capire meglio come appender lavoro, diamo un’occhiata ad alcuni esempi di configurazione.

Il RollingFileAppender

Registrare tutto in un singolo file non è, ovviamente, l’ideale. Di solito è molto meglio rotolare regolarmente il file di registro attivo, che è esattamente ciò che fa RollingFileAppender.

Potrai anche andare oltre le basi con questo tipo di appender e configurare sia una politica di attivazione personalizzata che una strategia di rollover.

Il criterio di attivazione determina quando viene eseguito il rollover del file di registro, ovvero viene creato un nuovo file, mentre la strategia di rollover determina come viene eseguito il rollover del file.

Come un esempio veloce, andiamo a configurare un appender che crea un nuovo file di registro sulla base di 3 criteri:

  • OnStartupTriggeringPolicy – un nuovo file di registro viene creato ogni volta che la JVM inizia
  • TimeBasedTriggeringPolicy – il file di log è rotolato basato su un gruppo data/ora pattern
  • SizeBasedTriggeringPolicy – il file è rotolato quando si raggiunge una certa dimensione

La configurazione di usare il DefaultRolloverStrategy:

Puoi vedere quanto sia flessibile questo stile di configurazione e come puoi sintonizzare la semantica esatta della tua strategia di registrazione – fino all’ultimo dettaglio.

JDBCAppender

Come suggerisce il nome, questo appender utilizza JDBC per scrivere log in un database relazionale.

Per questa configurazione, è necessario definire una ConnectionSource, che può essere un’origine dati JNDI o una ConnectionFactory personalizzata. Il logger utilizza ConnectionSource per ottenere connessioni JDBC, motivo per cui è importante utilizzare un pool di connessioni per prestazioni migliori.

Per configurare l’appender nel file di configurazione XML, è possibile utilizzare il tag JDBC:

Come si può vedere, l’origine dati JNDI viene semplicemente specificata utilizzando l’attributo jndiName del tag DataSource. Insieme a ConnectionSource, è possibile definire la tabella e le colonne da utilizzare per la memorizzazione dei dati di registro.

Il FailoverAppender

Infine, diamo un’occhiata al FailoverAppender; questo definisce un appender primario e un elenco di backup che interverranno per gestire la registrazione nel caso in cui il primario fallisce.

Ad esempio, è possibile configurare un JDBCAppender primario, con un secondario the RollingFile e Console appenders nel caso in cui non sia possibile stabilire una connessione al database:

In un ambiente di produzione, avere una strategia di failover per il meccanismo di registrazione è sempre una buona idea.

Configurazione dei layout

Mentre gli appenditori sono responsabili dell’invio di messaggi di log a una destinazione, i layout vengono utilizzati dagli appenditori per definire come verrà formattato un messaggio di log.

Ecco una breve descrizione di alcuni dei layout più comunemente utilizzati che log4j2 offre:

  • PatternLayout – consente di configurare i messaggi in base a un modello di Stringa
  • JsonLayout – definisce un formato JSON per i messaggi di log
  • CsvLayout – può essere utilizzato per creare messaggi in formato CSV

PatternLayout

Il primo tipo di layout stiamo andando a guardare è il PatternLayout. Questa è una soluzione abbastanza flessibile che ti dà un sacco di controllo sull’output finale del messaggio di log.

Il meccanismo è guidato principalmente da un modello di conversione che contiene gli specificatori di conversione. Ogni identificatore inizia con il segno%, seguito da modificatori che controllano elementi come la larghezza e il colore del messaggio e un carattere di conversione che rappresenta il contenuto, come la data o il nome del thread.

Diamo un’occhiata a un esempio di configurazione di un PatternLayout che configura le linee di log per mostrare la data, il thread, il livello di log e il messaggio di log con colori diversi per diversi livelli di log:

Questi specificatori meritano di essere compresi in dettaglio, quindi diamo uno sguardo più da vicino:

  • %d{HH:mm:ss.SSS} – uscite la data del log eventi nel formato specificato
  • %t – uscite il nome del thread
  • %livello – visualizza il livello di log del messaggio
  • %evidenziare {livello} – è utilizzato per definire i colori per il modello tra parentesi graffe
  • %msg%n – uscite il messaggio di log

L’uscita di visualizzare il registro livelli con diversi colori:

Si può leggere di più circa la serie completa di opzioni per la definizione di modelli in log4j2 documentazione PatternLayout.

Il JsonLayout

Registrazione dei dati utilizzando il formato JSON ha alcuni vantaggi significativi, come rendere i registri più facili da analizzare ed elaborati da strumenti di registrazione lungo la linea.

Per configurare il JSONLayout in log4j2, puoi semplicemente definire il tag corrispondente:

<JSONLayout complete="true" compact="false"/>

Setting complete=true produrrà un documento JSON ben formato:

Per essere in grado di produrre JSON, devi anche aggiungere la libreria jackson-databind al classpath:

Configurazione dei filtri

I filtri in log4j2 vengono utilizzati per determinare se un messaggio di log deve essere elaborato o saltato.

È possibile configurare un filtro per l’intera configurazione o a livello di logger o appender.

La libreria fornisce diversi tipi di filtri che possono essere utilizzati:

  • BurstFilter – controlla il numero di eventi di log ammessi
  • DynamicThresholdFilter – filtri di linee di log in base a determinati attributi
  • RegexFilter – filtri messaggi, a seconda che corrispondono a una espressione regolare

È possibile, per esempio, controllare la velocità con cui l’applicazione è consentita per registrare i dati.

Per fare, puoi impostare un BurstFilter e applicarlo ai messaggi INFO:

<Filters> <BurstFilter level="INFO" rate="10" maxBurst="100"/></Filters>

Questo ignorerà selettivamente il controllo del traffico dei messaggi a livello di informazioni e al di sotto, assicurandosi di non perdere nessuno dei messaggi più importanti sopra le INFORMAZIONI.

In questo caso, rate definisce la media dei messaggi di log che devono essere elaborati al secondo e maxBurst controlla la dimensione complessiva del traffico prima che il filtro inizi a eliminare le voci di log.

Allo stesso modo, possiamo configurare l’appender solo per accettare messaggi di log che corrispondono a una specifica espressione regolare:

<Appenders> <JDBC name="JDBCAppender"> <RegexFilter regex="*jdbc*" onMatch="ACCEPT" onMismatch="DENY"/> </JDBC></Appenders>

Nel complesso, questo meccanismo di filtraggio può essere utilizzato con grande precisione per assicurarsi che ogni appender nella configurazione di registrazione complessiva stia monitorando le informazioni giuste. La capacità di registrare solo informazioni molto specifiche e pertinenti porta generalmente a un’analisi delle cause alla radice molto rapida, specialmente nei sistemi complessi, specialmente se abbinata a un potente strumento di visualizzazione dei log.

Configurazione dei logger

Oltre al logger Root, possiamo anche definire elementi Logger aggiuntivi con diversi livelli di log, appendici o filtri. Ogni Logger richiede un nome, che può essere usato per fare riferimento è:

<Loggers> <Logger name="RollingFileLogger"> <AppenderRef ref="RollingFileAppender" /> </Logger></Loggers>

Per scrivere i messaggi di log di utilizzo di questo particolare Strumento, è possibile ottenere un riferimento ad esso utilizzando il LogManager classe:

Logger rfLogger = LogManager.getLogger("RollingFileLogger");rfLogger.info("User info updated");

un Altro modo molto comune per la struttura della gerarchia di questi logger è basato sulla classe Java:

Logger logger = LogManager.getLogger(MyServiceTest.class);

Utilizzando le Ricerche

le Ricerche rappresentano un modo per inserire i valori esterni in log4j2 di configurazione. Abbiamo già visto un esempio della ricerca della data nella configurazione di RollingFileAppender:

<RollingFile name="RollingFileAppender" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">

La ricerca insert{date:yyy-MM} inserirà la data corrente nel nome del file, mentre il precedente character è un carattere di escape, per inserire l’espressione di ricerca nell’attributo filePattern.

È anche possibile inserire il Sistema di valori di proprietà in log4j2 di configurazione utilizzando il formato ${sys:nome_proprietà}:

<File name="ApplicationLog" fileName="${sys:path}/app.log"/>

un Altro tipo di informazioni che si può cercare e inserire Java, ambiente informazioni:

<PatternLayout header="${java:version} - ${java:os}"> <Pattern>%d %m%n</Pattern></PatternLayout>

potete trovare ulteriori dettagli sul tipo di dati che è possibile inserire attraverso ricerche in log4j2 documentazione.

Configurazione programmatica

Oltre ai file di configurazione, log4j2 può anche essere configurato a livello di programmazione. Ci sono diversi modi per farlo:

  • creare un custom ConfigurationFactory
  • utilizzare il Configuratore di classe
  • modificare la configurazione dopo l’inizializzazione
  • combina le proprietà di file e configurazione programmatica

diamo un’occhiata a come configurare un layout e appender a livello di codice:

Avanti, è possibile definire una data logger tramite il LoggerConfig classe, associare il appender e aggiornare la configurazione:

Quindi, puoi iniziare a utilizzare il logger come al solito:

Logger pLogger = LogManager.getLogger("programmaticLogger");pLogger.info("Programmatic Logger Message");

Questo stile di API fluent può portare a uno sviluppo e un’iterazione più rapidi su configurazioni di registrazione più complesse perché ora stai beneficiando dei vantaggi di lavorare direttamente con il codice Java.

Tuttavia, dato che XML può ancora essere più leggibile e compatto, è spesso possibile sviluppare la configurazione a livello di codice e quindi convertirla in XML quando tutto è fatto.

Livelli log personalizzati

I livelli log incorporati per log4j2 sono:

  • OFF
  • FATAL
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE
  • ALL

Oltre a questi, è anche possibile definire un livello di log personalizzato in base alle proprie esigenze applicative.

Ad esempio, per definire questo nuovo livello di log, è possibile utilizzare il Livello.forName () API-specifica il nome del nuovo livello e un numero intero che rappresenta la posizione del livello nella gerarchia dei livelli di registro:

Level myLevel = Level.forName("NEW_LEVEL", 350);

Per determinare quale valore intero usare, puoi dare un’occhiata ai valori definiti per gli altri livelli di log nella documentazione di log4j2:

Il valore 350 mette il livello tra WARN e INFO, il che significa che i messaggi verranno visualizzati quando il livello è impostato su INFO o superiore.

Per registrare un messaggio a livello personalizzato, è necessario utilizzare il metodo log ():

logger.log(myLevel, "Custom Level Message");

La configurazione XML equivalente potrebbe essere:

<CustomLevels> <CustomLevel name="NEW_XML_LEVEL" intLevel="350" /></CustomLevels>

Quindi può essere utilizzata tramite l’API log standard:

logger.log(Level.getLevel("NEW_XML_LEVEL"),"Custom XML Level Message");

I nuovi livelli personalizzati verranno visualizzati allo stesso modo di quelli standard:

11:28:23.558 NEW_LEVEL - Custom Level Message11:28:23.559 NEW_XML_LEVEL - Custom XML Level Message

Migrando da Log4j 1.x

Se si sta migrando un’applicazione utilizzando il 1.versione x della libreria alla corrente 2.versione x, ci sono un paio di percorsi che puoi seguire:

  • usa il log4j 1.x bridge
  • aggiornare manualmente l’API e la configurazione

Utilizzando il bridge è banale. È sufficiente sostituire la dipendenza log4j con la libreria log4j-1.2-api:

Mentre questo è il metodo più veloce, ha lo svantaggio di essere limitato nel tipo di configurazione che può essere convertito.

Il metodo manuale è, ovviamente, più lavoro, ma alla fine porterà a una soluzione di registrazione più flessibile e potente.

Ecco alcuni dei tipi più comuni di modifiche che dovrai fare:

Conclusione

I file di registro sono fondamentali in qualsiasi ambiente di produzione e la scelta di una buona soluzione di registrazione può essere la differenza tra spendere 5 minuti e trascorrere un’intera giornata per capire un problema in produzione.

Log4j2 è una soluzione di registrazione potente e robusta per le moderne applicazioni Java, con una vasta gamma di opzioni di configurazione.

Consente una facile configurazione delle migliori pratiche di registrazione avanzate come i file di rotolamento, diversi tipi di destinazioni di output di registrazione, supporto per formati di registrazione strutturati come JSON o XML, utilizzando più logger e filtri e livelli di registro personalizzati.

Infine, quando è necessario andare oltre l’analisi manuale dei dati di registro, controlla sicuramente le funzionalità di registrazione incluse in Retrace APM.