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!
Która wersja logback jest to? – fge
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
Ah, świetny połów. To absolutnie powodowało problemy. Innym problemem było to, że poziom root debugowania powinien być śladowy! Dzięki wielkie! –