如何在启动时在logback中滚动日志文件

我想configurationlogback来执行以下操作。

  • login到文件
  • 当文件达到50MB时滚动文件
  • 只保留7天的价值的日志
  • 在启动时总是生成一个新的文件(做一个滚动)

除了最后一个项目,启动卷,我已经工作了。 有谁知道如何做到这一点? 这是configuration…

<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> </layout> <File>server.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>server.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- keep 7 days' worth of history --> <MaxHistory>7</MaxHistory> <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <MaxFileSize>50MB</MaxFileSize> </TimeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> 

没有其他的build议适合我的情况。 我不想使用基于大小和时间的解决scheme,因为它需要configurationMaxFileSize,而且我们正在使用严格的基于时间的策略。 以下是我如何使用TimeBasedRollingPolicy在启动时滚动文件:

 @NoAutoStart public class StartupTimeBasedTriggeringPolicy<E> extends DefaultTimeBasedFileNamingAndTriggeringPolicy<E> { @Override public void start() { super.start(); nextCheck = 0L; isTriggeringEvent(null, null); try { tbrp.rollover(); } catch (RolloverFailure e) { //Do nothing } } } 

诀窍是将nextCheck时间设置为0L,以便isTriggeringEvent()将认为是滚动日志文件的时间。 它将执行必要的代码来计算文件名,以及方便地重置nextCheck时间值。 随后调用rollover()会导致日志文件被滚动。 由于这只在启动时发生,因此它是比在isTriggerEvent()内执行比较的更优化的解决scheme。 无论如何比较,在每条日志消息上执行时都会稍微降低性能。 这也会强制翻转在启动时立即发生,而不是等待第一个日志事件。

在所有其他初始化完成之前,@NoAutoStart注释对于防止Joran执行start()方法非常重要。 否则,你会得到一个NullPointerException。

这是configuration:

  <!-- Daily rollover appender that also appends timestamp and rolls over on startup --> <appender name="startupDailyRolloverAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d{yyyyMMdd}_%d{HHmmss,aux}</fileNamePattern> <TimeBasedFileNamingAndTriggeringPolicy class="my.package.StartupTimeBasedTriggeringPolicy" /> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> 

希望这可以帮助!

它适用于我,使用以下类作为timeBasedFileNamingAndTriggeringPolicy:

 import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import ch.qos.logback.core.joran.spi.NoAutoStart; import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP; @NoAutoStart public class Trigger<E> extends SizeAndTimeBasedFNATP<E> { private final AtomicBoolean trigger = new AtomicBoolean(); public boolean isTriggeringEvent(final File activeFile, final E event) { if (trigger.compareAndSet(false, true) && activeFile.length() > 0) { String maxFileSize = getMaxFileSize(); setMaxFileSize("1"); super.isTriggeringEvent(activeFile, event); setMaxFileSize(maxFileSize); return true; } return super.isTriggeringEvent(activeFile, event); } } 

当应用程序启动时,我find了另一个滚动logFile的解决scheme。

我使用logback的RollingFileAppender与logback的FixedWindowRollingPolicy和我自己的TriggeringPolicy<E>

FixedWindowRollingPolicy获取新的logFile的fileNamePattern,其中%1是文件的新编号。 maxIndex代表我的“历史”的最大数量。 更多信息: FixedWindowRollingPolicy

我的实现TriggeringPolicy 一次返回true,当isTriggeringEvent(…)被调用。 所以当第一次调用策略时,WindowRollingPolicy将滚动日志文件,之后它不会再次滚动。

RollingFileAppender的xmlconfiguration:

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

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

重写ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP中的isTriggeringEvent()方法应该可以很好地工作。 首次调用isTriggeringEvent()方法返回“true”。

Ceki的解决scheme似乎并不适合我,但至less似乎是部分原因。

由于在启动TimeBasedFileNamingAndTriggeringPolicyBase时无法看到滚动策略,所以它爆炸了。 随着一些hackery我得到它做一些日志logging,并有一些我得到它观察触发器,但然后再次打破,因为它不能解决其中的一个文件名属性…该软件包是一个logback的,所以我可以到达一些内部,复制SizeAndTimeBasedFNATP#isTriggeringEvent一些逻辑并调用computeCurrentPeriodsHighestCounterValue 。 我认为沿着这条路线可能会起作用,但还没有find魔法组合。 我真的希望自己做些傻事,因为否则我认为这将意味着要么打开一些子类化的细节,要么把这些细节作为另一个滚动/触发策略。

logback.xml:尝试了rollingPolicy内部和外部的triggeringPolicyTimeBasedFileNamingAndTriggeringPolicy各种sorting。

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

触发政策:

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

例外:

 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] 

对于使用已经存在的组件的解决scheme,logback提供了唯一命名的文件 : http : //logback.qos.ch/manual/appenders.html#uniquelyNamed

在应用程序开发阶段或在短期应用程序(例如批处理应用程序)的情况下,最好在每次启动新应用程序时创build一个新的日志文件。 这在<timestamp>元素的帮助下很容易做到。

 <?xml version="1.0" encoding="UTF-8"?> <configuration> <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> <appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> </layout> <file>server-${startTimestamp}.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</FileNamePattern> <!-- keep 7 days' worth of history --> <MaxHistory>7</MaxHistory> <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <MaxFileSize>1KB</MaxFileSize> </TimeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <root level="DEBUG"> <appender-ref ref="File" /> </root> </configuration> 

更新为logback-1.2.1

 <?xml version="1.0" encoding="UTF-8"?> <configuration> <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> <appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> </layout> <file>server-${startTimestamp}.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</fileNamePattern> <maxFileSize>10MB</maxFileSize> <!-- keep 7 days' worth of history --> <maxHistory>7</maxHistory> <totalSizeCap>20GB</totalSizeCap> </rollingPolicy> </appender> <root level="DEBUG"> <appender-ref ref="File" /> </root> </configuration> 

创build你自己的ch.qos.logback.core.rolling.TimeBasedRollingPolicy的子类并覆盖它的start

 public class MyPolicy extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy { public void start ( ) { super.start( ); rollover( ); } } 

我有以下的工作(结合以前的答案)。 注意我正在处理基于大小的文件,而不是基于时间,但我猜测相同的解决scheme的作品。

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

}

我终于弄明白了。 我可以按照规模,时间和开始。 这里是解决scheme:

1创build你自己的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 ); }; } 

