Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

logback: Two appenders, multiple loggers, different levels

I want to have two log files in my application (Spring Integration), debug.log and main.log. I want to run main.log at an INFO level and debug.log at a DEBUG level. This is doable with filters on the appenders. I want to log different levels to the appenders based on the source. In other words

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

So to summarise:

  1. Spring logger
    • main -> ERROR
    • debug -> DEBUG
  2. com.myapp logger
    • main -> INFO
    • debug -> DEBUG

Because of this I have to have the loggers running at DEBUG and a threshold filter on an appender isn't fine grained enough.

Update Added clarity to the question

like image 427
John Oxley Avatar asked May 24 '12 08:05

John Oxley


People also ask

What are the log levels in Logback?

Loggers are the third main component of Logback, which developers can use to log messages at a certain level. The library defines 5 log levels: TRACE, DEBUG, INFO, WARN, ERROR; each of these has a corresponding logging method: trace(), debug(), info(), warn(), error().

What is RollingFileAppender in Logback?

RollingFileAppender extends FileAppender with the capability to rollover log files. For example, RollingFileAppender can log to a file named log. txt file and, once a certain condition is met, change its logging target to another file.

What is additivity false in Logback?

Add additivity="false" to the "AUDIT_LOGGER" , as described in one of the answers above, to not inherit the appenders from the root logger. Remove the appender element from the "AUDIT_LOGGER" . This will cause the "AUDIT_LOGGER" to inherit the appenders from the root logger.


2 Answers

Create a ThresholdLoggerFilter class which can be put on an appender like:

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

The following code works

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();         }     } } 
like image 164
John Oxley Avatar answered Oct 13 '22 21:10

John Oxley


You can also do this somewhat more simply if you are willing to inherit from the root logger, e.g. here we add an extra logger for errors, that logs to stderr. It's only enabled for particular loggers.

<configuration>     <appender name="CONSOLE-stdout" class="ch.qos.logback.core.ConsoleAppender">         <target>System.out</target> <!-- the default -->         <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> 
like image 26
artbristol Avatar answered Oct 13 '22 21:10

artbristol