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

package de.tgunkel.Java.LogTest;

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: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
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:

0 [main] INFO de.tgunkel.Java.LogTest.MyLogTest - Hello World
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=org.apache.log4j.ConsoleAppender
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

Logger.getRootLooger();

Alle anderen Logger werden über

Logger.getLogger(name);

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 logger=...;
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):

if( logger.isDebugEnabled())
{
    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:

log4j.additivity.MyLogger=false

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

-Dlog4j.configuration=

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.MyAppender1=org.apache.log4j.ConsoleAppender

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

# max nr of log messages (default seems to be 512)
log4j.appender.BusinessMailAppender.BufferSize=2048

Java Logging

Alternative zu log4j

Beispiel

private Logger mLogger;

...

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!");