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

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


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>


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


Solution based on configuration only, with a ThresoldFilter and LevelFilters to keep things really simple to understand :

<configuration>    <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">        <target>System.err</target>        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">          <level>WARN</level>        </filter>        <encoder>            <pattern>%date %level [%thread] %logger %msg%n</pattern>        </encoder>    </appender>    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">        <target>System.out</target>        <filter class="ch.qos.logback.classic.filter.LevelFilter">          <level>DEBUG</level>          <onMatch>ACCEPT</onMatch>        </filter>        <filter class="ch.qos.logback.classic.filter.LevelFilter">          <level>INFO</level>          <onMatch>ACCEPT</onMatch>        </filter>        <filter class="ch.qos.logback.classic.filter.LevelFilter">          <level>TRACE</level>          <onMatch>ACCEPT</onMatch>        </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>%date %level [%thread] %logger %msg%n</pattern>        </encoder>    </appender>    <root level="INFO">        <appender-ref ref="STDOUT" />        <appender-ref ref="STDERR" />    </root></configuration>