第二次configurationlockbax

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

这个解决scheme非常有用,非常感谢。 但是,有一个令人讨厌的小故障:当你第一次运行程序时,日志在创build之后立即滚动,当它是空的或者空的时候。 所以我build议一个解决方法:检查日志文件是否存在,并且在调用方法时不是空的。 此外,还有一个修复方法:重命名“已启动”variables,因为它隐藏了具有相同名称的inheritance成员。

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

此外,我相信它适用于logback版本1.1.4-SNAPSHOT(我得到了源代码并编译它自己),但它不完全适用于1.1.3版本。 使用1.1.3时,它会使用指定的时区正确命名文件,但在默认时区午夜仍会发生滚动。

该API已经改变(例如setMaxFileSize不再存在),上面的东西似乎没有工作,但我有一个对我来说是针对logback 1.1.8(最新在这个时候)。

我想在启动和滚动的大小,但没有时间。 这样做:

 public class RollOnStartupAndSizeTriggeringPolicy<E> extends SizeBasedTriggeringPolicy<E> { private final AtomicBoolean firstTime = new AtomicBoolean(); public boolean isTriggeringEvent(final File activeFile, final E event) { if (firstTime.compareAndSet(false, true) && activeFile != null && activeFile.length() > 0) { return true; } return super.isTriggeringEvent(activeFile, event); } } 

有了这个你也需要滚动策略。 FixedWindowRollingPolicy可能会做,但我不喜欢它,因为我想保留大量的文件,这是非常低效的。 逐渐增加的数字(而不是像FixedWindow那样滑动)会起作用,但不存在。 只要我写我自己,我决定用时间而不是数。 我想扩展当前的logback代码,但是对于基于时间的东西,滚动和触发策略经常合并成一个类,并且有嵌套和循环的东西以及没有getter的字段的日志,所以我发现这是不可能的。 所以我必须从头开始做很多事情。 我保持简单,并没有实现像压缩function – 我很想拥有它们,但我只是想保持简单。

 public class TimestampRollingPolicy<E> extends RollingPolicyBase { private final RenameUtil renameUtil = new RenameUtil(); private String activeFileName; private String fileNamePatternStr; private FileNamePattern fileNamePattern; @Override public void start() { super.start(); renameUtil.setContext(this.context); activeFileName = getParentsRawFileProperty(); if (activeFileName == null || activeFileName.isEmpty()) { addError("No file set on appender"); } if (fileNamePatternStr == null || fileNamePatternStr.isEmpty()) { addError("fileNamePattern not set"); fileNamePattern = null; } else { fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); } addInfo("Will use the pattern " + fileNamePattern + " to archive files"); } @Override public void rollover() throws RolloverFailure { File f = new File(activeFileName); if (!f.exists()) { return; } if (f.length() <= 0) { return; } try { String archiveFileName = fileNamePattern.convert(new Date(f.lastModified())); renameUtil.rename(activeFileName, archiveFileName); } catch (RolloverFailure e) { throw e; } catch (Exception e) { throw new RolloverFailure(e.toString(), e); } } @Override public String getActiveFileName() { return activeFileName; } public void setFileNamePattern(String fnp) { fileNamePatternStr = fnp; } } 

然后configuration看起来像

 <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <file>/tmp/monitor.log</file> <rollingPolicy class="my.log.TimestampRollingPolicy"> <fileNamePattern>/tmp/monitor.%d{yyyyMMdd-HHmmss}.log</fileNamePattern> </rollingPolicy> <triggeringPolicy class="my.log.RollOnStartupAndSizeTriggeringPolicy"> <maxFileSize>1gb</maxFileSize> </triggeringPolicy> </appender> 

如果你感到沮丧,这是不是本地解决,投票

http://jira.qos.ch/browse/LOGBACK-204

http://jira.qos.ch/browse/LOGBACK-215

(这已经有好几年了,对我来说,这绝对是关键的function,尽pipe我知道许多其他框架也会失败)