Java Logging
Simple Logging Facade for Java SLF4J
Mit SLF4J bietet generische Log Methoden an, welches Framework dann wirklich zum Loggen benutzt wird, kann dann zur Laufzeit festgelegt werden. Sehr praktisch wenn ein Programm vertreiben möchte und den Kunden bezüglich des Log Frameworks die Qual der Wahl lassen will.
So einfach kann man dann Logs schreiben:
Erst slf4j-api-?.jar SLF4J dem Projekt hinzufügen und dann
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyLogTest
{
final static Logger logger1 = LoggerFactory.getLogger(MyLogTest.class);
final static Logger logger2 = LoggerFactory.getLogger("Foo");
public static void main(String[] args)
{
logger1.info("Hello World");
logger1.warn("Say '{}' for '{}' times", "Hello World", 3);
logger2.info("Bye bye");
}
}
Allerdings passiert mit den Logs erst mal nichts, es erscheint nur folgende Warnung in der Konsole
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J Simple
Um das Logging auszuprobieren, kann man dann
slf4j-simple-?.jar
in den Klassenpfad auchnehmen. Und schon erscheinen dann die Logmeldungen:
4 [main] WARN de.tgunkel.Java.LogTest.MyLogTest - Say 'Hello World' for '3' times
4 [main] INFO Foo - Bye bye
SLF4J NOP
Mit slf4j-nop-?.jar werden alle Logmeldungen hingegen einfach verworfen.
SLF4J log4J
Um log4j zu benutzen sind ein paar extra Schritte notwendig:
slf4j-log4j12-?.jar in der Klassenpfad aufnehmen. log4j-?.jar (von der log4j Webseite http://logging.apache.org/log4j/) runterladen und ebenfalls dem Klassenpfad hinzufügen Eine Datei log4j.properties anlegen:
log4j.appender.MyAppender1.layout=org.apache.log4j.PatternLayout
log4j.rootLogger = DEBUG, MyAppender1
und ebenfalls dem Klassenpfad hinzufügen.
Log4j
Komponenten
In Log4j gibt es 3 (4) Komponenten
- Loggers
- Layouts
- Appenders
- (und aus Gründen der Rückwärtskompatibilität noch Category)
Loggers
Der Root Logger hat keinen Namen und existiert implizit. Man erhält ihn über die statische Methode
Alle anderen Logger werden über
bezogen.
Logger sind hierarchisch über ihren Namen aufgebaut. Der Logger foo ist der Vater von foo.bar, welcher der Vater von foo.bar.blub ist, usw. Das kann z.B. so benutzt werden, dass man als Namen für den Logger den vollständigen Klassennamen de.foo.class1 oder nur den Paketnamen de.foo benutzt.
Logger ohne Vater haben automatisch den Root Logger als Vater.
Levels
Alle Logger haben einen Log Level. Es gibt folgende Level
- FATAL
- ERROR
- WARN
- INFO
- DEBUG
Wird für einen Logger kein Level konfiguriert, erhält er den Level des nächsten übergeordneten Vorgängers, der einen Level gesetzt hat. Der Root Logger hat immer ein Log Level gesetzt.
Geloggt wird im Java Code so:
logger.debug("Hello World");
logger.info("Hello World");
logger.warn("Hello World");
logger.error("Hello World");
logger.fatal("Hello World");
Die Meldung erscheint aber nur, wenn der Log Level mindestens auf dem Level steht, welches der Log Methode entspricht. Also logger.info() wirkt nur, wenn logger mindestens auf DEBUG oder INFO steht. Baut man den Text zum Loggen erst aufwendig zusammen, lohnt es sich oft, erst zu prüfen, ob dieses Level überhaupt geloggt werden soll (ansonsten lohnt sich dieser extra Test aber nicht):
{
String text="foo bar";
logger.debug("a"+"b"+r*s/t+"c"+text);
}
Appenders
Jedem Logger kann ein oder mehrere Appenders zugewiesen werden. Dorthin werden die Log Meldungen geschrieben. Appenders können z.B. Dateien (FileAppender, DailyRollingFileAppender), die Konsole, syslog, E-Mail (SMTPAppender) oder sogar eine Datenbanktabelle (JDBCAppender) sein. Der Log Text erscheint in allen Appenders des benutzten Loggers plus in allen Appenders aller Vorgänger inklusive dem Root Logger. Möchte man das nicht, kann man das sogenannte Additivity Flag setzen:
Layout
Ausgaben können formatiert werden. Interessant sind SimpleLayout, PatternLayout, HTMLLayout
Konfiguration
Wenn die Konfiguration über eine Properties Datei durchgeführt wird, gibt man diese Datei entweder über
beim Starten der VM an, oder man nennt die Datei log4j.properties, Log4j durchsucht alle Ordner im Klassenpfad nach einer solchen Datei.
Beispiel
log4j.appender.MyAppender2=org.apache.log4j.RollingFileAppender
log4j.appender.MyAppender2.file=logfile.log
log4j.appender.MyAppender2.MaxFileSize=10MB
log4j.appender.MyAppender2.MaxBackupIndex=1
log4j.appender.MyAppender2.layout=org.apache.log4j.PatternLayout
log4j.appender.MyAppender2.layout.ConversionPattern=%-5p [%t] (%F:%L) - %m%n
# send logs via mail
#log4j.appender.MyAppender2.layout.ConversionPattern=ROOT %d{ABSOLUTE} [%-30.30C{1}] [%-17t] %-5p %x - %m%n
log4j.appender.MyAppender3 = org.apache.log4j.net.SMTPAppender
log4j.appender.MyAppender3.To = foo@example.com <mailto:foo@example.com>
log4j.appender.MyAppender3.From = bar@example.com
log4j.appender.MyAppender3.SMTPHost <mailto:bar@example.comlog4j.appender.MyAppender3.SMTPHost> = mail.example.com
log4j.appender.MyAppender3.Subject = New Mail from your logger
log4j.appender.MyAppender3.LocationInfo = false
log4j.appender.MyAppender3.layout = org.apache.log4j.PatternLayout
log4j.appender.MyAppender3.layout.ConversionPattern=%m%n
log4j.appender.MyAppender3.EvaluatorClass = foo.bar.MailEventTriggerEvaluatorClass
log4j.rootLogger = DEBUG, MyAppender1
log4j.logger.MyLogger1 = ERROR, MyAppender2
log4j.additivity.MyLogger1=false
log4j.logger.MyLogger1.Foo = DEBUG, MyAppender2, MyAppender3
Achtung, der SQL Appender von log4j hat ein Limit an Zeilen, die geloggt werden. Sonst schneidet er die älteren Zeilen einfach ab
log4j.appender.BusinessMailAppender.BufferSize=2048
Java Logging
Alternative zu log4j
Beispiel
...
private Logger getLogger()
{
if(mLogger==null)
{
Level minLevel=Level.FINE;
mLogger=Logger.getLogger(this.getClass().toString());
mLogger.setLevel(minLevel);
Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(minLevel);
mLogger.addHandler(consoleHandler);
}
return mLogger;
}
...
getLogger().warning("Oh oh!");