Sie möchten sich ein Protokollierungsframework und möglicherweise ein Protokollierungsframework für Fassaden ansehen.
Es gibt mehrere Protokollierungsframeworks, die häufig überlappende Funktionalitäten aufweisen, sodass sich im Laufe der Zeit viele davon auf eine gemeinsame API stützen oder über ein Fassadenframework verwendet werden, um ihre Verwendung zu abstrahieren und zu ermöglichen, dass sie an Ort und Stelle ausgetauscht werden wenn benötigt.
Frameworks
Einige Protokollierungsframeworks
Einige Logging-Fassaden
Verwendung
Grundlegendes Beispiel
Mit den meisten dieser Frameworks können Sie etwas aus dem Formular schreiben (hier mit slf4j-api
und 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");
}
}
Beachten Sie die Verwendung der aktuellen Klasse, um einen dedizierten Protokollierer zu erstellen, mit dem SLF4J / LogBack die Ausgabe formatieren und angeben kann, woher die Protokollierungsnachricht stammt.
Wie im SLF4J-Handbuch erwähnt , ist ein typisches Verwendungsmuster in einer Klasse normalerweise:
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!");
}
}
}
Tatsächlich ist es jedoch noch üblicher, den Logger mit dem folgenden Formular zu deklarieren:
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
Auf diese Weise kann der Logger auch in statischen Methoden verwendet werden und wird von allen Instanzen der Klasse gemeinsam genutzt. Dies ist höchstwahrscheinlich Ihre bevorzugte Form. Wie Brendan Long in seinen Kommentaren feststellte, sollten Sie die Auswirkungen verstehen und entsprechend entscheiden (dies gilt für alle Protokollierungsframeworks, die diesen Redewendungen folgen).
Es gibt andere Möglichkeiten, Logger zu instanziieren, indem Sie beispielsweise einen String-Parameter verwenden, um einen benannten Logger zu erstellen:
Logger logger = LoggerFactory.getLogger("MyModuleName");
Debug-Ebenen
Die Debug-Level variieren von einem Framework zum anderen, aber die häufigsten sind (in der Reihenfolge der Kritikalität, von harmlos bis schlecht und von wahrscheinlich sehr häufig bis hoffentlich sehr selten):
TRACE
Sehr detaillierte Informationen. Sollte nur in Protokolle geschrieben werden. Wird nur verwendet, um den Programmfluss an Kontrollpunkten zu verfolgen.
DEBUG
Genaue Information. Sollte nur in Protokolle geschrieben werden.
INFO
Bemerkenswerte Laufzeitereignisse. Sollte auf einer Konsole sofort sichtbar sein, so sparsam verwenden.
WARNING
Laufzeitunregelmäßigkeiten und behebbare Fehler.
ERROR
Andere Laufzeitfehler oder unerwartete Bedingungen.
FATAL
Schwerwiegende Fehler, die zu einer vorzeitigen Beendigung führen.
Blöcke und Wachen
Angenommen, Sie haben einen Codeabschnitt, in dem Sie eine Reihe von Debug-Anweisungen schreiben werden. Dies kann sich schnell auf Ihre Leistung auswirken, sowohl aufgrund der Auswirkungen der Protokollierung selbst als auch aufgrund der Generierung von Parametern, die Sie möglicherweise an die Protokollierungsmethode übergeben.
Um solche Probleme zu vermeiden, möchten Sie häufig etwas in der Form schreiben:
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
Wenn Sie diesen Schutz vor Ihrem Block von Debug-Anweisungen nicht verwendet hätten, obwohl die Meldungen möglicherweise nicht ausgegeben werden (wenn Ihr Logger beispielsweise derzeit so konfiguriert ist, dass nur Dinge über dem INFO
Level gedruckt werden), wäre die heavyComputation()
Methode dennoch ausgeführt worden .
Aufbau
Die Konfiguration hängt stark von Ihrem Protokollierungsframework ab, bietet jedoch meist die gleichen Techniken:
- programmatische Konfiguration (zur Laufzeit über eine API - ermöglicht Laufzeitänderungen ),
- statische deklarative Konfiguration (zum Start in der Regel über eine XML- oder Eigenschaftendatei - wahrscheinlich das, was Sie zuerst benötigen ).
Sie bieten auch meist die gleichen Funktionen:
- Konfiguration des Formats der Ausgangsnachricht (Zeitstempel, Markierungen usw.),
- Konfiguration der Ausgangspegel,
- Konfiguration von feinkörnigen Filtern (zum Beispiel um Pakete oder Klassen einzuschließen / auszuschließen),
- Konfiguration von Appendern, um zu bestimmen, wo protokolliert werden soll (zur Konsole, zur Datei, zu einem Web-Service ...) und möglicherweise was mit älteren Protokollen zu tun ist (zum Beispiel mit automatisch rollenden Dateien).
Im Folgenden finden Sie ein allgemeines Beispiel für eine deklarative Konfiguration mithilfe einer logback.xml
Datei.
<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>
Wie bereits erwähnt, hängt dies von Ihrem Framework ab, und es gibt möglicherweise andere Alternativen (LogBack ermöglicht beispielsweise auch die Verwendung eines Groovy-Skripts). Das XML-Konfigurationsformat kann auch von Implementierung zu Implementierung variieren.
Weitere Konfigurationsbeispiele finden Sie unter anderem unter:
Ein bisschen historischer Spaß
Bitte beachten Sie, dass Log4J im Moment ein großes Update sieht, das von Version 1.x auf 2.x übergeht . Vielleicht möchten Sie sich beide ansehen, um mehr historischen Spaß zu haben oder Verwirrung zu stiften , und wenn Sie sich für Log4J entscheiden, bevorzugen Sie wahrscheinlich die 2.x-Version.
Es ist erwähnenswert, wie Mike Partridge in Kommentaren erwähnte, dass LogBack von einem ehemaligen Log4J-Teammitglied erstellt wurde. Welches erstellt wurde, um Mängel des Java Logging-Frameworks zu beheben. Und dass die kommende Hauptversion von Log4J 2.x selbst jetzt einige Funktionen von LogBack integriert.
Empfehlung
Unterm Strich bleiben Sie so weit wie möglich entkoppelt, spielen Sie mit ein paar herum und sehen Sie, was für Sie am besten funktioniert. Am Ende ist es nur ein Protokollierungsframework . Außer wenn Sie einen bestimmten Grund haben, abgesehen von der Benutzerfreundlichkeit und den persönlichen Vorlieben, ist einer dieser Gründe eher in Ordnung, sodass es keinen Sinn macht, darüber zu hängen. Die meisten von ihnen können auch auf Ihre Bedürfnisse erweitert werden.
Wenn ich heute noch eine Kombination auswählen müsste, würde ich mich für LogBack + SLF4J entscheiden. Aber wenn Sie mich ein paar Jahre später gefragt hätten, ob ich Log4J mit Apache Commons Logging empfehlen würde, behalten Sie Ihre Abhängigkeiten im Auge und entwickeln Sie sich mit ihnen weiter.