Da meine aktuellen Java-Projekte immer größer werden, muss ich immer häufiger Debug-Ausgaben in mehrere Punkte meines Codes einfügen.
Um diese Funktion abhängig vom Öffnen oder Schließen der Testsitzungen entsprechend zu aktivieren oder zu deaktivieren, setze ich in der Regel private static final boolean DEBUG = false
zu Beginn der von meinen Tests überprüften Klassen ein und verwende es trivial wie folgt:
public MyClass {
private static final boolean DEBUG = false;
... some code ...
public void myMethod(String s) {
if (DEBUG) {
System.out.println(s);
}
}
}
und dergleichen.
Aber das freut mich nicht, denn natürlich funktioniert es, aber es könnte zu viele Klassen geben, in denen DEBUG auf true gesetzt werden kann, wenn Sie nicht nur ein paar von ihnen anstarren.
Umgekehrt würde ich (wie - ich denke - viele andere) nicht gerne die gesamte Anwendung in den Debug-Modus versetzen, da die Menge des ausgegebenen Texts überwältigend sein könnte.
Gibt es also eine richtige Methode, um mit einer solchen Situation architektonisch umzugehen, oder die richtige Methode, um das DEBUG-Klassenmitglied zu verwenden?
Antworten:
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
undlogback-core
):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:
Tatsächlich ist es jedoch noch üblicher, den Logger mit dem folgenden Formular zu deklarieren:
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:
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:
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 dieheavyComputation()
Methode dennoch ausgeführt worden .Aufbau
Die Konfiguration hängt stark von Ihrem Protokollierungsframework ab, bietet jedoch meist die gleichen Techniken:
Sie bieten auch meist die gleichen Funktionen:
Im Folgenden finden Sie ein allgemeines Beispiel für eine deklarative Konfiguration mithilfe einer
logback.xml
Datei.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.
quelle
static
, da dies wenig Speicherplatz spart, aber in bestimmten Fällen Probleme verursacht: slf4j.org/faq.html#declared_staticVerwenden Sie ein Protokollierungsframework
Meistens gibt es eine statische Fabrikmethode
Dann können Sie Ihren Protokollierungscode mit verschiedenen Ebenen ausgeben:
Dann gibt es eine einzelne Datei, in der Sie definieren können, welche Nachrichten für jede Klasse in die Protokollausgabe geschrieben werden sollen (Datei oder stderr).
quelle
Genau dafür sind Logging-Frameworks wie log4j oder das neuere slf4j gedacht. Mit ihnen können Sie die Protokollierung sehr detailliert steuern und sogar konfigurieren, während die Anwendung ausgeführt wird.
quelle
Ein Protokollierungsframework ist definitiv der richtige Weg. Sie müssen jedoch auch eine gute Testsuite haben. Durch eine gute Testabdeckung kann häufig die Notwendigkeit einer Debug-Ausgabe insgesamt beseitigt werden.
quelle