2.1 Primo logger - log4j
Come già saprai, la cronologia dei log è iniziata con System.err.println()
l'output di un record sulla console. Viene ancora utilizzato attivamente per il debug, ad esempio Intellij IDEA lo utilizza per visualizzare i messaggi di errore nella console. Ma questa opzione non ha impostazioni, quindi andiamo avanti.
Il primo e più popolare logger si chiamava Log4j
. Era una buona soluzione e altamente personalizzabile. A causa di varie circostanze, questa decisione non è mai entrata nel JDK, il che ha sconvolto notevolmente l'intera comunità.
Questo logger non era solo in grado di registrare, è stato creato da programmatori per programmatori e ha permesso loro di risolvere i problemi che si presentavano costantemente in relazione alla registrazione.
Come già sai, i log vengono scritti alla fine in modo che qualcuno li legga e cerchi di capire cosa è successo durante il funzionamento del programma: cosa e quando è andato storto come previsto.
C'erano log4j
tre cose per questo:
- registrazione del sottopacchetto;
- set di appenders (risultati);
- impostazioni di ricarica a caldo.
In primo luogo, le impostazioni log4j
potrebbero essere scritte in modo tale da abilitare l'accesso in un pacchetto e disabilitarlo in un altro. Ad esempio, era possibile abilitare l'accesso in com.codegym.server
, ma disabilitarlo in com.codegym.server.payment
. Ciò ha permesso di rimuovere rapidamente le informazioni non necessarie dal registro.
In secondo luogo, log4j
consentiva di scrivere i risultati della registrazione in più file di registro contemporaneamente. E l'uscita a ciascuno potrebbe essere configurata individualmente. Ad esempio, in un file era possibile scrivere solo informazioni su errori gravi, in un altro - registri da un modulo specifico e in un terzo - registri per un certo periodo.
Ogni file di registro è stato quindi ottimizzato per un particolare tipo di problema previsto. Ciò semplifica enormemente la vita dei programmatori che non amano guardare manualmente i file di registro di gigabyte.
E infine, in terzo luogo, log4j
ha permesso di modificare le impostazioni del registro direttamente mentre il programma era in esecuzione, senza riavviarlo. Questo è stato molto utile quando era necessario correggere il lavoro dei log per trovare informazioni aggiuntive su un errore specifico.
Importante! Esistono due versioni del registro log4j
: 1.2.xe 2.xx , che sono incompatibili tra loro .
Puoi connettere il logger al progetto usando il codice:
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
</dependencies>
2.2 Primo logger ufficiale - JUL: java.util.logging
Dopo che lo zoo dei logger è apparso nella comunità Java, gli sviluppatori JDK
hanno deciso di creare un logger standard che tutti avrebbero utilizzato. Ecco come è apparso il logger JUL
: pacchetto java.util.logging
.
Tuttavia, durante il suo sviluppo, i creatori del logger non hanno preso come base log4j
, ma una variante del logger di IBM, che ne ha influenzato lo sviluppo. La buona notizia è che il logger JUL
è incluso JDK
, la cattiva notizia è che poche persone lo usano.

Gli sviluppatori non solo JUL
hanno creato "un altro standard universale" , ma hanno anche creato i propri livelli di registrazione per esso, che differivano da quelli accettati dai logger più diffusi in quel momento.
E questo era un grosso problema. Dopotutto, i prodotti vengono Java
spesso raccolti da un gran numero di librerie e ciascuna di queste librerie aveva il proprio logger. Quindi è stato necessario configurare tutti i logger presenti nell'applicazione.
Sebbene il logger stesso sia piuttosto buono. La creazione di un logger è più o meno la stessa. Per fare ciò, è necessario importare:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Il nome della classe viene passato in modo speciale per sapere da dove proviene la registrazione.
Solo con il rilascio gli sviluppatori hanno risolto problemi importanti, dopodiché è JUL
davvero comodo da usare. Prima di allora, era una specie di registratore di second'ordine.
Questo logger supporta anche le espressioni lambda e la valutazione lazy. A partire da Java 8
, puoi passare Supplier<String>
. Questo aiuta a leggere e creare una stringa solo nel momento in cui è veramente necessaria, e non ogni volta, come prima.
I metodi con un argomento Supplier<String> msgSupplier
hanno questo aspetto:
public void info(Supplier msgSupplier) {
log(Level.INFO, msgSupplier);
}
2.3 Primo wrapper del logger - JCL: jakarta commons logging
Per molto tempo non esisteva uno standard unico tra i taglialegna, avrebbe JUL
dovuto diventarlo, ma era peggio log4j
, quindi non è mai apparso un unico standard. Ma è apparso un intero zoo di taglialegna, ognuno dei quali voleva diventare lo stesso.

