2013-05-30 6 views
11

Potrzebuję dynamicznie tworzyć rejestratory logback i różne bity dla klas, które ładują się i ładują dynamicznie. Mam zmienną liczbę tych klas, chociaż będzie to mniej niż 150 wszystkie powiedział. Wydajność jest poważnym problemem, a jest to wysoce gwintowane i bardzo współbieżne środowisko, więc pomysł korzystania z MDC nie będzie latał z powodu potencjalnie tysięcy połączeń na sekundę, gdy coś pójdzie nie tak. Nie chcę też bezpośrednio przekazywać rejestratorów do klas, chciałbym, żeby po prostu wyciągnęli je z powietrza, używając metody getLogger, co jest typowe.Dynamicznie tworzyć rejestratory dzienników i dodatki

Każda klasa musi logować wszystkie komunikaty o błędach do własnego pliku błędów i wszystkich swoich komunikatów śledzenia do własnego pliku śledzenia. Oba pliki muszą być odtwarzane co noc. Dodatkowo wszystko, co zaloguje się w systemie, musi znaleźć się w głównym dzienniku systemowym.

Utworzyłem następujący fragment kodu, aby wypróbować ten pomysł. Wygląda to tak, jakby działało, ale wyniki nie są takie, jakich oczekiwałbym. Oto program testowy, który może być uruchamiany bezpośrednio:

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


    } 

} 

Oto plik logback.xml:

<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> 

Jeśli uruchomić ten kod, to właściwie wszystko logowania do głównego pliku dziennika . I utworzy 2 dzienniki śladu i 2 błędy zgodnie z oczekiwaniami. Ale żaden z komunikatów śledzenia nie znajdzie się w plikach dziennika śledzenia, a oba komunikaty o błędach znajdą się w pliku błędu klasy 2. Zachowuje się tak, jakby wszyscy 4 aplikanci byli dodawani do tego samego rejestratora, a tylko dodawany ostatni dodający działa. Chciałbym zrozumieć, co robię tutaj. Dzięki!

+0

Która wersja logback jest to? – fge

+2

Wygląda całkiem nieźle. Jedyny problem, jaki mogłem zauważyć po pobieżnym spojrzeniu, to to, że nie powinno się udostępniać koderów. Musisz utworzyć nowy dla każdego pliku/RollingFileAppender. – Ceki

+0

Ah, świetny połów. To absolutnie powodowało problemy. Innym problemem było to, że poziom root debugowania powinien być śladowy! Dzięki wielkie! –

Odpowiedz

2

Wystąpił szereg problemów z powyższym kodem. Najpierw jest to, co Ceki zawołał: nie można udostępniać koderów. Utworzenie dwóch enkoderów w pętli zmieniło zachowanie we właściwym kierunku. Drugi problem był w pliku XML, poziom root powinien być śledzony, a nie debugowany. Było to oczywiste po zmianie enkodera.