How can I configure Logback to log different levels for a logger to different destinations?

前端 未结 12 1725
挽巷
挽巷 2020-11-28 18:37

How can I configure Logback to log different levels for a logger to different destinations?

For example, given the following Logback configuration, will Logback reco

相关标签:
12条回答
  • 2020-11-28 18:56

    No programming needed. configuration make your life easy.

    Below is the configuration which logs different level of logs to different files

    <property name="DEV_HOME" value="./logs" />
    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n
            </Pattern>
        </layout>
    </appender>
    
    <appender name="FILE-ERROR"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${DEV_HOME}/app-error.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n
            </Pattern>
        </encoder>
    
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${DEV_HOME}/archived/app-error.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <!--output messages of exact level only -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="FILE-INFO"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${DEV_HOME}/app-info.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n
            </Pattern>
        </encoder>
    
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${DEV_HOME}/archived/app-info.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    
    
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <!--output messages of exact level only -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    
    <appender name="FILE-DEBUG"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${DEV_HOME}/app-debug.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </Pattern>
        </encoder>
    
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${DEV_HOME}/archived/app-debug.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <!--output messages of exact level only -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <appender name="FILE-ALL"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${DEV_HOME}/app.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </Pattern>
        </encoder>
    
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${DEV_HOME}/archived/app.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <logger name="com.abc.xyz" level="DEBUG" additivity="true">
        <appender-ref ref="FILE-DEBUG" />
        <appender-ref ref="FILE-INFO" />
        <appender-ref ref="FILE-ERROR" />
        <appender-ref ref="FILE-ALL" />
    </logger>
    
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
    

    0 讨论(0)
  • 2020-11-28 19:00

    I believe this would be the simplest solution:

    <configuration>
        <contextName>selenium-plugin</contextName>
        <!-- Logging configuration -->  
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <Target>System.out</Target>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <encoder>
                <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%level] %msg%n</pattern>
            </encoder>
        </appender>
        <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
                <Target>System.err</Target>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <encoder> 
                <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%level] [%thread] %logger{10} [%file:%line] %msg%n</pattern> 
            </encoder> 
        </appender>
        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="STDERR" />
        </root>
    </configuration>
    
    0 讨论(0)
  • 2020-11-28 19:03

    Update: For an all configuration based approach using Groovy see Dean Hiller's answer.

    --

    You can do some interesting things with Logback filters. The below configuration will only print warn and error messages to stderr, and everything else to stdout.

    logback.xml

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
      <target>System.out</target>
      <filter class="com.foo.StdOutFilter" />
       ...
    </appender>
    
    <appender name="stderr" class="ch.qos.logback.core.ConsoleAppender">
      <target>System.err</target>
      <filter class="com.foo.ErrOutFilter" />
       ...
    </appender>
    
    <logger name="mylogger" level="debug">
        <appender-ref ref="stdout" />
        <appender-ref ref="stderr" />
    </logger>
    

    com.foo.StdOutFilter

    public class StdOutFilter extends ch.qos.logback.core.filter.AbstractMatcherFilter
    {
    
        @Override
        public FilterReply decide(Object event)
        {
            if (!isStarted())
            {
                return FilterReply.NEUTRAL;
            }
    
            LoggingEvent loggingEvent = (LoggingEvent) event;
    
            List<Level> eventsToKeep = Arrays.asList(Level.TRACE, Level.DEBUG, Level.INFO);
            if (eventsToKeep.contains(loggingEvent.getLevel()))
            {
                return FilterReply.NEUTRAL;
            }
            else
            {
                return FilterReply.DENY;
            }
        }
    
    }
    

    com.foo.ErrOutFilter

    public class ErrOutFilter extends ch.qos.logback.core.filter.AbstractMatcherFilter
    {
    
        @Override
        public FilterReply decide(Object event)
        {
            if (!isStarted())
            {
                return FilterReply.NEUTRAL;
            }
    
            LoggingEvent loggingEvent = (LoggingEvent) event;
    
            List<Level> eventsToKeep = Arrays.asList(Level.WARN, Level.ERROR);
            if (eventsToKeep.contains(loggingEvent.getLevel()))
            {
                return FilterReply.NEUTRAL;
            }
            else
            {
                return FilterReply.DENY;
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-28 19:03

    I take no credit for this answer, as it's merely a combination of the best two answers above: that of X. Wo Satuk and that of Sébastien Helbert: ThresholdFilter is lovely but you can't configure it to have an upper level as well as a lower level*, but combining it with two LevelFilters set to "DENY" WARN and ERROR works a treat.

    Very important: do not forget the <target>System.err</target> tag in the STDERR appender: my omission of it had me frustrated for a few minutes.

    <configuration>
        <timestamp key="byDay" datePattern="yyyyMMdd'T'HHmmss" />
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>INFO</level>
            </filter>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>WARN</level>
                <onMatch>DENY</onMatch>
            </filter>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>DENY</onMatch>
            </filter>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\)
                    - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>WARN</level>
            </filter>
            <target>System.err</target>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\)
                    - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <root level="debug">
            <appender-ref ref="STDOUT" />
            <appender-ref ref="STDERR" />
        </root>
    </configuration>
    

    * it does however have a method decide in the API but I haven't a clue how you'd use it in this context.

    0 讨论(0)
  • 2020-11-28 19:06
    <configuration scan="true" scanPeriod="60 seconds">
     <appender name="A1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${storm.log.dir}/${logfile.name}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
          <fileNamePattern>${storm.log.dir}/${logfile.name}.%i</fileNamePattern>
          <minIndex>1</minIndex>
          <maxIndex>9</maxIndex>
        </rollingPolicy>
    
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
          <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
    
        <encoder>
          <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ} %c{1} [%p] %m%n</pattern>
        </encoder>
     </appender>
    
     <appender name="ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${storm.log.dir}/access.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
          <fileNamePattern>${storm.log.dir}/access.log.%i</fileNamePattern>
          <minIndex>1</minIndex>
          <maxIndex>9</maxIndex>
        </rollingPolicy>
    
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
          <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
    
        <encoder>
          <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ} %c{1} [%p] %m%n</pattern>
        </encoder>
      </appender>
    
      <appender name="METRICS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${storm.log.dir}/metrics.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
          <fileNamePattern>${storm.log.dir}/logs/metrics.log.%i</fileNamePattern>
          <minIndex>1</minIndex>
          <maxIndex>9</maxIndex>
        </rollingPolicy>
    
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
          <maxFileSize>2MB</maxFileSize>
        </triggeringPolicy>
    
        <encoder>
          <pattern>%d %-8r %m%n</pattern>
        </encoder>
      </appender>
    
      <root level="INFO">
        <appender-ref ref="A1"/>
      </root>
    
      <logger name="backtype.storm.security.auth.authorizer" additivity="false">
        <level value="INFO" />
        <appender-ref ref="ACCESS" />
      </logger>
    
      <logger name="backtype.storm.metric.LoggingMetricsConsumer" additivity="false" >
        <level value="INFO"/>
        <appender-ref ref="METRICS"/>
      </logger>
    
    </configuration>
    
    So here is the logback file in which I am not printing backtype.storm.metric.LoggingMetricsConsumer info level if i say additivity = "true" then for for all classes in backtype.* this rule will be applied
    
    0 讨论(0)
  • 2020-11-28 19:11

    Try this. You can just use built-in ThresholdFilter and LevelFilter. No need to create your own filters programmically. In this example WARN and ERROR levels are logged to System.err and rest to System.out:

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!-- deny ERROR level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
        </filter>
        <!-- deny WARN level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>DENY</onMatch>
        </filter>
        <target>System.out</target>
        <immediateFlush>true</immediateFlush>
        <encoder>
            <charset>utf-8</charset>
            <pattern>${msg_pattern}</pattern>
        </encoder>
    </appender>
    
    <appender name="stderr" class="ch.qos.logback.core.ConsoleAppender">
        <!-- deny all events with a level below WARN, that is INFO, DEBUG and TRACE -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
        <target>System.err</target>
        <immediateFlush>true</immediateFlush>
        <encoder>
            <charset>utf-8</charset>
            <pattern>${msg_pattern}</pattern>
        </encoder>
    </appender>   
    
    <root level="WARN">
        <appender-ref ref="stderr"/>
    </root>
    
    <root level="TRACE">
        <appender-ref ref="stdout"/>
    </root>
    

    0 讨论(0)
提交回复
热议问题