2012-05-24 5 views
34

Chcę mieć dwa pliki dziennika w mojej aplikacji (Spring Integration), debug.log i main.log. Chcę uruchomić plik main.log na poziomie INFO i debug.log na poziomie DEBUG. Jest to możliwe dzięki filtrom na aplikantach. Chcę logować różne poziomy do aplikantów na podstawie źródła. Innymi słowylogback: Dwóch aplikatorów, wiele rejestratorów, różne poziomy

<logger name="org.springframework" level="ERROR"> 
    <appender-ref ref="main" /> 
</logger> 
<logger name="org.springframework" level="DEBUG"> 
    <appender-ref ref="debug" /> 
</logger> 
<logger name="com.myapp" level="INFO"> 
    <appender-ref ref="main" /> 
</logger> 
<logger name="com.myapp" level="DEBUG"> 
    <appender-ref ref="debug" /> 
</logger> 

Więc Podsumowując:

  1. Wiosna rejestrator
    • Głównym -> ERROR
    • debug -> DEBUG
  2. com.myapp rejestrator
    • główny - > INFO
    • debug -> DEBUG

tego muszę mieć rejestratory uruchomione na debugowania i filtr próg On o appender Ponieważ nie jest w porządku, tyle drobnoziarnisty.

Aktualizacja Dodano jasność na pytanie

Odpowiedz

39

Utwórz klasę ThresholdLoggerFilter które można umieścić na appender jak:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
     <level>INFO</level> 
    </filter> 
    <filter class="com.myapp.ThresholdLoggerFilter"> 
     <logger>org.springframework</logger> 
     <level>ERROR</level> 
    </filter> 
    </appender> 

Poniższy kod działa

package com.myapp; 

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.filter.Filter; 
import ch.qos.logback.core.spi.FilterReply; 

public class ThresholdLoggerFilter extends Filter<ILoggingEvent> { 
    private Level level; 
    private String logger; 

    @Override 
    public FilterReply decide(ILoggingEvent event) { 
     if (!isStarted()) { 
      return FilterReply.NEUTRAL; 
     } 

     if (!event.getLoggerName().startsWith(logger)) 
      return FilterReply.NEUTRAL; 

     if (event.getLevel().isGreaterOrEqual(level)) { 
      return FilterReply.NEUTRAL; 
     } else { 
      return FilterReply.DENY; 
     } 
    } 

    public void setLevel(Level level) { 
     this.level = level; 
    } 

    public void setLogger(String logger) { 
     this.logger = logger; 
    } 

    public void start() { 
     if (this.level != null && this.logger != null) { 
      super.start(); 
     } 
    } 
} 
+1

Prosta i czysta odpowiedź! Ten przykład był idealny do moich potrzeb !!! – araknoid

+4

Nie musisz się wdrażać, użyj pliku ch.qos.logback.classic.filter.ThresholdFilter –

+2

ThresholdFilter filtruje tylko próg. Chcę filtrować zarówno dla progu loggera ORAZ progu –

15

można również zrób to nieco prościej, jeśli chcesz dziedziczyć z głównego rejestru, np tutaj dodajemy dodatkowy rejestrator błędów, który loguje się na stderr. Jest włączony tylko dla określonych rejestratorów.

<configuration> 
    <appender name="CONSOLE-stdout" class="ch.qos.logback.core.ConsoleAppender"> 
     <target>System.out</target> 
     <encoder> 
      <pattern>%d %-5level [%thread] %logger{0}: %msg%n</pattern> 
     </encoder> 
    </appender> 
    <appender name="CONSOLE-stderr" class="ch.qos.logback.core.ConsoleAppender"> 
     <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
      <level>ERROR</level> 
     </filter> 

     <target>System.err</target> 
     <encoder> 
      <pattern>%d %-5level [%thread] %logger{0}: %msg%n</pattern> 
     </encoder> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="CONSOLE-stdout" /> 
    </root> 

     <!-- We want error logging from this logger to go to an extra appender 
      It still inherits CONSOLE-stdout from the root logger --> 
    <logger name="org.springframework" level="INFO"> 
     <appender-ref ref="CONSOLE-stderr" /> 
    </logger> 
</configuration> 
+0

Dzięki @artbristol, ale to nie daje ziarnistości kontroli, jakiej pragnę. Zaktualizowałem pytanie, więc pokaż, dlaczego. –

0

Korzystanie z wielu rejestratorów różnych komunikatów będzie tak:

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.Logger; 

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.spi.ILoggingEvent; 
import ch.qos.logback.core.FileAppender; 

public class ConfigureLogBack 
{ 
    public static void programmaticConfiguration() 
    { 
     Logger camel = getLogger("MyRoute", C:\\Users\\amrut.malaji\\Desktop\\Oracle\\logback\\camel-Log.txt"); 
     Logger services = getLogger("webservices", "C:\\Users\\amrut.malaji\\Desktop\\Oracle\\logback\\services-log.txt"); 
    } 

    private static Logger getLogger(String string, String file) { 
     LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
    PatternLayoutEncoder ple = new PatternLayoutEncoder(); 

    ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n"); 
    ple.setContext(lc); 
    ple.start(); 
    FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>(); 
    fileAppender.setFile(file); 
    fileAppender.setEncoder(ple); 
    fileAppender.setContext(lc); 
    fileAppender.start(); 

    Logger logger = (Logger) LoggerFactory.getLogger(string); 
    logger.addAppender(fileAppender); 
    logger.setLevel(Level.INFO); 
    logger.setAdditive(false); /* set to true if root should log too */ 

    return logger; 
} 
1

Wystarczy znaleźć praktyczne rozwiązanie z wykorzystaniem elementów logback tylko, że działa całkiem dobrze, przede wszystkim trzeba mieć dwie appenders, jeden z domyślne, a drugi z filtrem (w moim przykładzie używam konsoli):

<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="WARN_FILTER_STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
     <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
      <level>WARN</level> 
     </filter> 
     <encoder> 
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <logger name="org.apache.spark" level="INFO" additivity="false"> 
     <appender-ref ref="SPARK" /><!-- this line is not necessary, just here to ilustrate the need for the filter --> 
     <appender-ref ref="WARN_FILTER_STDOUT" /> 
    </logger> 

    <root level="info"> 
     <appender-ref ref="STDOUT" /> 
    </root> 
1

Dodanie dodatkowego rozwiązania, które jest prostsze niż to, co już ją e

Żadne z tych rozwiązań nie sprawdziło się, ponieważ nie używam frameworków takich jak Spark czy Spring. Zrobiłem więc coś prostszego, co wydaje się dobrze funkcjonować. Chociaż to rozwiązanie może nie działać w OP, być może może być przydatne dla kogoś, kto chce czegoś nie tak nieporęcznego.

<property name="pattern" value="%d{yyyy.MMM.dd HH:mm:ss.SSS} [ProgramName] %level - %msg%n" /> 

<appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
    <file>/path/to/your/program.log</file> 
    <append>true</append> 
    <encoder> 
     <pattern>${pattern}</pattern> 
    </encoder> 
</appender> 

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <target>System.out</target> 
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
     <level>INFO</level> 
    </filter> 
    <encoder> 
     <pattern>${pattern}</pattern> 
    </encoder> 
</appender> 

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

Przy tej konfiguracji, jestem w stanie utrzymać konsolę raczej czyste, podczas wyprowadzania oświadczenia debugowania w pliku dziennika.