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 log4jtre cose per questo:

  • registrazione del sottopacchetto;
  • set di appenders (risultati);
  • impostazioni di ricarica a caldo.

In primo luogo, le impostazioni log4jpotrebbero 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, log4jconsentiva 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, log4jha 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 JDKhanno 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.

LUG

Gli sviluppatori non solo JULhanno 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 Javaspesso 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é è JULdavvero 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> msgSupplierhanno 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 JULdovuto 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.

JCL

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à JCLera molto scarsa e nessuno voleva usarla. Il logger, progettato per sostituire tutti i logger, ha incontrato la stessa sorte in quanto JULnon è 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 log4jha 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 log4jdi 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, Logbacknon richiede alcuna impostazione e registra tutti i registri dal livello DEBUGin su. Se hai bisogno di un comportamento diverso, può essere configurato tramite xmlla 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 log4jha 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 and 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

Slf4jsupporta 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 productione 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, SLF4Jha 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.