2016-07-26 14 views
1

Heute habe ich ein Problem, die log4j2-Konfiguration richtig zu rekonfigurieren. Um das Problem zu erklären, habe ich eine Beispielanwendung erstellt, die fast unserem Produktivcode entspricht. Das Beispielprojekt Struktur ist in der folgenden Abbildung dargestellt:Wie ersetzt man die Log4j2-Standardkonfiguration programmgesteuert?

enter image description here

Für Entwickler Zweck wir die Hauptanwendung mit einer Wrapper-Klasse starten wollen einige Parameter konfigurieren wie Konfiguration oder Systemeigenschaften Anmeldung, die platziert werden soll nicht in der produktive Code Daher sollte die produktive log4j2-Konfiguration durch die Entwicklerlogik ersetzt werden, um die Protokollebene spezifischer zu machen und eine Anhängung der Protokolleinträge zu vermeiden. Im Folgenden ist der Code für die produktiven Hauptklasse:

package logging.log4j2; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 

public class MainApp { 

    private final Log LOG = LogFactory.getLog(MainApp.class); 
    private final String[] commandLineArgs; 

    public static void main(String[] args) { 
     MainApp app = new MainApp(args); 
     app.start(); 
    } 

    protected MainApp(String[] args) { 
     commandLineArgs = args; 
    } 

    public void start() { 
     LOG.info("Starting MainApp application ..."); 

     // ... do main application stuff here 
     LOG.debug("This is only for DEBUG mode."); 
    } 
} 

Jetzt ist der Code für die Entwickler-Wrapper Hauptklasse:

package logging.log4j2; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 

import java.net.URL; 

public class DevWrapperMainApp extends MainApp { 

    private static final Log LOG = LogFactory.getLog(DevWrapperMainApp.class); 
    public static final String PROP_LOG4J_CONFIGURATION_FILE = "log4j.configurationFile"; 

    protected DevWrapperMainApp(String[] args) { 
     super(args); 
    } 

    public static void main(String[] args) { 
     preconfigureDevMode(); 
     DevWrapperMainApp devApp = new DevWrapperMainApp(args); 
     devApp.start(); 
    } 

    private static void preconfigureDevMode() { 
     LOG.debug("Preconfigure application for deveoper mode ..."); 
     String log4j2ConfigFilePath = System.getProperty(PROP_LOG4J_CONFIGURATION_FILE); 
     if(log4j2ConfigFilePath == null || log4j2ConfigFilePath.isEmpty()) { 
      URL configResource = DevWrapperMainApp.class.getResource("/dev-log4j2.xml"); 
      if(configResource != null) { 
       System.setProperty(PROP_LOG4J_CONFIGURATION_FILE, configResource.toExternalForm()); 
      } else { 
       LOG.error("Set log4j2 configuration file property failed. Resource file could not be detected correctly."); 
      } 
     } 
    } 
} 

Die Protokollierung der produktiven Anwendung durch die log4j2.xml konfiguriert ist:

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration name="productiveConfig" status="WARN" monitorInterval="5"> 
    <properties> 
     <property name="log.pattern.layout">%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property> 
    </properties> 

    <Appenders> 
     <Console name="Console" target="SYSTEM_OUT"> 
      <PatternLayout pattern="${sys:log.pattern.layout}"/> 
     </Console> 
    </Appenders> 
    <Loggers> 
     <Root level="INFO"> 
      <AppenderRef ref="Console"/> 
     </Root> 
    </Loggers> 
</Configuration> 

Für die Beispielanwendung gibt es keine Datei appender aber die Protokollstufe und der Name der Konfiguration ist differe nt aus der folgenden dev-log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration name="developerConfig" status="DEBUG" monitorInterval="5"> 
    <properties> 
     <property name="log.pattern.layout">DEV-MODE: %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property> 
    </properties> 

    <Appenders> 
     <Console name="Console" target="SYSTEM_OUT"> 
      <PatternLayout pattern="${sys:log.pattern.layout}"/> 
     </Console> 
    </Appenders> 
    <Loggers> 
     <Root level="DEBUG"> 
      <AppenderRef ref="Console"/> 
     </Root> 
    </Loggers> 
</Configuration> 

Indem der DevWrapperMainApp Klasse I die folgende Ausgabe:

"C:\Program Files\Java\jdk1.8.0_66\bin\java" ... 
11:40:14.553 [main] INFO logging.log4j2.MainApp - Starting MainApp application ... 

Process finished with exit code 0 

Neben dem INFO Protokollierung erwartete ich die Ausgabe der DEBUG Protokollierung auch. Daher scheint die Protokollkonfiguration nicht neu konfiguriert zu sein, indem die Systemeigenschaft in diesem Moment überschrieben wird. Vielleicht ist es zu spät und log4j2 ist bereits durch die produktive Konfigurationsdatei konfiguriert? Wie kann ich die gesamte Konfiguration zum Zeitpunkt des Starts meiner Anwendung ändern? Die Dokumentation lautet:

Sollte jedoch eine Protokollierung versucht werden, bevor Configurator.initialize() aufgerufen wird, wird die Standardkonfiguration für diese Protokollereignisse verwendet. (Teil: Reconfigure Log4j Using ConfigurationBuilder with the Configurator

Vielleicht hat jemand einen Tipp für mich in der richtigen Richtung zu gehen ich weiß auch die Möglichkeit, einen log4j2-test.xml für die Entwicklung Zweck zu schaffen, sondern einen Mangel dies zu vermeiden und auch die Systemeigenschaft setzen. Der Code sollte bekannt sein, wo die Konfigurationsdatei finden.

Vielen Dank im Voraus.

Hardie

Antwort

0

Log4j 2 unterstützt zum Testen eine separate Konfiguration. Sie ca n haben zwei Konfigurationsdateien, eine namens log4j2.xml für die Produktion und eine namens log4j2-test.xml zum Testen. Wenn beide vorhanden sind, verwendet Log4j 2 die Testkonfiguration. In der Produktion wird die Testkonfiguration einfach nicht bereitgestellt. Genaue Informationen finden Sie in der Dokumentation order in which Log4j 2 initializes.