2013-05-30 10 views
11

Ich muss Log-Logger und andere Bits dynamisch für Klassen erstellen, die dynamisch geladen und neu geladen werden. Ich habe eine variable Anzahl dieser Klassen, obwohl es insgesamt weniger als 150 sein wird. Leistung ist ein großes Anliegen und dies ist eine hochgradige Threaded und extrem gleichzeitige Umgebung, so dass die Idee der Verwendung von MDC wird nicht aufgrund von möglicherweise Tausende von Anrufen pro Sekunde, wenn die Dinge schief gehen. Ich möchte auch nicht direkt die Logger in die Klassen bringen, ich möchte, dass sie sie einfach mit getLogger aus der Luft ziehen, wie es typisch ist.Log-Logger und Appender dynamisch erstellen

Jede Klasse muss alle Fehlermeldungen in ihre eigene Fehlerdatei und alle Trace-Nachrichten in ihre eigene Trace-Datei eintragen. Beide Dateien müssen sich jeden Abend rollen. Darüber hinaus muss alles, was im System angemeldet ist, auch in den Hauptsystemprotokollen enden.

Ich habe das folgende Code-Snippet erstellt, um diese Idee auszuprobieren. Es scheint, als würde es funktionieren, aber die Ergebnisse sind nicht das, was ich erwarten würde. Hier haben wir das Testprogramm, das direkt ausgeführt werden können:

package logbacktesting; 

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.LoggerContext; 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; 
import ch.qos.logback.classic.filter.LevelFilter; 
import ch.qos.logback.core.rolling.RollingFileAppender; 
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; 
import ch.qos.logback.core.spi.FilterReply; 
import ch.qos.logback.core.util.StatusPrinter; 
import org.slf4j.LoggerFactory; 

public class Main { 

    public static void main(String[] args) { 

     Logger templateLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.myapp"); 
     LoggerContext loggerContext = templateLogger.getLoggerContext(); 

     String[] nameList = new String[] {"test1.class", "test2.class"}; 

     // Set up the pattern 
     PatternLayoutEncoder encoder = new PatternLayoutEncoder(); 
     encoder.setContext(loggerContext); 
     encoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"); 
     encoder.start(); 

     // Spin over the names to create all the needed objects 
     for(int i = 0; i < nameList.length; i++) { 

      String name = nameList[i]; 

      // Set up the roll over policies and the name when it rolls over 
      TimeBasedRollingPolicy tracePolicy = new TimeBasedRollingPolicy(); 
      tracePolicy.setContext(loggerContext); 
      tracePolicy.setFileNamePattern(name + "-Trace-%d{yyyy-MM-dd}.log"); 
      tracePolicy.setMaxHistory(30); 

      TimeBasedRollingPolicy errorPolicy = new TimeBasedRollingPolicy(); 
      errorPolicy.setContext(loggerContext); 
      errorPolicy.setFileNamePattern(name + "-Error-logFile.%d{yyyy-MM-dd}.log"); 
      errorPolicy.setMaxHistory(30); 

      // Set up the filters to ensure things get split as expected 
      LevelFilter traceFilter = new LevelFilter(); 
      traceFilter.setContext(loggerContext); 
      traceFilter.setLevel(Level.TRACE); 
      traceFilter.setOnMatch(FilterReply.ACCEPT); 
      traceFilter.setOnMismatch(FilterReply.DENY); 

      LevelFilter errorFilter = new LevelFilter(); 
      errorFilter.setContext(loggerContext); 
      errorFilter.setLevel(Level.ERROR); 
      errorFilter.setOnMatch(FilterReply.ACCEPT); 
      errorFilter.setOnMismatch(FilterReply.DENY); 

      // Set up the trace and error appenders 
      RollingFileAppender rollingFileAppenderTrace = new RollingFileAppender(); 
      rollingFileAppenderTrace.setContext(loggerContext); 
      rollingFileAppenderTrace.setName(name + "-Trace"); 
      rollingFileAppenderTrace.setFile(name + "-Trace.log"); 
      rollingFileAppenderTrace.setEncoder(encoder); 
      rollingFileAppenderTrace.setRollingPolicy(tracePolicy); 
      rollingFileAppenderTrace.addFilter(traceFilter); 
      tracePolicy.setParent(rollingFileAppenderTrace); 

      RollingFileAppender rollingFileAppenderError = new RollingFileAppender(); 
      rollingFileAppenderError.setContext(loggerContext); 
      rollingFileAppenderError.setName(name + "-Error"); 
      rollingFileAppenderError.setFile(name + "-Error.log"); 
      rollingFileAppenderError.setEncoder(encoder); 
      rollingFileAppenderError.setRollingPolicy(errorPolicy); 
      rollingFileAppenderError.addFilter(errorFilter); 
      errorPolicy.setParent(rollingFileAppenderError); 

      // Start everything 
      tracePolicy.start(); 
      errorPolicy.start(); 
      traceFilter.start(); 
      errorFilter.start(); 
      rollingFileAppenderTrace.start(); 
      rollingFileAppenderError.start(); 

      // attach the rolling file appenders to the logger 
      Logger logger = (ch.qos.logback.classic.Logger) loggerContext.getLogger(name); 
      logger.addAppender(rollingFileAppenderTrace); 
      logger.addAppender(rollingFileAppenderError); 

     } 

     StatusPrinter.print(loggerContext); 

     // Test it to see what happens 
     for(int i = 0; i < nameList.length; i++) { 

      String name = nameList[i]; 

      Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(name); 
      logger.error("error message"); 
      logger.warn("warn message"); 
      logger.info("info message"); 
      logger.debug("debug message"); 
      logger.trace("trace message"); 
     } 

     Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.myapp"); 
     logger.error("generic error message "); 


    } 

} 

Hier wird die logback.xml Datei:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
     <encoder> 
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>logFile.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> 
      <maxHistory>30</maxHistory> 
     </rollingPolicy> 
     <encoder> 
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <root level="debug"> 
     <appender-ref ref="STDOUT" /> 
     <appender-ref ref="FILE" /> 
    </root> 

</configuration> 

Wenn Sie diesen Code ausführen, wird es richtig alles in die Haupt-Protokolldatei protokollieren . Und es wird 2 Trace und 2 Fehlerprotokolle wie erwartet erstellen. Keine der Trace-Nachrichten wird jedoch in den Trace-Protokolldateien gespeichert, und beide Fehlermeldungen landen in der Fehlerdatei der Klasse 2. Es verhält sich so, als ob alle 4 Appender zum selben Logger hinzugefügt werden und nur der letzte Appender, der hinzugefügt wird, funktioniert. Ich würde gerne verstehen, was ich hier mache. Vielen Dank!

+0

Welche Version Logbuch ist das? – fge

+2

Sieht ziemlich gut aus. Das einzige Problem, das ich aus einem flüchtigen Blick erkennen konnte, ist, dass Sie keine Encoder freigeben sollten. Sie müssen für jede Datei/RollingFileAppender eine neue Datei erstellen. – Ceki

+0

Ah, toller Fang. Das hat absolut Probleme verursacht. Das andere Problem war, dass die root-Ebene von debug Trace sein sollte! Vielen Dank! –

Antwort

2

Es gab mehrere Probleme mit dem obigen Code. Erstens hat Ceki gerufen: Sie können keine Encoder teilen. Durch das Erstellen von zwei Encodern in der Schleife wurde das Verhalten in der richtigen Richtung geändert. Das zweite Problem war in der XML-Datei, Root-Ebene sollte Trace sein, nicht debuggen. Es war offensichtlich nach dem Codiererwechsel.