Logging-Konfiguration über externe Datei
Java verwendet zum Logging ein zweistufiges System, das im
einfachsten Fall aus einem Logger-Objekt, das für die
Erzeugung der Log-Nachricht, dem LogRecord
,
zuständig ist und einem die Ausgabe steuernden Handler
besteht. Der Logger
ist üblicherweise auf
package- oder class-Ebene definiert, während der Handler
programmweit existiert. Im Gegensatz zum Logger
,
der initialisiert werden muss, muss ein Handler
nicht zwingend explizit erzeugt werden. Java initialisiert zur
Laufzeit als Standard einen ConsoleHandler
, der die
Ausgabe regelt. Er gibt die Meldungen bis zum Level INFO
incl. auf System.err
aus.
import java.util.logging.Logger; public class LoggingConfigBsp { public static void main(String[] args) { Logger logger = Logger.getAnonymousLogger(); logger.severe("schwerer Fehler"); logger.warning("Vorsicht!"); logger.fine("vielleicht anders...?"); logger.finest("gaaaaanz fein"); } }
Zur Demonstration dient das obige Quelltext-Beispiel, in dem in
main()
lediglich ein Logger
-Objekt
erzeugt wird und einige Meldungen auf unterschiedlichen
Logebenen generiert werden. Die Methoden severe(),
warning(), fine()
und finest()
erzeugen
Lognachrichten, deren Text als Parameter übergeben wird.
Führt man es aus, so erzeugt das Programm die folgende
Ausgabe:
Nov 02, 2017 7:59:57 AM allgemeines.logging.LoggingConfigBsp main SCHWERWIEGEND: schwerer Fehler Nov 02, 2017 7:59:57 AM allgemeines.logging.LoggingConfigBsp main WARNUNG: Vorsicht!
Zur Ausgabe wird, wie oben angesprochen, der Standard-ConsoleHandler
verwendet. Greift man nicht verändernd ein, so sind sowohl
der Logger
als auch der Handler
so
konfiguriert, dass sie die Meldungen nur bis zum Level INFO
ausgeben. Das Logging der Ebenen SEVERE
und WARNING
wird durchgeführt, da diese Logebenen oberhalb von INFO
liegen1. Eine Ausgabe der Meldungen
der Level FINE
und FINEST
unterbleibt
jedoch.
Für diese Konfiguration ist eine Datei logging.properties
verantwortlich, die sich im Verzeichnis lib
des JRE
befindet. Sie enthält2 den
folgenden, der Übersicht halber um die Kommentare
bereinigten Inhalt:
############################################################ # Default Logging Configuration File # ... handlers= java.util.logging.ConsoleHandler .level= INFO # ... java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter # ... java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter #...
Die erste Zeile legt fest, dass ein ConsoleHandler
als Standard-Handler Verwendung finden soll. Die zweite Zeile
definiert INFO
als globales Loglevel. In den beiden
dann folgenden Blöcken werden zunächst die
Standard-Einstellungen für einen FileHandler
,
der die Ausgabe in eine Datei steuert, und dann diejenigen
für einen ConsoleHandler
festgelegt. Details
zur Konfiguration können der Tabelle
unten entnommen werden.
LogManager
Die angegebenen Werte werden von einem LogManager
verwaltet, der auch alle Logger
-Objekte managed.
Als Singleton
existiert von ihm nur ein Objekt, auf das durch LogManager.getLogManager()
zugegriffen werden kann. Durch Aufruf der überladenen
Methode LogManager.readConfiguration()
kann der LogManager
zur Laufzeit veranlasst werden, die Konfigurationsdatei neu
einzulesen, sodass die vorgegebenen Standardeinstellungen u.U.
sogar geändert werden können.
Hierzu muss dann ggf.
eine abweichende Konfigurationsdatei angegeben werden, die die
Werte der Standarddatei funktional ersetzt. Sie kann durch einen
FileInputStream
eingelesen werden, der der Methode
als Parameter übergeben wird.
Der obige Quelltext kann hierzu auf folgende
Weise ergänzt werden, um die Konfigurationsdatei myLogging.properties
aus dem Arbeitsverzeichnis einzulesen:
Logger logger = Logger.getAnonymousLogger(); LogManager manager = LogManager.getLogManager(); try { manager.readConfiguration(new FileInputStream("myLogging.properties")); } catch (IOException e) { logger.warning(e.getMessage()); } //...
Eine zweite Möglichkeit besteht darin, die abgewandelte Konfigurationsdatei direkt als Systemeigenschaft einzutragen und sie dann durch Angabe des Property-Keys einzulesen:
System.setProperty("java.util.logging.config.file", "myLogging.properties"); //... manager.readConfiguration(new FileInputStream(System.getProperty("java.util.logging.config.file"))); //...
Geänderte Standard-Konfiguration
.level=FINEST handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=FINE
Enthält myLogging.properties
die obigen
Konfigurationsangaben, so wird durch .level=FINEST
das Ausgabelevel des Loggers global auf FINEST
gesetzt, in der zweiten Zeile der Standard-Handler
als ConsoleHandler
definiert und dessen
Ausgabelevel in der dritten Zeile schließlich auf FINE
gesetzt. Entsprechend wird die Nachricht der Ebene FINEST
hier unterdrückt.
Da die zentrale Konfigurationsdatei
funktional ersetzt wird, muss beachtet werden, dass hier
explizit ein Handler
aufgeführt werden muss.
Würde der Handler
(hier ConsoleHandler
)
nicht angegeben, so würde auch nichts auf System.err
ausgegeben.
Die Ausgabe sieht folgendermaßen aus:
Nov 04, 2017 9:51:05 AM allgemeines.logging.LoggingConfigBsp main SCHWERWIEGEND: schwerer Fehler Nov 04, 2017 9:51:05 AM allgemeines.logging.LoggingConfigBsp main WARNUNG: Vorsicht! Nov 04, 2017 9:51:05 AM allgemeines.logging.LoggingConfigBsp main FEIN: vielleicht anders...?
Ein zusätzlicher FileHandler
Soll zusätzlich zum ConsoleHandler
noch eine
Ausgabe des Loggings in eine Datei erfolgen, so kann die
Konfigurationsdatei entsprechend erweitert und zur Konfiguration
eines FileHandler
eingerichtet werden:
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler java.util.logging.FileHandler.pattern=%h/java%u.log java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter java.util.logging.FileHandler.level=WARNING
Im Quelltext muss der FileHandler
dann unter Angabe
des Speicherortes der Datei noch erzeugt und beim Logger
angemeldet werden. Hierbei ist wichtig, dass die
Konfigurationsdatei vor der Objektbildung des Handlers
eingelesen wird, ansonsten wird er entsprechend der dann noch
aktiven Standard-Konfigurationsdatei eingerichtet.
try { manager.readConfiguration(new FileInputStream("myLogging.properties")); FileHandler fileHandler = new FileHandler("myLogFile.log"); logger.addHandler(fileHandler); } catch (IOException e) { logger.warning(e.getMessage()); }
Konfiguration des FileHandler
Ein FileHandler
kann durch eine Anzahl an
Eigenschaften zusätzlich konfiguriert werden. Sie werden
durch den Punktoperator mit dem voll qualifizierten Namen des
Handlers verbundenen:
java.util.logging.FileHandler.pattern=%h/java%u.log
Ein Überblick über die zur Verfügung stehenden Eigenschaften finden sich in der folgenden Liste:
-
.level
- Ausgabelevel des Handlers
-
.filter
-
spezifiziert ein Objekt vom Typ
java.util.logging.Filter
. Filter ist ein funktionales Interface zur Feinsteuerung des Loggings. -
.formatter
-
spezifitiert einen
Formatter
, der das Format der Ausgabe steuert. Standard ist einXMLFormatter
. -
.encoding
- spezifiziert das Character-Set der Ausgabe.
-
.limit
-
spezifiziert eine ungefähre Maximalgröße
einer Ausgabedatei.
0
bezeichnet keine Grenze. -
.count
- spezifiziert, wieviele Ausgabedateien durchlaufen werden sollen.
-
.pattern
- spezifiziert ein Muster zur Benennung der Logdateien.
Musterangaben zur Benennung von Logdateien
Die Eigenschaft .pattern
zur Erzeugung des
Dateinamens von Log-Dateien definiert einen String, der
spezielle Musterangaben enthalten kann, die zur Laufzeit durch
die folgenden Angaben ersetzt werden:
"/" | der lokale Dateitrenner |
"%t" | das temporäre Verzeichnis des Systems |
"%h" | Pfad des Heimatverzeichnisses des Users |
"%g" | die aufsteigende Generationsnummer bei rotierenden Logs beginnend bei 0 |
"%u" | eine eindeutige Nummer, um Konflikte zu vermeiden, z.B. beim Zugriff auf bereits anderweitig geöffnete Dateien. |
"%%" | ein einfaches Prozentzeichen ("%") |
Quellen
https://docs.oracle.com/javase/7/docs/api/java/util/logging/package-summary.html
1) Zu den Loggingebenen siehe https://javabeginners.de/Allgemeines/Logging/Einfaches_Logging.php#loggingebenen
2) java version "1.8.0_25" auf MacOS 10.11.6
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.