Log4j ist ein Framework zur Unterstützung zentral konfiguriertem Loggings.
Zur Laufzeit und ohne Neucompilierung kann der Logging-Level umgeschaltet werden, um zusätzliche Meldungen zur Fehlersuche einzuschalten.
'Logger' definieren den Logging-Priority-Level und über welche 'Appender' die Logging-Meldungen ausgegeben werden.
'Appender' definieren den Ausgabekanal, zum Beispiel Console, Datei, DailyRollingFile, E-Mail, Socket, Telnet, JDBC und JMS.
'Layout' definiert die Ausgabeformatierung, zum Beispiel 'SimpleLayout', 'PatternLayout', 'HTMLLayout' und 'XMLLayout'.
Die Log4j-Konfiguration erfolgt wahlweise entweder programmatisch im Java-Sourcecode, über eine Property-Datei oder eine XML-Datei.
Erzeugen Sie folgende Verzeichnisstruktur ('\MeinWorkspace' kann bei Ihnen anders lauten) (Sie können stattdessen auch 'Log4j-Test' in Eclipse als Java-Projekt anlegen) (kontrollieren Sie die Struktur mit "tree /F"):
[\MeinWorkspace] '- [Log4j-Test] |- [bin] |- [lib] |- [logs] '- [src] '- [meinpackage1]
Speichern Sie in 'src\meinpackage1' die folgende Datei 'Main.java':
package meinpackage1; import org.apache.log4j.*; public class Main { private static Logger logger = Logger.getRootLogger(); public static void main( String[] args ) { try { SimpleLayout layout = new SimpleLayout(); ConsoleAppender consoleAppender = new ConsoleAppender( layout ); logger.addAppender( consoleAppender ); FileAppender fileAppender = new FileAppender( layout, "logs/MeineLogDatei.log", false ); logger.addAppender( fileAppender ); // ALL | DEBUG | INFO | WARN | ERROR | FATAL | OFF: logger.setLevel( Level.WARN ); } catch( Exception ex ) { System.out.println( ex ); } logger.debug( "Meine Debug-Meldung" ); logger.info( "Meine Info-Meldung" ); logger.warn( "Meine Warn-Meldung" ); logger.error( "Meine Error-Meldung" ); logger.fatal( "Meine Fatal-Meldung" ); } }
Öffnen Sie ein Kommandozeilenfenster ('Windows-Taste' + 'R', 'cmd') und geben Sie folgende Befehle ein (unter Windows können Sie den Kommandotext im Webbrowser mit gedrückter Maustaste markieren, mit 'Strg+C' zwischenspeichern und irgendwo im Kommandozeilenfenster mit rechter Maustaste, 'Einfügen' und 'Return' ausführen):
cd \MeinWorkspace\Log4j-Test
tree /F
set CLASSPATH=bin;lib/*
javac -d bin src/meinpackage1/Main.java
java meinpackage1.Main
type logs\MeineLogDatei.log
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
Testen Sie weitere Appender:
Testen Sie weitere Layout-Typen:
Speichern Sie in 'src\meinpackage2' die folgende Datei 'Main.java':
package meinpackage2; import org.apache.log4j.*; public class Main { private static Logger logger = Logger.getRootLogger(); public static void main( String[] args ) { try { PatternLayout layout = new PatternLayout( "%d{ISO8601} %-5p [%t] %c: %m%n" ); DailyRollingFileAppender fileAppender = new DailyRollingFileAppender( layout, "logs/MeineLogDatei.log", "'.'yyyy-MM-dd_HH-mm" ); logger.addAppender( fileAppender ); logger.setLevel( Level.ALL ); } catch( Exception ex ) { System.out.println( ex ); } new MeineKlasse2(); } }
Und die folgende Datei 'MeineKlasse2.java':
package meinpackage2; import org.apache.log4j.Logger; public class MeineKlasse2 { private static Logger logger = Logger.getLogger( MeineKlasse2.class ); MeineKlasse2() { logger.info( "Meine Info-Meldung aus MeineKlasse2." ); logger.error( "Meine Error-Meldung aus MeineKlasse2." ); } }
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
set CLASSPATH=bin;lib/*
javac -d bin src/meinpackage2/*.java
java meinpackage2.Main
type logs\MeineLogDatei.log*
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
Hier im Beispiel ist ein etwas aufwändigerer Appender gezeigt. Der 'DailyRollingFileAppender' speichert in vorgegebenen Zeitintervallen die Logdatei unter einem Dateinamen mit Zeitstempel (z.B. 'MeineLogDatei.log.2005-05-22_22-40') und leert die aktuelle Logdatei (z.B. 'MeineLogDatei.log'), damit sie nicht zu groß wird. Das Zeitintervall wird durch das dem Konstruktor übergebene 'datePattern' definiert, zum Beispiel so:
'.'yyyy-MM-dd_HH-mm | startet minütlich eine neue Logdatei (die Uhrzeit darf nicht mit ':' definiert werden) |
'.'yyyy-MM-dd | startet täglich eine neue Logdatei |
Um den Effekt beobachten zu können, müssen Sie die letzten beiden der oben genannten Kommandos nach einer Minute noch mal ausführen.
Es wird nicht das 'SimpleLayout', sondern stattdessen das 'PatternLayout' verwendet. Es generiert einen Meldetext, dessen Format durch das dem Konstruktor übergebene 'ConversionPattern' definiert wird:
%d{ISO8601} | Zeitstempel im internationalen ISO-8601-Format 'yyyy-MM-dd HH:mm:ss,SSS' |
%-5p | Prioritäts-Level (z.B. 'INFO'), das '-' bedeutet linksbündig, die '5' bedeutet verlängert auf 5 Zeichen (damit z.B. 'INFO'- und 'DEBUG'-Ausgaben bündig untereinander stehen) |
%t | Thread-Name |
%c | Kategoriename |
%m | Übergebener Meldetext |
%n | Zeilenwechsel |
%X{...} | MDC-Variable (Message Diagnostic Context) (gesetzt mit 'MDC.put()', siehe unten) |
Speichern Sie in 'src\meinpackage3' die folgende Datei 'Main.java':
package meinpackage3; import org.apache.log4j.PropertyConfigurator; public class Main { public static void main( String[] args ) { PropertyConfigurator.configureAndWatch( "log4j-3.properties", 60*1000 ); new MeineKlasse3(); } }
Und die folgende Datei 'MeineKlasse3.java':
package meinpackage3; import org.apache.log4j.Logger; public class MeineKlasse3 { private static Logger logger = Logger.getLogger( MeineKlasse3.class ); MeineKlasse3() { logger.info( "Meine Info-Meldung aus MeineKlasse3." ); logger.error( "Meine Error-Meldung aus MeineKlasse3." ); } }
Speichern Sie im '<projektverzeichnis>' die folgende Datei 'log4j-3.properties':
log4j.rootLogger=DEBUG, MeinConsoleAppender, MeinDaRoFiAppender log4j.appender.MeinConsoleAppender=org.apache.log4j.ConsoleAppender log4j.appender.MeinConsoleAppender.layout=org.apache.log4j.PatternLayout log4j.appender.MeinConsoleAppender.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n log4j.appender.MeinDaRoFiAppender=org.apache.log4j.DailyRollingFileAppender log4j.appender.MeinDaRoFiAppender.datePattern='.'yyyy-MM-dd_HH-mm log4j.appender.MeinDaRoFiAppender.file=logs/MeineLogDatei.log log4j.appender.MeinDaRoFiAppender.layout=org.apache.log4j.PatternLayout log4j.appender.MeinDaRoFiAppender.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
set CLASSPATH=bin;lib/*
javac -d bin src/meinpackage3/*.java
java meinpackage3.Main
type logs\MeineLogDatei.log
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
Sie können für bestimmte Packages oder Klassen spezielle Logging-Level einstellen. Tragen Sie dazu in die 'log4j-3.properties'-Datei Zeilen ein wie zum Beispiel:
log4j.logger.meinpackage3=DEBUG
Speichern Sie in 'src\meinpackage4' die folgende Datei 'Main.java':
package meinpackage4; import org.apache.log4j.xml.DOMConfigurator; public class Main { public static void main( String[] args ) { DOMConfigurator.configureAndWatch( "log4j-4.xml", 60*1000 ); new MeineKlasse4(); } }
Und die folgende Datei 'MeineKlasse4.java':
package meinpackage4; import org.apache.log4j.Logger; public class MeineKlasse4 { private static Logger logger = Logger.getLogger( MeineKlasse4.class ); MeineKlasse4() { logger.info( "Meine Info-Meldung aus MeineKlasse4." ); logger.error( "Meine Error-Meldung aus MeineKlasse4." ); } }
Speichern Sie im Verzeichnis '<projektverzeichnis>' die folgende Datei 'log4j-4.xml':
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="MeinAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="datePattern" value="'.'yyyy-MM-dd_HH-mm" /> <param name="file" value="logs/MeineLogDatei.log" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p [%t] %c: %m%n" /> </layout> </appender> <root> <priority value="INFO" /> <appender-ref ref="MeinAppender" /> </root> </log4j:configuration>
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
set CLASSPATH=bin;lib/*
javac -d bin src/meinpackage4/*.java
java meinpackage4.Main
type logs\MeineLogDatei.log
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
Speichern Sie in 'src\meinpackage5' die folgende Datei 'Main.java':
package meinpackage5; public class Main { public static void main( String[] args ) { new MeineKlasse5(); } }
Und die folgende Datei 'MeineKlasse5.java':
package meinpackage5; import org.apache.log4j.Level; public class MeineKlasse5 { private static MeinLogger logger = MeinLogger.getInstance(); MeineKlasse5() { logger.log( Level.ERROR, this, "E002", new String[] { "abc", "xyz" } ); } }
Und die folgende Datei 'MeinLogger.java':
package meinpackage5; import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.apache.log4j.*; import org.apache.log4j.xml.DOMConfigurator; public class MeinLogger { private static final String LOG4J_CONFIG_FILE = "log4j-5.xml"; private static final String MEIN_LOGGER_NAME = "MeinLogger"; private static final String MESSAGES_RESBUNDLE = "messages"; private static ResourceBundle messagesResBundle; private static MeinLogger meinLogger; private static Logger log4jLogger; // private damit Singleton private MeinLogger() { init(); } private synchronized void init() { try { DOMConfigurator.configureAndWatch( LOG4J_CONFIG_FILE, 60*1000 ); log4jLogger = Logger.getLogger( MEIN_LOGGER_NAME ); messagesResBundle = ResourceBundle.getBundle( MESSAGES_RESBUNDLE ); log4jLogger.setResourceBundle( messagesResBundle ); } catch( MissingResourceException ex ) { System.err.println( "Fehler: '" + MESSAGES_RESBUNDLE + "'-.properties-Datei fehlt!" ); } catch( Exception ex ) { System.err.println( "Fehler bei Logger-Initialisierung!" ); } } // Singleton-Instanz public static synchronized MeinLogger getInstance() { if( meinLogger == null ) meinLogger = new MeinLogger(); return meinLogger; } public synchronized void log( Level level, Object caller, String id, Object[] parms ) { MDC.put( "clss", caller.getClass().getName() ); MDC.put( "id", id ); String message = id; if( null != messagesResBundle ) { try { message = messagesResBundle.getString( id ); } catch( MissingResourceException ex ) {/**/} } if( null != parms ) message = MessageFormat.format( message, parms ); switch( level.toInt() ) { case Priority.ALL_INT: case Priority.DEBUG_INT: log4jLogger.debug( message ); break; case Priority.INFO_INT: log4jLogger.info( message ); break; case Priority.WARN_INT: log4jLogger.warn( message ); break; case Priority.ERROR_INT: log4jLogger.error( message ); break; case Priority.FATAL_INT: log4jLogger.fatal( message ); break; } } public boolean isEnabledFor( Level level ) { return log4jLogger.isEnabledFor( level ); } }
Speichern Sie im Verzeichnis '<projektverzeichnis>' die folgende Datei 'log4j-5.xml':
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="MeinStandardAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="datePattern" value="'.'yyyy-MM-dd" /> <param name="file" value="logs/MeineLogDatei.log" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p %X{id} [%t] %X{clss}: %m%n" /> </layout> </appender> <root> <priority value="INFO" /> <appender-ref ref="MeinStandardAppender" /> </root> </log4j:configuration>
Speichern Sie im Verzeichnis 'res' die folgende Datei 'messages.properties':
E002=My Message with the two Parameters {0} and {1}.
Und die folgende Datei 'messages_de.properties':
E002=Meine Meldung mit den zwei Parametern {0} und {1}.
Ihre Verzeichnisstruktur enthält jetzt folgende Verzeichnisse und Dateien (kontrollieren Sie es mit "tree /F"):
[\MeinWorkspace] '- [Log4j-Test] |- [bin] |- [lib] | '- log4j-1.2.16.jar |- [logs] |- [res] | |- messages.properties | '- messages_de.propertie |- [src] | '- [meinpackage5] | |- Main.java | |- MeineKlasse5.java | '- MeinLogger.java '- log4j-5.xml
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
tree /F
set CLASSPATH=bin;res;lib/*
javac -d bin src/meinpackage5/*.java
java meinpackage5.Main
type logs\MeineLogDatei.log
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
Als Ergebnis erhalten Sie in etwa:
2005-05-23 22:04:47,019 ERROR E002 [main] meinpackage5.MeineKlasse5: Meine Meldung mit den zwei Parametern abc und xyz.
Die 'main()'-Methode braucht nicht mehr 'DOMConfigurator.configureAndWatch()' aufzurufen, da dies in 'MeinLogger.init()' geschieht.
Um den Logger zu benutzen, wird in 'MeineKlasse5' nicht der Log4j-'Logger', sondern der eigene Logger 'MeinLogger' instanziiert.
Um verschiedene Sprachen realisieren zu können, wird nicht direkt der Meldetext, sondern nur die Message-ID (im Beispiel 'E002') dem Logger übergeben. Für jede implementierte Sprache müssen die Meldetexte in 'messages_XX.properties'-Dateien vorgehalten werden, wobei 'XX' durch das Sprachkürzel ersetzt werden muss (z.B. 'de'). Zusätzlich können in den Meldetext einzusetzende Parameter ('{0}', '{1}', ...) als 'String[]' übergeben werden.
'MeinLogger' erzeugt nicht nur den Meldetext aus der Message-ID, sondern erzeugt zusätzlich zwei MDC-Strings die dem 'Message Diagnostic Context' des Log4j hinzugefügt werden. Mit 'MDC.put()' werden unter den angegebenen Namen 'clss' und 'id' zwei Text-Strings abgelegt, die über die Ausdrücke '%X{clss}' und '%X{id}' im 'ConversionPattern' des 'PatternLayout' in der 'log4j-5.xml'-Datei im Log-Text eingefügt werden.
Die Methode 'isEnabledFor()' kann verwendet werden, um dem Logger für einen bestimmten Priority-Level (z.B. 'DEBUG') zu übergebende aber zeitaufwändig zu berechnende Ausdrücke nur dann berechnen zu müssen, wenn wirklich der entsprechende Level eingeschaltet ist (allerdings muss bereits der Logger-Level entsprechend gesetzt sein, nur beim Appender genügt nicht).
Speichern Sie in 'src\meinpackage6' die folgende Datei 'Main.java':
package meinpackage6; import org.apache.log4j.xml.DOMConfigurator; public class Main { public static void main( String[] args ) { DOMConfigurator.configureAndWatch( "log4j-6.xml", 60*1000 ); new MeineKlasse6(); } }
Und die folgende Datei 'MeineKlasse6.java':
package meinpackage6; import org.apache.log4j.Logger; public class MeineKlasse6 { private static Logger stdLogger = Logger.getLogger( MeineKlasse6.class ); private static Logger hbtLogger = Logger.getLogger( "MeinHeartbeatLogger" ); MeineKlasse6() { stdLogger.info( "Meine Info-Meldung aus MeineKlasse6." ); stdLogger.error( "Meine Error-Meldung aus MeineKlasse6." ); hbtLogger.info( "Meine HeartbeatLogger-Meldung." ); } }
Und die folgende Datei 'HeartbeatFileAppender.java':
package meinpackage6; import java.io.*; import org.apache.log4j.FileAppender; import org.apache.log4j.helpers.LogLog; import org.apache.log4j.spi.LoggingEvent; public class HeartbeatFileAppender extends FileAppender { private RandomAccessFile raFile; /** @see org.apache.log4j.FileAppender#activateOptions() */ @Override public void activateOptions() { super.activateOptions(); if( null == raFile ) { if( null != fileName ) { try { raFile = new RandomAccessFile( fileName, "rw" ); } catch( FileNotFoundException ex ) { // } } if( null == raFile ) { LogLog.error( "Heartbeat-Logdatei '" + fileName + "' kann nicht angelegt werden fuer '" + name + "'." ); } } } /** @see org.apache.log4j.WriterAppender#subAppend(LoggingEvent) */ @Override protected void subAppend( LoggingEvent event ) { // Nicht 'super.subAppend(event)' aufrufen! if( null != raFile ) { try { raFile.seek( 0 ); raFile.setLength( 0 ); raFile.writeBytes( getLayout().format( event ) ); } catch( IOException ex ) { LogLog.error( "Probleme beim Schreiben in Heartbeat-Logdatei '" + fileName + "' fuer '" + name + "'." ); } } } }
Speichern Sie im Verzeichnis '<projektverzeichnis>' die folgende Datei 'log4j-6.xml':
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="MeinStandardAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="datePattern" value="'.'yyyy-MM-dd" /> <param name="file" value="logs/MeineLogDatei.log" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p [%t] %c: %m%n" /> </layout> </appender> <appender name="MeinHeartbeatAppender" class="meinpackage6.HeartbeatFileAppender"> <param name="file" value="logs/MeineHeartbeatLogDatei.log" /> <param name="Append" value="false" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p [%t] %c: %m%n" /> </layout> </appender> <logger name="MeinHeartbeatLogger" additivity="false"> <level value="INFO" /> <appender-ref ref="MeinHeartbeatAppender" /> </logger> <root> <priority value="INFO" /> <appender-ref ref="MeinStandardAppender" /> </root> </log4j:configuration>
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
set CLASSPATH=bin;lib/*
javac -d bin src/meinpackage6/*.java
java meinpackage6.Main
java meinpackage6.Main
java meinpackage6.Main
type logs\MeineLogDatei.log
type logs\MeineHeartbeatLogDatei.log
Passen Sie den Pfad '\MeinWorkspace\Log4j-Test' an Ihr '<projektverzeichnis>' an.
[\MeinWorkspace] '- [Log4j-Test] |- [bin] |- [lib] | '- log4j-1.2.16.jar |- [logs] |- [res] '- [src] '- [meinpackage7] |- [pkg1] |- [pkg2] | '- [pkg22] '- [pkg3] '- [pkg33]
Speichern Sie folgende Klassen:
'src\meinpackage7\Main.java':
package meinpackage7; import meinpackage7.pkg1.Klasse1; import meinpackage7.pkg2.Klasse2; import meinpackage7.pkg2.pkg22.Klasse22; import meinpackage7.pkg3.Klasse3; import meinpackage7.pkg3.pkg33.Klasse33; import org.apache.log4j.Logger; public class Main { static final Logger CLASS_LOGGER = Logger.getLogger( Main.class ); static final Logger ADD_T_LOGGER = Logger.getLogger( "AdditivityTrueLogger" ); static final Logger ADD_F_LOGGER = Logger.getLogger( "AdditivityFalseLogger" ); public static void main( String[] args ) { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); ADD_T_LOGGER.info( "Mein Text" ); ADD_T_LOGGER.error( "Mein Text" ); ADD_F_LOGGER.info( "Mein Text" ); ADD_F_LOGGER.error( "Mein Text" ); Klasse1.log(); Klasse2.log(); Klasse3.log(); Klasse22.log(); Klasse33.log(); System.out.println( "Ergebnisse siehe Logdateien im logs-Verzeichnis." ); } }
'src\meinpackage7\pkg1\Klasse1.java':
package meinpackage7.pkg1; import org.apache.log4j.Logger; public class Klasse1 { static final Logger CLASS_LOGGER = Logger.getLogger( Klasse1.class ); static final Logger ADD_T_LOGGER = Logger.getLogger( "AdditivityTrueLogger" ); static final Logger ADD_F_LOGGER = Logger.getLogger( "AdditivityFalseLogger" ); public static void log() { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); ADD_T_LOGGER.info( "Mein Text" ); ADD_T_LOGGER.error( "Mein Text" ); ADD_F_LOGGER.info( "Mein Text" ); ADD_F_LOGGER.error( "Mein Text" ); } }
'src\meinpackage7\pkg2\Klasse2.java':
package meinpackage7.pkg2; import org.apache.log4j.Logger; public class Klasse2 { static final Logger CLASS_LOGGER = Logger.getLogger( Klasse2.class ); public static void log() { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); } }
'src\meinpackage7\pkg2\pkg22\Klasse22.java':
package meinpackage7.pkg2.pkg22; import org.apache.log4j.Logger; public class Klasse22 { static final Logger CLASS_LOGGER = Logger.getLogger( Klasse22.class ); public static void log() { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); } }
'src\meinpackage7\pkg3\Klasse3.java':
package meinpackage7.pkg3; import org.apache.log4j.Logger; public class Klasse3 { static final Logger CLASS_LOGGER = Logger.getLogger( Klasse3.class ); public static void log() { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); } }
'src\meinpackage7\pkg3\pkg33\Klasse33.java':
package meinpackage7.pkg3.pkg33; import org.apache.log4j.Logger; public class Klasse33 { static final Logger CLASS_LOGGER = Logger.getLogger( Klasse33.class ); public static void log() { CLASS_LOGGER.info( "Mein Text" ); CLASS_LOGGER.error( "Mein Text" ); } }
Speichern Sie folgende 'res\log4j.properties'-Datei:
log4j.rootLogger=error, RootAppender, RootErrorAppender log4j.logger.AdditivityTrueLogger=info, AdditivityTrueAppender log4j.additivity.AdditivityTrueLogger=true log4j.logger.AdditivityFalseLogger=info, AdditivityFalseAppender log4j.additivity.AdditivityFalseLogger=false log4j.logger.meinpackage7.pkg2=info, pkg2Appender log4j.additivity.meinpackage7.pkg2=true log4j.logger.meinpackage7.pkg3=info, pkg3Appender log4j.additivity.meinpackage7.pkg3=false log4j.appender.AdditivityFalseAppender=org.apache.log4j.RollingFileAppender log4j.appender.AdditivityFalseAppender.file=logs/AdditivityFalse.log log4j.appender.AdditivityFalseAppender.MaxFileSize=100KB log4j.appender.AdditivityFalseAppender.MaxBackupIndex=10 log4j.appender.AdditivityFalseAppender.layout=org.apache.log4j.PatternLayout log4j.appender.AdditivityFalseAppender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.AdditivityTrueAppender=org.apache.log4j.RollingFileAppender log4j.appender.AdditivityTrueAppender.file=logs/AdditivityTrue.log log4j.appender.AdditivityTrueAppender.MaxFileSize=100KB log4j.appender.AdditivityTrueAppender.MaxBackupIndex=10 log4j.appender.AdditivityTrueAppender.layout=org.apache.log4j.PatternLayout log4j.appender.AdditivityTrueAppender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.pkg2Appender=org.apache.log4j.RollingFileAppender log4j.appender.pkg2Appender.file=logs/pkg2.log log4j.appender.pkg2Appender.MaxFileSize=100KB log4j.appender.pkg2Appender.MaxBackupIndex=10 log4j.appender.pkg2Appender.layout=org.apache.log4j.PatternLayout log4j.appender.pkg2Appender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.pkg3Appender=org.apache.log4j.RollingFileAppender log4j.appender.pkg3Appender.file=logs/pkg3.log log4j.appender.pkg3Appender.MaxFileSize=100KB log4j.appender.pkg3Appender.MaxBackupIndex=10 log4j.appender.pkg3Appender.layout=org.apache.log4j.PatternLayout log4j.appender.pkg3Appender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.RootAppender=org.apache.log4j.RollingFileAppender log4j.appender.RootAppender.file=logs/Root.log log4j.appender.RootAppender.MaxFileSize=100KB log4j.appender.RootAppender.MaxBackupIndex=10 log4j.appender.RootAppender.layout=org.apache.log4j.PatternLayout log4j.appender.RootAppender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.RootErrorAppender=org.apache.log4j.RollingFileAppender log4j.appender.RootErrorAppender.file=logs/RootError.log log4j.appender.RootErrorAppender.MaxFileSize=100KB log4j.appender.RootErrorAppender.MaxBackupIndex=10 log4j.appender.RootErrorAppender.layout=org.apache.log4j.PatternLayout log4j.appender.RootErrorAppender.layout.ConversionPattern=<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %C{1} %c{2} : %m%n log4j.appender.RootErrorAppender.threshold=error
Im Beispiel wird in der log4j.properties-Datei "%C{1} %c{2}" verwendet: Erläuterungen zur Syntax finden Sie unter http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html. Bitte beachten Sie: Während "%c" (mit kleinem "c") bedenkenlos verwendet werden kann, sollte "%C" (mit großem "C") nur in besonderen Test-/Debug-Situationen verwendet werden, da es die Performance beeinträchtigt.
Ihre Verzeichnisstruktur enthält jetzt folgende Verzeichnisse und Dateien (kontrollieren Sie es mit "tree /F"):
[\MeinWorkspace] '- [Log4j-Test] |- [bin] |- [lib] | '- log4j-1.2.16.jar |- [logs] |- [res] | '- log4j.properties '- [src] '- [meinpackage7] |- Main.java |- [pkg1] | '- Klasse1.java |- [pkg2] | |- Klasse2.java | '- [pkg22] | '- Klasse22.java '- [pkg3] |- Klasse3.java '- [pkg33] '- Klasse33.java
Öffnen Sie ein Kommandozeilenfenster und geben Sie folgende Befehle ein:
cd \MeinWorkspace\Log4j-Test
del logs\*.log*
tree /F
set CLASSPATH=bin;src;res;lib/*
javac -d bin src/meinpackage7/*.java
java meinpackage7.Main
type logs\*.log
Sie erhalten folgende Logdateien im logs-Verzeichnis:
<2009-05-21 13:12:14> INFO : Main AdditivityFalseLogger : Mein Text <2009-05-21 13:12:14> ERROR : Main AdditivityFalseLogger : Mein Text <2009-05-21 13:12:14> INFO : Klasse1 AdditivityFalseLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 AdditivityFalseLogger : Mein Text
<2009-05-21 13:12:14> INFO : Main AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Main AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> INFO : Klasse1 AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 AdditivityTrueLogger : Mein Text
'pkg2.log':
<2009-05-21 13:12:14> INFO : Klasse2 pkg2.Klasse2 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse2 pkg2.Klasse2 : Mein Text <2009-05-21 13:12:14> INFO : Klasse22 pkg22.Klasse22 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse22 pkg22.Klasse22 : Mein Text
'pkg3.log':
<2009-05-21 13:12:14> INFO : Klasse3 pkg3.Klasse3 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse3 pkg3.Klasse3 : Mein Text <2009-05-21 13:12:14> INFO : Klasse33 pkg33.Klasse33 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse33 pkg33.Klasse33 : Mein Text
'Root.log':
<2009-05-21 13:12:14> ERROR : Main meinpackage7.Main : Mein Text <2009-05-21 13:12:14> INFO : Main AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Main AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 pkg1.Klasse1 : Mein Text <2009-05-21 13:12:14> INFO : Klasse1 AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> INFO : Klasse2 pkg2.Klasse2 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse2 pkg2.Klasse2 : Mein Text <2009-05-21 13:12:14> INFO : Klasse22 pkg22.Klasse22 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse22 pkg22.Klasse22 : Mein Text
<2009-05-21 13:12:14> ERROR : Main meinpackage7.Main : Mein Text <2009-05-21 13:12:14> ERROR : Main AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 pkg1.Klasse1 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse1 AdditivityTrueLogger : Mein Text <2009-05-21 13:12:14> ERROR : Klasse2 pkg2.Klasse2 : Mein Text <2009-05-21 13:12:14> ERROR : Klasse22 pkg22.Klasse22 : Mein Text
Die ersten beiden Logdateien (Additivity...log) zeigen nichts Besonderes.
Auch die nächsten beiden Logdateien (pkg...log) sind wie erwartet. Erwähnenswert ist höchstens, dass die log4j.logger.meinpackage...-Anweisung sich nicht nur auf das in der Anweisung genannte Package bezieht, sondern auch auf alle Unter-Packages (im Beispiel die Klassen Klasse22 und Klasse33 in den Unter-Packages pkg22 und pkg33).
Interessant ist die Root.log:
"INFO : Main meinpackage7.Main" und "INFO : Klasse1 pkg1.Klasse1":
Diese INFO-Meldungen fehlen, weil wegen "log4j.rootLogger=error, ..." nur ERROR- und keine INFO-Meldungen geloggt werden.
"INFO : ... AdditivityTrueLogger":
Obwohl für den rootLogger definiert wurde, dass nur ERROR- und keine INFO-Meldungen geloggt werden,
werden diese INFO-Meldungen geloggt, wegen "log4j.logger.AdditivityTrueLogger=info, AdditivityTrueAppender".
Obwohl hier ein anderer Appender genannt ist, bezieht sich die Logging-Level-Umdefinition auch zusätzlich auf den rootLogger/RootAppender.
"INFO : Klasse2 pkg2.Klasse2" und "INFO : Klasse22 pkg22.Klasse22":
Obwohl für den rootLogger definiert wurde, dass nur ERROR- und keine INFO-Meldungen geloggt werden,
werden diese INFO-Meldungen geloggt, wegen "log4j.logger.meinpackage7.pkg2=info, pkg2Appender".
Obwohl auch hier ein anderer Appender genannt ist, bezieht sich die Logging-Level-Umdefinition auch wieder zusätzlich auf den rootLogger/RootAppender.
"... Main AdditivityFalseLogger":
Fehlt, weil durch "log4j.additivity.AdditivityFalseLogger=false" die Verbindung zum rootLogger unterbrochen wurde
(auch ERROR-Meldungen fehlen).
"... Klasse3 pkg3.Klasse3" und "... Klasse33 pkg33.Klasse33":
Fehlen, weil durch "log4j.additivity.meinpackage7.pkg3=false" die Verbindung zum rootLogger unterbrochen wurde.
Hierbei wird zweierlei leicht übersehen:
a) Dies gilt nicht nur für INFO-Meldungen, sondern auch für ERROR-Meldungen.
b) Dies gilt nicht nur für das Package pkg3, sondern auch für alle Unter-Packages, wie pkg33.
Zur RootError.log:
Der RootErrorAppender zeigt, dass nicht nur im Logger auf einen Logging-Level begrenzt werden kann, sondern auch im Appender, nämlich per "log4j.appender.RootErrorAppender.threshold=error".
Das folgende Beispiel demonstriert, wie das Logging asynchron erfolgen kann. Falls Ihre Applikation viel loggt, kann dies eine merkliche Performanceverbesserung bringen.
Anders als bei den bisherigen Beispielen wird hier Maven verwendet.
Wechseln Sie in Ihr Workspace-Verzeichnis (z.B. \MeinWorkspace) und führen Sie folgende Kommandos aus:
cd \MeinWorkspace
md Log4j-Async
cd Log4j-Async
md src\main\resources
md src\main\java\log4jdemo
tree /F
Erstellen Sie im Log4j-Async-Projektverzeichnis die Maven-Projektkonfigurationsdatei: pom.xml
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>log4jdemo</groupId> <artifactId>Log4j-Async</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>log4jdemo.Log4jZeitmessung</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
Erzeugen Sie im src/main/resources-Verzeichnis die Log4j1-Konfiguration: log4j.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration> <appender name="MeinFileAppender" class="org.apache.log4j.FileAppender"> <param name="file" value="logs/MeineLogDatei.log" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p [%t] %c: %m%n" /> </layout> </appender> <appender name="MeinAsyncAppender" class="org.apache.log4j.AsyncAppender"> <param name="BufferSize" value="500" /> <appender-ref ref="MeinFileAppender" /> </appender> <root> <priority value="info" /> <appender-ref ref="MeinAsyncAppender" /> </root> </log4j:configuration>
Erzeugen Sie im src/main/java/log4jdemo-Verzeichnis die Main-Klasse: Log4jZeitmessung.java
package log4jdemo; import org.apache.log4j.Logger; /** Logging-Zeitmessung: Asynchrones Logging mit AsyncAppender ist etwa 20 % schneller */ public class Log4jZeitmessung { private static Logger logger = Logger.getLogger( Log4jZeitmessung.class ); public static void main( String[] args ) { long startZeitMs = System.nanoTime() / 1000000L; long dauerMs = 0; for( int i = 0; i < 10000; i++ ) { dauerMs = System.nanoTime() / 1000000L - startZeitMs; logger.info( "i: " + i + ", Aktuelle Dauer: " + dauerMs + " ms" ); } logger.info( "Gesamtauer: " + dauerMs ); System.out.println( "Gesamtauer: " + dauerMs + " ms" ); // Etwas Nachlaufzeit fuer asynchrones Logging: try { Thread.sleep( 1000 ); } catch( InterruptedException e ) {} } }
Die Projektstruktur sieht jetzt so aus (überprüfen Sie es mit tree /F):
[\MeinWorkspace\Log4j-Async] |- [src] | '- [main] | |- [java] | | '- [log4jdemo] | | '- Log4jZeitmessung.java | '- [resources] | '- log4j.xml '- pom.xml
Da die log4j.xml-Konfigurationsdatei im Classpath liegt, wird kein zusätzlicher Aufrufparameter benötigt. Mit Hilfe des maven-assembly-plugin wird eine ausführbare Jar-Datei erzeugt, die alle benötigten Abhängigkeiten enthält und einfach gestartet werden kann. Führen Sie im Kommandozeilenfenster aus:
cd \MeinWorkspace\Log4j-Async
mvn clean package
java -jar target\Log4j-Async-1.0-SNAPSHOT-jar-with-dependencies.jar
dir logs
Bei der oben gezeigten Konfiguration in der log4j.xml ist im root-Element der asynchrone Appender konfiguriert:
<root> <priority value="info" /> <appender-ref ref="MeinAsyncAppender" /> </root>
Um auf synchrones Logging umzuschalten, ersetzen Sie in diesem Block einfach die Referenz zum Appender:
<root> <priority value="info" /> <appender-ref ref="MeinFileAppender" /> </root>
Je nach PC beträgt bei diesem simplen Beispiel der Performancevorteil durch asynchrones Logging circa 20 %.
Falls Sie zusätzlich zum Haupt-Logger einen weiteren unabhängigen Logger benötigen:
Definieren Sie zusätzlich zum Haupt-Appender einen weiteren (z.B. mit eigener getrennter Logdatei),
definieren Sie zu diesem Appender einen Logger und
setzen Sie die Additivity auf false, damit nicht vom Root-Logger geerbt wird:
log4j.logger.MeinZweiterLogger=INFO, MeinZweiterAppender
log4j.additivity.MeinZweiterLogger=false
log4j.appender.MeinZweiterAppender=...
In der Java-Klasse rufen Sie den zweiten Logger über seinen Logger-Namen auf:
Logger meinSpezialLogger = Logger.getLogger( "MeinZweiterLogger" );
Ein genaueres Beispiel hierzu finden Sie in '"log4j.additivity...=false"' und genauere Erläuterungen unter manual.html#additivity.
Falls im Logging-Aufruf ein zeitaufwändig zu berechnender Ausdruck steht, ist es besser, vor den Logging-Aufruf eine Abfrage zu stellen, ob denn der Logging-Level überhaupt ein Logging erfordert. Zum Beispiel so:
if( logger.isEnabledFor( Level.DEBUG ) )
logger.debug( <zeitaufwändiger Ausdruck> );
Das funktioniert allerdings nur, wenn der Level bereits beim Logger entsprechend gesetzt ist und nicht erst beim Appender (per log4j.appender...threshold=...).
Das folgende Beispiel demonstriert:
Apache Log4j 2, Migrating from Log4j 1.x, Log4j2 Configuration, Log4j2 Appenders
Wechseln Sie in Ihr Workspace-Verzeichnis (z.B. \MeinWorkspace) und führen Sie folgende Kommandos aus:
cd \MeinWorkspace
md Log4j1-RollingFileAppender
cd Log4j1-RollingFileAppender
md src\main\resources
md src\main\java\log4j1demo
tree /F
Erstellen Sie im Log4j1-RollingFileAppender-Projektverzeichnis die Maven-Projektkonfigurationsdatei: pom.xml
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>log4j1demo</groupId> <artifactId>Log4j1-RollingFileAppender</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>log4j1demo.Log4j1Demo</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
Erzeugen Sie im src/main/resources-Verzeichnis die Log4j1-Konfiguration: log4j.properties
log4j.rootLogger=INFO, RoFiAppender log4j.appender.RoFiAppender=org.apache.log4j.RollingFileAppender log4j.appender.RoFiAppender.file=logs/Log4j1-RollingFileAppender.log log4j.appender.RoFiAppender.MaxFileSize=10KB log4j.appender.RoFiAppender.MaxBackupIndex=3 log4j.appender.RoFiAppender.layout=org.apache.log4j.PatternLayout log4j.appender.RoFiAppender.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
Als Logging-Level ist INFO konfiguriert. RollingFileAppender starten nach konfigurierbaren Kriterien neue Logdateien. In diesem Beispiel wird eine neue Logdatei gestartet, wenn die Dateigröße MaxFileSize von 10 KByte überschreitet. MaxBackupIndex 3 definiert, dass maximal drei vorherige Logdateien beibehalten werden. Ältere Logdateien werden gelöscht.
Erzeugen Sie im src/main/java/log4j1demo-Verzeichnis die Main-Klasse: Log4j1Demo.java
package log4j1demo; import org.apache.log4j.Logger; public class Log4j1Demo { private static Logger logger = Logger.getLogger( Log4j1Demo.class ); public static void main( String[] args ) { logger.debug( "Meine Debug-Meldung" ); logger.info( "Meine Info-Meldung" ); logger.warn( "Meine Warn-Meldung" ); logger.error( "Meine Error-Meldung" ); logger.fatal( "Meine Fatal-Meldung" ); } }
Sehen Sie sich die Javadoc an zu: Logger.
Die Projektstruktur sieht jetzt so aus (überprüfen Sie es mit tree /F):
[\MeinWorkspace\Log4j1-RollingFileAppender] |- [src] | '- [main] | |- [java] | | '- [log4j1demo] | | '- Log4j1Demo.java | '- [resources] | '- log4j.properties '- pom.xml
Da die log4j.properties-Konfigurationsdatei im Classpath liegt, wird kein zusätzlicher Aufrufparameter benötigt. Mit Hilfe des maven-assembly-plugin wird eine ausführbare Jar-Datei erzeugt, die alle benötigten Abhängigkeiten enthält und einfach gestartet werden kann. Führen Sie im Kommandozeilenfenster aus:
cd \MeinWorkspace\Log4j1-RollingFileAppender
mvn clean package
java -jar target\Log4j1-RollingFileAppender-1.0-SNAPSHOT-jar-with-dependencies.jar
dir logs
type logs\Log4j1-RollingFileAppender.log
Sie erhalten:
2017-01-01 01:01:01,000 INFO [main] log4j1demo.Log4j1Demo: Meine Info-Meldung 2017-01-01 01:01:01,000 WARN [main] log4j1demo.Log4j1Demo: Meine Warn-Meldung 2017-01-01 01:01:01,000 ERROR [main] log4j1demo.Log4j1Demo: Meine Error-Meldung 2017-01-01 01:01:01,000 FATAL [main] log4j1demo.Log4j1Demo: Meine Fatal-Meldung
Die Debug-Meldung wird nicht geloggt, weil in der log4j.properties beim log4j.rootLogger der Logging-Level "INFO" konfiguriert ist.
Wechseln Sie in Ihr Workspace-Verzeichnis (z.B. \MeinWorkspace) und führen Sie folgende Kommandos aus:
cd \MeinWorkspace
md Log4j2-RollingFileAppender
cd Log4j2-RollingFileAppender
md src\main\java\log4j2demo
tree /F
Erstellen Sie im Log4j2-RollingFileAppender-Projektverzeichnis die Maven-Projektkonfigurationsdatei: pom.xml
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>log4j2demo</groupId> <artifactId>Log4j2-RollingFileAppender</artifactId> <version>2.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>log4j2demo.Log4j2Demo</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.9.1</version> </dependency> </dependencies> </project>
Erzeugen Sie im Log4j2-RollingFileAppender-Projektverzeichnis die Log4j2-Konfiguration: log4j2.properties
status = error name = PropertiesConfig filters = threshold filter.threshold.type = ThresholdFilter filter.threshold.level = debug appenders = rofi appender.rofi.type = RollingFile appender.rofi.name = RollingFile appender.rofi.fileName = logs/${sys:log4j.logfilename}.log appender.rofi.filePattern = logs/${sys:log4j.logfilename}-%i.log.gz appender.rofi.layout.type = PatternLayout appender.rofi.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n appender.rofi.policies.type = Policies appender.rofi.policies.size.type = SizeBasedTriggeringPolicy appender.rofi.policies.size.size = 10 KB appender.rofi.strategy.type = DefaultRolloverStrategy appender.rofi.strategy.max = 3 loggers = rofi logger.rofi.name = log4j2demo logger.rofi.level = info logger.rofi.additivity = false logger.rofi.appenderRef.rofi.ref = RollingFile
Beachten Sie das im Vergleich zu Log4j1 geänderte Format der Log4j-Konfigurationsdatei. Wie schon bei Log4j1 werden auch bei Log4j2 mit RollingFile nach konfigurierbaren Kriterien neue Logdateien gestartet. In diesem Beispiel wird eine neue Logdatei gestartet, wenn die Dateigröße ...policies.size.size von 10 KByte überschreitet. ...strategy.max 3 definiert, dass maximal drei vorherige Logdateien beibehalten werden. Ältere Logdateien werden gelöscht. Der Dateiname der Logdateien soll bei diesem Beispiel per Kommandozeilenparameter vorgegeben werden können. Deshalb finden Sie bei ...fileName und bei ...filePattern die Platzhalterausdrücke {sys:log4j.logfilename}. Die Dateiendung .gz bei ...filePattern gibt an, dass die alten Logdateien gezippt werden sollen. Für das Package log4j2demo ist als Logging-Level info konfiguriert.
Erzeugen Sie im src/main/java/log4j2demo-Verzeichnis die Main-Klasse: Log4j2Demo.java
package log4j2demo; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class Log4j2Demo { private static Logger logger = LogManager.getLogger( Log4j2Demo.class ); public static void main( String[] args ) { logger.debug( "Meine Debug-Meldung" ); logger.info( "Meine Info-Meldung" ); logger.warn( "Meine Warn-Meldung" ); logger.error( "Meine Error-Meldung" ); logger.fatal( "Meine Fatal-Meldung" ); } }
Beachten Sie die im Vergleich zu Log4j1 geänderten import-Anweisungen und den neuen LogManager.getLogger()-Aufruf. Sehen Sie sich die Javadoc an zu: Logger und LogManager.
Die Projektstruktur sieht etwas anders aus als beim vorherigen Beispiel, weil die log4j2.properties-Konfigurationsdatei diesmal nicht im Classpath liegen soll:
[\MeinWorkspace\Log4j2-RollingFileAppender] |- [src] | '- [main] | '- [java] | '- [log4j2demo] | '- Log4j2Demo.java |- log4j2.properties '- pom.xml
Da die log4j2.properties-Konfigurationsdatei diesmal nicht im Classpath liegt, wird der zusätzliche Aufrufparameter -Dlog4j.configurationFile=log4j2.properties benötigt, der den Pfad zur Log4j2-Konfigurationsdatei angibt. Außerdem muss über den zweiten Aufrufparameter -Dlog4j.logfilename=Log4j2-RollingFileAppender der gewünschte Dateiname der Logdatei angegeben werden, da in der Log4j2-Konfigurationsdatei hierfür der Platzhalter ${sys:log4j.logfilename} eingetragen ist. Mit Hilfe des maven-assembly-plugin wird wieder eine ausführbare Jar-Datei erzeugt, die alle benötigten Abhängigkeiten enthält. Führen Sie im Kommandozeilenfenster aus:
cd \MeinWorkspace\Log4j2-RollingFileAppender
mvn clean package
java -jar -Dlog4j.logfilename=Log4j2-RollingFileAppender -Dlog4j.configurationFile=log4j2.properties target\Log4j2-RollingFileAppender-2.0-SNAPSHOT-jar-with-dependencies.jar
dir logs
type logs\Log4j2-RollingFileAppender.log
Sie erhalten:
2017-01-01 01:01:01 INFO Log4j2Demo:13 - Meine Info-Meldung 2017-01-01 01:01:01 WARN Log4j2Demo:14 - Meine Warn-Meldung 2017-01-01 01:01:01 ERROR Log4j2Demo:15 - Meine Error-Meldung 2017-01-01 01:01:01 FATAL Log4j2Demo:16 - Meine Fatal-Meldung
Die Debug-Meldung wird nicht geloggt, weil in der log4j2.properties beim logger.rofi.level als Logging-Level "info" konfiguriert ist.