Hinweise zur Verwendung der Logging API im JDK 1.4

Werbung
18. Oktober 2005
Hinweise zur Verwendung der
Logging API im JDK 1.4
18. Oktober 2005
[email protected]
[email protected]
Inhalt
1 Logging........................................................................................................................................ 2
1.1 Übersicht.............................................................................................................................. 2
1.1.1 Logger...........................................................................................................................3
1.1.2 Handler......................................................................................................................... 3
1.1.3 Logging Properties-File................................................................................................ 4
1.2 Logging Levels.....................................................................................................................4
1.2.1 SEVERE....................................................................................................................... 5
1.2.2 WARNING...................................................................................................................5
1.2.3 INFO.............................................................................................................................6
1.2.4 CONFIG....................................................................................................................... 6
1.2.5 FINE............................................................................................................................. 6
1.2.6 FINER...........................................................................................................................6
1.2.7 FINEST.........................................................................................................................6
1.3 Beispiele............................................................................................................................... 7
1.4 Programmierrichtlinien........................................................................................................ 9
1.4.1 Initialisierung................................................................................................................9
1.4.2 Logging Meldungen......................................................................................................9
1.4.3 Debugging.................................................................................................................... 9
1.4.4 root-Handler und root-Logger.................................................................................... 10
1.5 Kurzanleitung..................................................................................................................... 11
1.5.1 Konfigurationsfile.......................................................................................................11
1.5.2 Start der Anwendung.................................................................................................. 11
1.5.3 Meldungen..................................................................................................................11
1/11
18. Oktober 2005
1 Logging
Die Logging API wurde von Sun in der Java Version 1.4 in das JDK integriert. Vor JDK1.4 wurden
Logging APIs in verschieden Open-Source Projekten entwickelt, diese APIs werden teilweise noch
weiter verwendet (Jakarta Commons-Logging, Log4j). Im Folgenden wird die Logging API in
JDK1.4 kurz dokumentiert und Überlegungen und Implementierungsvorschläge für die Verwendung
zusammengefasst.
Einen vollständigen Überblick findet man bei [http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/]
1.1 Übersicht
Die zentrale Komponente der Logging API ist die Klasse java.util.logging.LogManager.
Der LogManager hat die Aufgabe verschiedene Logger-Objekte in einem hierachischem Namensraum zu organisieren, sowie zugehörige Logging-Handler zu verwalten. Der LogManager ist auch
für das Einlesen des Logging Konfigurationsfiles beim Start einer Anwendung zuständig.
Das folgende Schaubild zeigt stark vereinfacht den Ablauf bei der Verwendung der Logging API:
LoggingManager
Anwendung
Logging Meldung
Logger
log(level,msg)
LogRecord
Handler
Ausgabe
Die Anwendung verwendet einen Logger um ein Ereignis an die Logging API zu melden, der
Logger leitet diese Meldung in Form eines LogRecord an einen Handler weiter, der diese als
Meldung ausgibt.
Alle Handler sind Unterklassen der abstrakten Klasse java.util.logging.Handler. Häufig
verwendete Handler sind ConsoleHandler, der die Meldungen auf die Konsole ausgibt und
FileHandler, der die Meldungen in eine Datei schreibt. Wird kein Handler explizit definiert, so
installiert der LogManager einen ConsoleHandler als Default.
Um einen Logger in einer Anwendung zu verwenden muss dieser zunächst mit der static
Methode Logger.getLogger(“<name>“) erzeugt werden. Meldungen können dann mit der
Methode log(...) an diesen übergeben werden.
Bei der Übergabe einer Meldung durch die Anwendung an den Logger wird explizit oder implizit ein
Logging-Level für diese Meldung vorgegeben. Dieser Logging-Level gibt die Priorität der Meldung
an. Logger und Handler können so konfiguriert werden, dass lediglich Meldungen ab einer
bestimmten Priorität weitergeleitet werden. Hierfür wird die Methode setLevel() im Handler bzw.
im Logger Objekt verwendet.
Die Initialisierung des LogManager und damit die Konfiguration der verwendeten Logger und
Handler kann beim Start einer Java Anwendung über ein properties-File vorgenommen werden.
Dabei wird über den Parameter -Djava.util.logging.config.file=<filename> das zu
verwendende Properties File angegeben.
Für eine einfache Anwendung ist es hinreichend lediglich mit Logger Objekten zu arbeiten. Normalerweise werden die Handler lediglich in einem Konfigurationsfile definiert und nicht von der Anwendung selbst initialisiert. In einer aufwändigeren Konfiguration können sie verwendet werden um z.B.
Log Records in einem Ringpuffer zu speichern und lediglich bei Bedarf auszugeben. Auch der
LogManager selbst wird von einer einfachen Anwendung in der Regeln nicht direkt verwendet. Er
kann bei Bedarf jedoch benutzt werden, um z.B. ein geändertes Konfigurationsfile in einer
laufenden Anwendung neu zu laden.
In den folgenden Abschnitten wird genauer auf die Konfiguration der einzelnen Komponenten der
Logging API für eine “einfache“ Anwendung eingegangen.
2/11
18. Oktober 2005
1.1.1 Logger
Alle Logger Objekte werden in einem Namensraum hierachisch verwaltet. Bei der Initialisierung
eines Loggers mit der Methode Logger.getLogger(“<name>“) wird der Name des Loggers
angegeben. Normalerweise werden Logger nach dem Package- oder Klassennamen benannt in
dem sie verwendet werden. Ein besonderer Logger ist der root-Logger, der den Namen ““ (leerer
String) hat. Außer dem root-Logger besitzt jeder Logger eine Referenz auf den im Namensraum
übergeordneten Logger, dieser Logger wird auch als parent-Logger bezeichnet.
Ein Handler kann mit der Methode addHandler() bei einem Logger angemeldet werden. Alle
Logging Meldungen werden sowohl an die im Logger registrierten Handler als auch an seinen
parent-Logger weitergeleitet. Aus diesem Grund genügt das Registrieren eines einzigen Handlers
beim root-Logger, um die Meldungen aller in einer Anwendung verwendeten Logger entgegenzunehmen.
Jeder Logger besitzt einen Level, der den minimalen Level der Meldungen darstellt, die von ihm
angenommen werden. Wenn die Meldung z.B. über die Methode log(Level, String) von der
Anwendung übermittelt wird nimmt der Logger diese Meldung an, wenn der als Parameter übergebene Logging-Level der Meldung größer ist als der vorgegebene minimale Logging-Level. Die
Meldung wird dann an alle angehängten Handler und an den parent-Logger weitergegeben. Der
parent-Logger führt die Überprüfung des Logging-Level nicht mehr durch da die Meldung bereits
von einem anderen Logger angenommen wurde. Daraus folgt, dass eine Meldung, die durch einen
Logger angenommen wurde, alle parent-Logger dieses Loggers erreicht, und damit auch den
Handler des root-Loggers und zwar unabhängig vom Logging-Level der parent-Logger.
Der Logging-Level eines Loggers kann entweder über die Methode setLevel() in einer Anwendung direkt konfiguriert werden, oder wird in einem properties-File definiert. Wird vom Anwender
kein Level vorgegeben, so wird der Level des parent-Logger verwendet.
1.1.2 Handler
Logging Handler haben die Aufgabe die Logging Meldungen von den Loggern entgegenzunehmen
und auszugeben oder ggf. zwischenzuspeichern. Der Logging-Level kann über die Methode
setLevel() konfiguriert werden und definiert welche Meldungen bearbeitet werden. Die folgende
Auflistung beschreibt einen Teil der im JDK implementierten Handler:
•
ConsoleHandler
Dieser Handler schreibt die Meldungen nach System.err, als default-Level wird INFO
verwendet.
•
FileHandler
Dieser Handler schreibt die Meldungen in eine Datei oder in eine Menge von rotierenden
Logfiles welche im Konstruktor angegeben werden können, als default-Level wird ALL
verwendet.
•
MemoryHandler
Bei diesem Handler werden die Meldungen in einem Ringpuffer gespeichert und können bei
Bedarf an einen zweiten Handler weitergegeben werden.
Für einen Handler können Formatter-Objekte gesetzt werden, die definieren in welchen Format die
Meldungen ausgegeben werden. Im JDK sind die beiden folgenden Formatter implementiert:
•
SimpleFormatter
Konvertiert eine Logging Meldung in einen einfachen String, der aus ein oder zwei Zeilen
besteht. Dieser Formatter wird als Default verwendet.
•
XMLFormatter
Konvertiert eine Logging Meldung in eine XML Struktur.
3/11
18. Oktober 2005
1.1.3 Logging Properties-File
Beim Start einer Java Anwendung kann mit dem Kommandozeilenparameter “-Djava.util.
logging.config.file=<filename>“ ein Properties-File angegeben werden, n dem für den
LogManager die Konfiguration der Logger und Handler festgelegt werden kann. Wird kein solcher
Kommandozeilenparameter angegeben so liest der LogManager die Konfiguration aus einer Datei
an der Stelle lib/logging.properties im Verzeichnis der verwendeten JRE.
Die Properties-Files können unter anderem die folgenden Angaben enthalten:
•
Property “handlers“
definiert eine durch Whitespace oder Komma getrennte Liste von Klassennamen, die dem rootLogger als Handler zugewiesen werden.
•
Propety “<logger>.handlers“
definiert eine durch Whitespace oder Komma getrennte Liste, die dem Logger mit dem Namen
“<logger>“ als Handler zugewiesen werden.
•
Property “.level“
definiert einen Logging Level für den root-Logger.
•
Property “<logger>.level“
definiert einen Logging-Level für einen Logger mit dem Namen „<logger>“.
Das oben genannte Properties-File innerhalb der JRE enthält u.a. die folgenden Parameter:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = INFO
.level = INFO
Dadurch wird eine ConsoleHandler für den root-Logger installiert, sowie der Level INFO als
Default-Level für alle in einer Anwendung verwendeten Logger initialisiert. Diese Einstellungen
können sowohl in der Anwendung durch explizite Methodenaufrufe als auch durch die Verwendung
eines eigenen Properties-File verändert werden.
Um z.B. einen ConsoleHandler für den root-Logger zu installieren, der alle Logging Meldung
ausgibt, müssen die folgenden Parameter im properties-File gesetzt werden:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
Um beispielsweise die Logger in einem Package net.mypackage so zu konfigurieren, dass sie
alle Meldungen an den Handler weitergeben, muss der folgenden Parameter im properties-File
gesetzt werden:
net.mypackage.level = ALL
An Stelle des Namens eines Packages kann auch eine einzelne Klasse angegeben werden. Dies
ist jedoch nur sinnvoll, wenn für die Logger in der Klasse auch der Name der Klasse verwendet
wurde.
Für den root-Logger setzt man den Level zur Ausgabe aller Meldungen mit dem Parameter
.level = ALL
1.2 Logging Levels
Für die Logger entscheidet der eingestellte Logging Level über die Annahme einer Meldung wenn
diese z.B. über die log(Level, String) Methode durch die Anwendung übergeben wird.
Wurde eine Meldung jedoch einmal von einem Logger angenommen, so wird diese an den parentLogger weitergegeben und von diesem unabhängig vom Logging-Level angenommen.
Für die Handler entscheidet der Logging-Level über die Ausgabe einer Meldung z.B. auf die
Konsole oder in eine Datei.
4/11
18. Oktober 2005
Zusammengefasst bedeutet dies: Entscheidend, ob eine Meldung angenommen wird, ist der Level
des Loggers, entscheidend, ob eine Meldung ausgegeben wird, ist der Level des Handlers.
Die Logging Levels des JDK 1.4 sind in der Reihenfolge ihrer Priorität:
•
SEVERE (höchste Priorität)
•
WARNING
•
INFO (default Level für Logger und Handler)
•
CONFIG
•
FINE
•
FINER
•
FINEST (niedrigste Priorität)
Darüber hinaus gibt es noch die Level OFF und ALL, diese können verwendet werden, um in den
Loggern oder Handlern sämtliche Logging Meldungen ein- oder auszuschalten. Die Logging Level
werden als public static Felder des Objekts java.util.logging.Level implementiert. Es
ist möglich java.util.logging.Level zu erweitern und eigene Logging Level zu implementieren.
In der default-Konfiguration ,d.h. wenn die verwendeten Logger oder Handler nicht durch das
Setzen der Logging Levels in der Anwendung konfiguriert werden, werden alle Meldungen mit der
Priorität INFO oder höher ausgegeben.
Die folgenden Abschnitte schlagen Richtlinien zur Verwendung der einzelnen Level vor.
1.2.1 SEVERE
Dieser Level sollte verwendet werden wenn aufgrund von auftretenden Fehlern eine Anwendungnicht länger ausgeführt werden kann, d.h. wenn ein weiteres Ausführen der Anwendung zu inkonsistenten Daten oder zum unmittelbaren Absturz der Anwendung führen würde.
Dieser Level sollte auch verwendet werden, wenn Ereignisse im Programm auf einen Fehler in der
Implementierung der Anwendung hindeuten (Programmierfehler), die Anwendung jedoch mit sinnvollen Werten weiterrechnen kann.
Beispiele:
•
Ein Operative konnte sich nach mehreren Versuchen nicht beim Dispatcher anmelden, der
Operative bricht mit mit einer SEVERE Message ab.
•
Bei der Überprüfung mit instanceof hat ein Objekt nicht die notwendige Klasse.
•
Der Kontrollfluss in einem switch-Block landet in einem „unmöglichen“ case/default-Zweig.
•
Fehler in Architeuthis
1.2.2 WARNING
Dieser Level sollte verwendet werden wenn Fehler in einer Anwendung auftreten, die Anwendung
jedoch selbständig versucht den Fehler zu beheben, oder die Anwendung zunächst weiterarbeiten
kann, der Fehler also keine unmittelbaren Auswirkungen hat.
Beispiele:
•
Temporäre Fehler z.B. durch Netzwerkprobleme.
•
Der Verbindungsaufbau zu einem Operative ist fehlgeschlagen, es wird jedoch weiter versucht
die Verbindung herzustellen.
•
Fehler in den durch den Anwender programmierten Teilproblemen, RemoteStores etc. (Fehler
im Benutzercode)
5/11
18. Oktober 2005
1.2.3 INFO
Sonstige Meldungen, die für den Anwender von Interesse sein könnten. Da Meldungen mit diesem
Level in der default-Konfiguration ausgegeben werden sollten lediglich selten auftretende wichtige
Ereignisse in einer Anwendung dokumentiert werden, die für den Anwender von Interesse sind.
•
Angeforderte Dateien im Classfileserver
•
Start/Ende der Berechnung
1.2.4 CONFIG
Dieser Level sollte verwendet werden, um den “normalen“ Kontrollfluss in einer Anwendung zu
dokumentieren.
Beispiel:
•
Verbindungsaufbau oder Verbindungsabbau zu einem Operative
•
Meldungen wenn default-Werte für optionale Parameter beim Programmstart verwendet werden.
•
Kommandozeilenargumente nach dem Parsen im Operative
•
Anmeldung des Operative
1.2.5 FINE
Dieser Level sollte verwendet werden, um ein oberflächliches Debugging einer Anwendung zu
erlauben. Dabei werden vor allen Konfigurationsparameter einer Anwendung ausgegeben. Damit
können häufiger auftretende Ereignisse im normalen Kontrollfluss einer Anwendung dokumentiert
werden
Beispiele:
•
Ausgabe der Filenamen von Ein- und Ausgabedateien, Port- und IP-Nummern im laufenden
Betrieb.
•
Ein neues Problem wird zum Dispatcher übermittelt und berechnet.
•
Aufrufe der wichtigen Methoden registerRemoteStore() und fetchPartialProblem().
•
Zurückliefern eine Lösung im Operative
1.2.6 FINER
Dieser Level sollte verwendet werden um einzelne Methodenaufrufe zu dokumentieren. Dabei
können zusätzlich auch die Parameter der Methodenaufrufe ausgegeben werden. Dieser Level
wird von den Methoden entering(), exiting() und throwing() eines Logging Objekts
verwendet. Diese Methoden definieren also implizit einen Logging Level und können verwendet
werden, um bequem die entsprechenden Ereignisse in einer Anwendung an einen Logger zu
melden. Beim Aufruf müssen als Parameter mindestens der Name der Methode sowie der Name
der Klasse übergeben werden:
entering(String sourceClass, String sourceMethod);
Beispiele:
•
sämtliche “interessantern“ Methodenein- oder -austritte.
1.2.7 FINEST
Dieser Level sollte verwendet werden, um gegebenenfalls den Kontrollfluss innerhalb einer
Methode zu dokumentieren.
Beispiele:
6/11
18. Oktober 2005
•
Ausgabe von Schleifendurchläufen
•
“interessante“ Ereignisse innerhalb einer Methode
1.3 Beispiele
In diesem Abschnitt soll anhand einiger Beispiele die Funktionsweise der Logging API veranschaulicht werden. Es soll insbesondere die Verarbeitung der Logging Meldungen innerhalb der hierachischen Struktur der Logger verdeutlicht werden. Zunächst wird der Aufbau einer solchen
Struktur aus Loggern und Handler sowohl mit Hilfe der Parameter eines Properties-Files als auch
mit Hilfe von Java-Methoden beschrieben. Die folgende Abbildung verdeutlicht die verwendete
Struktur, die Pfeile veranschaulichen den “Weg“ zweier Logging-Meldungen, die im Folgenden
besprochen werden.
default root-Logger (““)
default Logger (“A“)
default handler1
"hello A.B.A!" "hello A.B.C!"
default Logger (“A.A“)
default Logger (“A.B“)
default handler2
"hello A.B.A!“ "hello A.B.C!"
default Logger (“A.B.B“)
default Logger (“A.B.C“)
default Logger (“A.B.A“)
log(Level.INFO, "hello A.B.A!");
log(Level.INFO, "hello A.B.C!");
Symbole:
Logging-Level
level
object
Objekt
(Logger/Handler)
default handler3
"hello A.B.C!"
Logging-Meldungen:
weiter geleitet/
angenommen
nicht angenommen
Das folgende Codefragment erzeugt diese Struktur:
Logger logger = Logger.getLogger("");
Logger logger_A = Logger.getLogger("A");
Logger logger_A_A = Logger.getLogger("A.A");
Logger logger_A_B = Logger.getLogger("A.B");
Logger logger_A_B_A = Logger.getLogger("A.B.A");
Logger logger_A_B_B = Logger.getLogger("A.B.B");
Logger logger_A_B_C = Logger.getLogger("A.B.C");
Handler handler1 = new ConsoleHandler();
logger_A.addHandler(handler1);
Handler handler2 = new ConsoleHandler();
logger_A_B.addHandler(handler2);
Handler handler3 = new ConsoleHandler();
logger_A_B_C.addHandler(handler3);
alternativ kann diese Struktur auch mit einem properties-File mit dem folgenden Inhalt erzeugt
werden:
A.handlers = java.util.logging.ConsoleHandler
7/11
18. Oktober 2005
A.B.handlers = java.util.logging.ConsoleHandler
A.B.C.handlers = java.util.logging.ConsoleHandler
Durch dieses properties-File werden lediglich die verwendeten Handler den entsprechenden
Loggern zugeordnet. Die gewünschte hierachische Struktur wird automatisch durch die Namen der
verwendeten Logger erzeugt sobald diese in der Anwendung initialisiert werden. Die Initialisierung
erfolgt in der Anwendung durch die statische Methode Logger.getLogger(“...“).
•
Mit dem folgenden Befehl wird durch jeden der 3 verwendeten Handler die Meldung “hello
A.B.C!“ ausgegeben:
logger_A_B_C.log(Level.INFO, "hello A.B.C!");
•
Der folgende Befehl gibt lediglich über handler1 und handler2 die Meldung “hello A.B.A!“ aus:
logger_A_B_A.log(Level.INFO, “hello A.B.A!“);
Nun werden zusätzlich die Logging-Level der einzelnen Handler und Logger gesetzt, so dass die
folgende Struktur entsteht:
default root-Logger (““)
default Logger (“A“)
default handler1
"hello A.B.C!"
default Logger (“A.A“)
WARN. Logger (“A.B“)
default handler2
"hello A.B.C!"
Level vom parent
default Logger (“A.B.B“)
default Logger (“A.B.A“)
log(Level.INFO, "hello A.B.A!");
INFO
Logger (“A.B.C“)
WARN. handler3
log(Level.INFO, "hello A.B.C!");
Logging-Meldungen:
weiter geleitet/
object
level
Logging-Level
angenommen
nicht angenommen
Logging-Level wird vom vom parent-Logger übernommen
Symbole:
Objekt
(Logger/Handler)
Das Setzen der Level erfolgt mit den folgenden zusätzlichen Methodenaufrufen:
logger_A_B_C.setLevel(Level.INFO);
logger_A_B.setLevel(Level.WARNING);
handler3.setLevel(Level.WARNING);
•
Der folgende Befehl gibt keine Meldung aus:
logger_A_B_A.log(Level.INFO, "hello A.B.A!");
Für logger_A_B_A wurde kein Logging-Level explizit gesetzt, der Logger übernimmt also
den Logging-Level WARNING seines parent-Loggers wie in Abschnitt 1.1.1 beschrieben. Die
Meldung mit dem Level INFO wird also nicht angenommen.
•
Der folgende Befehlt gibt über die handler1 und handler2 die Meldung “hello A.B.C“ aus:
logger_A_B_C.log(Level.INFO, "hello A.B.C!");
Der Logger logger_A_B_C wird auf den level INFO gesetzt, die Meldung mit dem Level
INFO wird also angenommen und an den registrierten Handler sowie den parent-Logger
8/11
18. Oktober 2005
weitergegeben. Der parent-Logger von logger_A_B_C hat zwar den Level WARNING, er
leitet die Meldung jedoch ebenfalls an die registrierten Handler und an seinen parentLogger weiter, da die Meldung nicht über die Methode log(“...“) von der Anwendung
abgesetzt wurde, sondern von einem anderen Logger an ihn weitergeleitet wurde.
1.4 Programmierrichtlinien
In diesem Abschnitt werden verschiedenen Vorschläge für die Verwendung der Logging API
zusammengefasst.
1.4.1 Initialisierung
Für jede Klasse einer Anwendung kann wie folgt ein Logger initialisiert werden:
private static final Logger LOGGER
= Logger.getLogger(<Klassenname>.class.getName());
Diese Methode bietet die folgenden Vorteile
•
Der Logger ist static und wird daher von allen Instanzen dieser Klasse verwendet.
•
In einer Anwendung bilden die mit dieser Methode initialisierten Logger die Klassen- und Packagestruktur der Anwendung nach.
•
Beim Umbenennen einer Klasse durch ein Refactoring-Tool wird auch der Name des Loggers
umbenannt
1.4.2 Logging Meldungen
Jedem Logging Level ist in der Klasse Logger eine Methode zugeordnet, mit der Meldungen der
entsprechenden Priorität an den Logger übermittelt werden können. Beispielsweise wird beim
Aufruf der Methode info(“Meldung“) die Meldung mit der Priorität INFO weitergeleitet. Diese
Methode können verwendet werden, um bequem ein Ereignis mit dem entsprechenden Level zu
melden.
Häufig werden beim Aufruf der Logging Methoden die Meldungen aus mehreren Strings zusammengesetzt.
Beispiel:
LOGGER.log(Level.INFO, “Verbindungsabau über Port “ + Portnumber
+ “ mit “ + IPnumber + “ war erfolgreich“);
Da das Zusammenfügen von Strings mit dem “+“ Operator in Java aufwändig ist, ist es in solchen
Fällen sinnvoll zunächst zu prüfen, ob der Logging Level vom Logger überhaupt bearbeitet wird:
if (LOGGER.isEnabled(Level.INFO)) {
LOGGER.log(Level.INFO,
“Verbindungsabau über Port “ + Portnumber
+ “ mit “ + IPnumber + “ war erfolgreich“);
}
1.4.3 Debugging
Für das Debugging einer Anwendung wird häufig ein Komandozeilenparameter verwendet. Dieser
wird beim Start abgefragt und als ein boolean Flag innerhalb der Anwendung implementiert. Vor
der Ausgabe von Debugging Informationen wird jeweils überprüft, ob dieses Flag gesetzt ist. Durch
das folgenden Schema kann dieses Flag ersetzt werden:
•
Der Komandozeilenparameter wird abgefragt. Falls gewünscht wird der Log-Level für die Logger
der Anwendung auf einen definierten Wert gesetzt. Dies kann geschehen, indem man z.B. den
Logging-Level für den root-Logger (““) auf eine entsprechend niedrigere Priorität setzt. Damit
9/11
18. Oktober 2005
werden in der gesamte Anwendung alle Meldungen mit der gleichen oder höheren Priorität
ausgegeben. Der Zugriff auf dem root-Logger wird in Abschnitt 1.4.4 erläutert. Falls nur die
Meldungen eines Teilpakets ausgegeben werden sollen kann natürlich auch nur der Logger
dieses Teilpakets durch das Setzen der Priorität entsprechen konfiguriert werden.
•
Bei der Ausgabe von Debugging Meldungen werden die Meldungen mit einer definierten Priorität an den Logger geschickt. Diese Priorität muss höher sein, als die zuvor für die Konfiguration
der Logger verwendetet Priorität, damit die Meldungen angenommen und durch den Handler
später ausgegeben werden. Durch Abfrage eines Kommandozeilenparameters und entsprechendes Setzen der Log-Level kann also die Ausgabe ein- oder ausgeschaltet werden.
Vorteile:
•
Das Verwalten des debug-Flags und ggf. die Weitergabe des Flags an Komponenten einer
Anwendung entfällt.
•
Es können bequem mehrere debug-Levels implementiert werden.
Nachteile:
•
Es muss darauf geachtet werden, dass der Logging Level im Handler nicht auf einem zu hohen
Wert eingestellt werden, so dass die gewünschten Debug Meldungen im Handler versehentlich
ausgefiltert werden.
1.4.4 root-Handler und root-Logger
In einer einfachen Anwendung genügt es den root-Handler für die Ausgabe von LoggingMeldungen zu verwenden. Damit können alle Meldungen direkt auf die Konsole ausgegeben
werden. Standardmäßig werden alle Meldungen mit dem Level INFO oder höher ausgegeben.
Möchte man in der Anwendung auch Meldungen mit niedrigerem Level ausgeben, so muss der
Level des root-Loggers und des root-Handlers verändert werden. Dies kann mit dem folgenden
Codefragment implementiert werden:
// der DefaultHandler hängt am root-Logger
Logger rootLogger = Logger.getLogger("");
Handler[] handlers = rootLogger.getHandlers();
// einen ConsoleHandler finden:
ConsoleHandler consoleHandler = null;
for (int i=0; i < handlers.length; i++) {
if (handlers[i] instanceof ConsoleHandler) {
consoleHandler = (ConsoleHandler) handlers[i];
}
}
// kein ConsoleHandler am root-Logger ?!
// wir hängen selbst einen an:
if (consoleHandler == null) {
consoleHandler = new java.util.logging.ConsoleHandler();
Logger.getLogger("").addHandler(consoleHandler);
}
consoleHandler.setLevel(Level.FINE);
rootLogger.setLevel(Level.FINE);
Damit werden alle Logging-Meldungen der Anwendung mit dem Level FINE oder höher ausgegeben.
10/11
18. Oktober 2005
1.5 Kurzanleitung
In diesem Abschnitt werden noch einmal die wichtigsten Schritte zur Verwendung der Logging-API
beschrieben.
1.5.1 Konfigurationsfile
Ein minimales Konfigurationsfile, mit dem alle Meldungen auf die Konsole ausgegeben werden und
der root-Logger alle Meldungen annimmt, kann wie folgt aussehen:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
.level = ALL
Dieses File kann unter dem Dateinamen logging.properties gespeichert werden. Möchte
man nur für einen Teil der Anwendung alle Meldungen ausgeben, für alle anderen Teile der
Anwendung lediglich Meldung mit dem Level WARNING oder höher:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
.level = WARNING
teil.package.level = ALL
1.5.2 Start der Anwendung
Um dem LoggingManager das oben beschriebene Konfigurationsfile zu übergeben, muss die JavaAnwendung mit dem zusätzlichen Parameter
-Djava.util.logging.config.file=logging.properties
gestartet werden.
1.5.3 Meldungen
In der Anwendung selbst wird zunächst der Logger innerhalb einer Klasse mit dem folgenden
Befehl erzeugt:
private static final Logger LOGGER
= Logger.getLogger(MeineKlasse.class.getName());
Eine Meldung mit dem Level INFO wird mit folgendem Kommando abgesetzt:
LOGGER.log(Level.INFO,“eine info-Meldung“);
Um einen Methodeneintritt zu melden kann folgender Code verwendet werden:
LOGGER.entering(“Klassennamen“, “Methodennamen“);
Die Meldung wird dann mit dem Level FINER ausgegeben. Falls gewünscht können zusätzlich
noch die Parameter der Methode ausgegeben werden:
LOGGER.entering( “Klassennamen“,
“Methodennamen“,
new Object[] {"param1", "param2"});
11/11
Herunterladen