Search code examples
jsonspringspring-bootlogginglogback

How to configure different levels for different appenders but under same logger in logback


We are writing 2 appenders to write logs in different formats to 2 different files. But we want to enable these logs based on some configuration.

So if the user wants to enable both of the formats, then both of logs will be printed. But if the user wants to disable one, that log should not be created.

Below is my logger configuration :

<logger name="package.name" additivity="false" level="DEBUG">
     <appender-ref ref="STDOUT" />
     <appender-ref ref="json_logs"/>
     <appender-ref ref="text_logs"/>
</logger>

Now I want to put separate levels for this appender-ref. and value of these levels either should come from some property file which will be edited by user or user could simply update logback.xml file only.

I am not able to find a way to put separate levels for these appenders. And since I have to write logs from same classes, I cant create 2 separate loggers too.

Also, if the user does not want to see txt logs, then the corresponding log.txt file should not be created.


Solution

  • What you are after is the ThresholdFilter which can be fine tuned for each appender:

    http://logback.qos.ch/manual/filters.html#thresholdFilter

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        ...
    </appender>
    

    As for not writing the file at all based on some flag... you could write your own appender. Something like this ultra-simplistic example that could be refined in a number of ways but should hopefully get you started:

    public class ConditionalAppender<E> extends OutputStreamAppender<E> {
    
        private boolean masterSwitch;
    
        private String file;
    
        @Override
        public void start() {
    
            if(masterSwitch)
                setOutputStream(new FileOutputStream(file));
            else 
                setOutputStream(new NullOutputStream());
    
            super.start();
        }
    
        public void setMasterSwitch(final boolean enabled) {
    
            this.masterSwitch = enabled;
        }
    
        public void setFile(final String file) {
    
            this.file = file;
        }
    }
    
    <appender name="CONDITIONAL" class="mypackage.ConditionalAppender">
        <!-- switch this appender on or off -->
        <masterSwitch>true</masterSwitch>
        <!-- set the output file -->
        <file>/var/log/app/app.log</file>
        <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        ...
    </appender>
    
    

    Hope this helps.