Si desidera esaminare un framework di registrazione e forse un framework di facciata di registrazione.
Esistono più framework di registrazione là fuori, spesso con funzionalità sovrapposte, tanto che nel tempo molti si sono evoluti per fare affidamento su un'API comune o sono stati utilizzati attraverso un framework di facciate per astrarre il loro uso e consentire loro di essere scambiati sul posto se necessario.
Frameworks
Alcuni frame di registrazione
Alcune facciate di registrazione
uso
Esempio di base
La maggior parte di questi framework ti consentirebbe di scrivere qualcosa del modulo (qui usando slf4j-api
e logback-core
):
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
Si noti l'uso di una classe corrente per creare un logger dedicato, che consentirebbe a SLF4J / LogBack di formattare l'output e indicare da dove proviene il messaggio di registrazione.
Come notato nel manuale SLF4J , un tipico modello di utilizzo in una classe è di solito:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
In realtà, è ancora più comune dichiarare il logger con il modulo:
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
Ciò consente al logger di essere utilizzato anche all'interno di metodi statici ed è condiviso tra tutte le istanze della classe. È molto probabile che questa sia la tua forma preferita. Tuttavia, come osservato da Brendan Long nei commenti, si desidera essere sicuri di comprendere le implicazioni e decidere di conseguenza (questo vale per tutti i framework di registrazione che seguono questi idiomi).
Esistono altri modi per creare un'istanza dei logger, ad esempio utilizzando un parametro stringa per creare un logger denominato:
Logger logger = LoggerFactory.getLogger("MyModuleName");
Livelli di debug
I livelli di debug variano da una struttura all'altra, ma quelli comuni sono (in ordine di criticità, da benigni a quelli di merda di pipistrello e da probabilmente molto comuni a speriamo molto rari):
TRACE
Informazioni molto dettagliate Dovrebbe essere scritto solo nei registri. Utilizzato solo per tenere traccia del flusso del programma ai punti di controllo.
DEBUG
Informazioni dettagliate. Dovrebbe essere scritto solo nei registri.
INFO
Notevoli eventi di runtime. Dovrebbe essere immediatamente visibile su una console, quindi usa con parsimonia.
WARNING
Stranezze di runtime ed errori recuperabili.
ERROR
Altri errori di runtime o condizioni impreviste.
FATAL
Gravi errori che causano la risoluzione anticipata.
Blocchi e protezioni
Ora, supponiamo che tu abbia una sezione di codice in cui stai per scrivere una serie di istruzioni di debug. Ciò potrebbe influire rapidamente sulle prestazioni, sia a causa dell'impatto della registrazione stessa sia della generazione di qualsiasi parametro che si potrebbe passare al metodo di registrazione.
Per evitare questo tipo di problema, spesso vuoi scrivere qualcosa del modulo:
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
Se non avessi usato questa protezione prima del blocco delle istruzioni di debug, anche se i messaggi potrebbero non essere emessi (se, ad esempio, il tuo logger è attualmente configurato per stampare solo cose al di sopra del INFO
livello), il heavyComputation()
metodo sarebbe comunque stato eseguito .
Configurazione
La configurazione dipende abbastanza dal tuo framework di registrazione, ma offrono principalmente le stesse tecniche per questo:
- configurazione programmatica (in fase di runtime, tramite un'API - consente modifiche di runtime ),
- configurazione dichiarativa statica (all'avvio, di solito tramite un file XML o proprietà - probabilmente sarà quello che ti serve all'inizio ).
Offrono anche per lo più le stesse funzionalità:
- configurazione del formato del messaggio di output (timestamp, marker, ecc ...),
- configurazione dei livelli di uscita,
- configurazione di filtri a grana fine (ad esempio per includere / escludere pacchetti o classi),
- configurazione di appendici per determinare dove accedere (alla console, al file, a un servizio Web ...) e possibilmente cosa fare con i registri più vecchi (ad esempio, con i file con rotazione automatica).
Ecco un esempio comune di una configurazione dichiarativa, usando un logback.xml
file.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Come accennato, questo dipende dal tuo framework e potrebbero esserci altre alternative (ad esempio, LogBack consente anche di utilizzare uno script Groovy). Il formato di configurazione XML può anche variare da un'implementazione all'altra.
Per ulteriori esempi di configurazione, fare riferimento (tra gli altri) a:
Un po 'di divertimento storico
Si prega di notare che Log4J sta vedendo un importante aggiornamento per il momento, la transizione dalla versione 1.x alla 2.x . Potresti dare un'occhiata a entrambi per divertimento o confusione più storici, e se scegli Log4J probabilmente preferisci andare con la versione 2.x.
Vale la pena notare, come Mike Partridge ha menzionato nei commenti, che LogBack è stato creato da un ex membro del team Log4J. Che è stato creato per affrontare le carenze del framework di registrazione Java. E che l'imminente versione principale di Log4J 2.x si sta integrando ora con alcune funzionalità tratte da LogBack.
Raccomandazione
In conclusione, rimanete disaccoppiati il più possibile, giocatene con alcuni e vedete cosa funziona meglio per voi. Alla fine è solo un framework di registrazione . Tranne se hai una ragione molto specifica, a parte la facilità d'uso e le preferenze personali, ognuna di queste cose farebbe piuttosto bene, quindi non ha senso essere sospesi. La maggior parte di essi può anche essere estesa alle tue esigenze.
Tuttavia, se dovessi scegliere una combinazione oggi, sceglierei LogBack + SLF4J. Ma se mi avessi chiesto qualche anno dopo, avrei raccomandato Log4J con Apache Commons Logging, quindi tieni d'occhio le tue dipendenze ed evolvi con esse.