Tuttavia, ai normali sviluppatori Java non è piaciuto che quasi tutte le librerie abbiano il proprio logger e debbano essere configurate in qualche modo in un modo speciale. Pertanto, la comunità ha deciso di creare un wrapper speciale su altri logger: ecco comeJCL: jakarta commons logging
E ancora, il progetto, nato per essere leader, non lo è diventato. Non puoi creare un vincitore, puoi solo diventare un vincitore. La funzionalità JCL
era molto scarsa e nessuno voleva usarla. Il logger, progettato per sostituire tutti i logger, ha incontrato la stessa sorte in quanto JUL
non è stato utilizzato.
Sebbene sia stato aggiunto a molte librerie rilasciate dalla comunità Apache, lo zoo dei taglialegna è solo cresciuto.
2.4 Primo ultimo logger - Logback
Ma non è tutto. Lo sviluppatore log4j
ha deciso di essere il più intelligente (beh, dopo tutto, la maggior parte delle persone usava il suo logger) e ha deciso di scrivere un nuovo logger migliorato che combinasse i vantaggi log4j
di altri logger.
Il nuovo logger si chiamava Logback
. Era questo logger che doveva diventare il futuro singolo logger che tutti avrebbero usato. Era basato sulla stessa idea di log4j
.
Puoi connettere questo logger al progetto usando il codice:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
Le differenze erano in Logback
:
- prestazione migliorata;
- aggiunto il supporto nativo
slf4j
; - opzione di filtraggio estesa.
Un altro vantaggio di questo logger era che aveva ottime impostazioni predefinite. E dovevi configurare il logger solo se volevi cambiare qualcosa in essi. Inoltre, il file delle impostazioni è stato adattato meglio al software aziendale: tutte le sue configurazioni sono state impostate come xml/
.
Per impostazione predefinita, Logback
non richiede alcuna impostazione e registra tutti i registri dal livello DEBUG
in su. Se hai bisogno di un comportamento diverso, può essere configurato tramite xml
la configurazione:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
<root level="info">
<appender-ref ref="FILE" />
</root>
</configuration>
2.5 Ultimo logger universale - SLF4J: Simple Logging Facade per Java
Quanto tempo ci vorrà per trovare il mezzo aureo...
Nel 2006, uno dei creatori log4j
ha lasciato il progetto e ha deciso di riprovare a creare un logger universale. Ma questa volta non si trattava di un nuovo logger, bensì di un nuovo standard universale (wrapper) che permetteva a diversi logger di interagire insieme.
Questo logger si chiamava slf4j — Simple Logging Facade for Java
, era un wrapper intorno a log4j
, JUL
, common-loggins и logback
. Questo logger ha risolto un vero problema: gestire uno zoo di logger, quindi tutti hanno iniziato immediatamente a usarlo.
Risolviamo eroicamente i problemi che creiamo per noi stessi. Come puoi vedere, il progresso è arrivato al punto che abbiamo creato un involucro sopra l'involucro ...
L'involucro stesso è composto da due parti:
API
, utilizzato nelle applicazioni;- Implementazioni che vengono aggiunte come dipendenze separate per ogni logger.
Puoi connettere il logger al progetto usando il codice:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
Basta collegare l'implementazione corretta e il gioco è fatto: l'intero progetto funzionerà con essa.
2.6 Ottimizzazione in slf4j
Slf4j
supporta tutte le nuove funzionalità come la formattazione delle stringhe per la registrazione . Prima di questo c'era un tale problema. Supponiamo che tu voglia stampare un messaggio nel registro:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
C'è un problema con questo codice. Supponiamo che la tua applicazione funzioni production
e non ne scriva alcuno nel log DEBUG-messages
, tuttavia, il metodo log.debug()
verrà comunque chiamato e, quando verrà chiamato, verranno chiamati anche i seguenti metodi:
user.toString();
request.getRemoteAddr();
La chiamata di questi metodi rallenta l'applicazione. La loro chiamata è necessaria solo durante il debug, ma vengono comunque chiamati.
Dal punto di vista della logica, questo problema doveva essere risolto nella libreria di registrazione stessa. E nella prima versione di log4j è arrivata la soluzione:
if (log.isDebugEnabled()) {
log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Invece di una riga per il registro, ora era necessario scriverne tre. Il che ha drasticamente peggiorato la leggibilità del codice e ridotto la popolarità di log4j
.
Il logger slf4j
è stato in grado di migliorare leggermente la situazione offrendo una registrazione intelligente. Sembrava così:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
dove {}
denotano l'inserimento di argomenti passati nel metodo. Cioè, il primo {}
corrisponde a user, il secondo {}
a request.getRemoteAddr()
.
Questi parametri verranno concatenati in un unico messaggio solo se il livello di registrazione consente la registrazione. Non perfetto, ma migliore di tutte le altre opzioni.
Successivamente, SLF4J
ha iniziato a crescere rapidamente in popolarità, al momento questa è la soluzione migliore.
Pertanto, prenderemo in considerazione la registrazione utilizzando l'esempio di un bundle slf4j-log4j12
.
GO TO FULL VERSION