How to roll the log file on startup in logback

前端 未结 11 1676
梦谈多话
梦谈多话 2020-12-02 12:50

I would like to configure logback to do the following.

  • Log to a file
  • Roll the file when it reaches 50MB
  • Only keep 7 days worth of logs
  • <
相关标签:
11条回答
  • 2020-12-02 13:48

    Ceki's solution doesn't appear to work for me, but seems to be part way there at least.

    It blows up because it can't see the rolling policy when starting the TimeBasedFileNamingAndTriggeringPolicyBase. With some hackery I got it to do some logging, and with some more I got it to observe the trigger, but then it broke again because it couldn't resolve one of the filename properties... The package is a logback one so I could get to some of the internals, to replicate some of the logic in SizeAndTimeBasedFNATP#isTriggeringEvent and call computeCurrentPeriodsHighestCounterValue. I think something along those lines might work, just haven't found the magic combination yet. I really hope I'm doing something silly, because otherwise I think it will mean either opening up some of the details for subclassing, or putting this straight into logback as another rolling/triggering policy.

    logback.xml: tried various orderings of triggeringPolicy, TimeBasedFileNamingAndTriggeringPolicy inside and outside the rollingPolicy.

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${LOG_FILE_BASE}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/${LOG_FILE_BASE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <MaxHistory>7</MaxHistory>
    
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.RollOnStartupPolicy" />
        </rollingPolicy>
    
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    

    The trigger policy:

    package ch.qos.logback.core.rolling;
    public class RollOnStartupPolicy<E> extends SizeAndTimeBasedFNATP<E> {
    private final AtomicBoolean firstTime = new AtomicBoolean(true);
    
        @Override
        public boolean isTriggeringEvent(File activeFile, E event) {
            if (!firstTime.get()) { // fast path
                return false;
            }
    
            if (firstTime.getAndSet(false)) {
                return true;
            }
            return false;
        }
    }
    

    The exception:

    java.lang.NullPointerException
    at  at ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicyBase.start(TimeBasedFileNamingAndTriggeringPolicyBase.java:46)
    at  at ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.start(SizeAndTimeBasedFNATP.java:36)
    at  at ch.qos.logback.core.joran... [snip joran config]
    
    0 讨论(0)
  • 2020-12-02 13:50

    I got the following to work (combining ideas from previous answers). Note I was dealing with size-based files, not time-based, but I am guessing the same solution works.

    public class StartupSizeBasedTriggeringPolicy<E> extends ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy<E> {
    
    private final AtomicReference<Boolean> isFirstTime = new AtomicReference<Boolean>(true);
    
    @Override
    public boolean isTriggeringEvent(final File activeFile, final E event) {
    
        //this method appears to have side-effects so always call
        boolean result = super.isTriggeringEvent(activeFile, event);
    
        return isFirstTime.compareAndSet(true, false) || result;
    }
    

    }

    0 讨论(0)
  • 2020-12-02 13:50

    I finally figure it out. I can roll by size, time and start up. Here is solution:

    1st create you own class

    @NoAutoStart
    public class StartupSizeTimeBasedTriggeringPolicy<E> extends SizeAndTimeBasedFNATP<E> {
    
        private boolean started = false;
    
        @Override
        public boolean isTriggeringEvent( File activeFile, E event ) {
            if ( !started ) {
                nextCheck = 0L;
                return started = true;
            }
    
            return super.isTriggeringEvent( activeFile, event );
        };
    }
    

    2nd configure logback

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS_DIR}/${FILE_NAME}.log</file>
        <encoder>
            <pattern>%d [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS_DIR}/${FILE_NAME}.%d{yyyy-MM-dd}_%d{HHmmss,aux}.%i.log.zip</fileNamePattern>
            <maxHistory>30</maxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="my.StartupSizeTimeBasedTriggeringPolicy">
                <MaxFileSize>250MB</MaxFileSize> 
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    0 讨论(0)
  • 2020-12-02 13:51

    I found another solution for rolling the logFile once, when the application starts.

    I use logback's RollingFileAppender with logback's FixedWindowRollingPolicy and my own implementation of a TriggeringPolicy<E>.

    The FixedWindowRollingPolicy gets the fileNamePattern for the new logFile, where %1 is the new number of the file. The maxIndex stands for the maximum number of my "history". More information: FixedWindowRollingPolicy

    My implementations TriggeringPolicy returns true for the first time, when isTriggeringEvent(...) gets called. So the WindowRollingPolicy rolls over the logfiles, when the Policy gets called the first time, and afterwards it will not roll over again.

    The xml-configuration for the RollingFileAppender:

    <configuration>
        ...
        <appender name="FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logFile.log</file>
    
            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
                <fileNamePattern>logFile.%i.log</fileNamePattern>
                <minIndex>1</minIndex>
                <maxIndex>4</maxIndex>
            </rollingPolicy>
    
            <triggeringPolicy class="my.classpath.RollOncePerSessionTriggeringPolicy"/>
        </appender>
    ...
    </configuration>
    

    The TriggeringPolicy:

    package my.classpath;
    
    import ch.qos.logback.core.rolling.TriggeringPolicyBase;
    
    import java.io.File;
    
    public class RollOncePerSessionTriggeringPolicy<E> extends TriggeringPolicyBase<E> {
        private static boolean doRolling = true;
    
        @Override
        public boolean isTriggeringEvent(File activeFile, E event) {
            // roll the first time when the event gets called
            if (doRolling) {
                doRolling = false;
                return true;
            }
            return false;
        }
    }
    
    0 讨论(0)
  • 2020-12-02 13:51

    Overriding the isTriggeringEvent() method in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP should work nicely. Just return 'true' the first time isTriggeringEvent() method is called.

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