我想配置logback以执行以下操作。
除了最后一项启动滚动之外,我已经完成了所有工作。有谁知道如何实现这一目标?这是配置......
<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>
答案 0 :(得分:25)
其他建议都不适合我的情况。我不想使用基于大小和时间的解决方案,因为它需要配置MaxFileSize,我们使用严格的基于时间的策略。以下是我使用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()内执行比较的解决方案更优化。无论比较小,它在每条日志消息上执行时仍会略微降低性能。这也会强制在启动时立即发生翻转,而不是等待第一个日志事件。
@NoAutoStart注释对于防止Joran在所有其他初始化完成之前执行start()方法非常重要。否则,您将获得NullPointerException。
这是配置:
<!-- 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>
希望这有帮助!
答案 1 :(得分:7)
它适用于我,使用以下类作为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);
}
}
答案 2 :(得分:5)
当应用程序启动时,我找到了另一种滚动logFile的解决方案。
我使用logback&#39; ViewHolder (android.widget.TextView) in ViewHolder cannot be applied
to (android.view.View)
和RollingFileAppender
以及FixedWindowRollingPolicy
我自己的实现。
TriggeringPolicy<E>
获取新logFile的fileNamePattern,其中FixedWindowRollingPolicy
是文件的新编号。 maxIndex代表我的&#34;历史记录&#34;的最大数量。更多信息:FixedWindowRollingPolicy
我的实现%1
在第一个时间返回true,当调用isTriggeringEvent(...)时。因此,当第一次调用策略时,WindowRollingPolicy将覆盖日志文件,之后它将不再翻转。
TriggeringPolicy
的xml配置:
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>
:
TriggeringPolicy
答案 3 :(得分:5)
对于使用现有组件的解决方案,logback会建议唯一命名的文件:http://logback.qos.ch/manual/appenders.html#uniquelyNamed
在应用程序开发阶段或在短暂的情况下 应用,例如批处理应用程序,最好创建一个新的 每次新应用程序启动时的日志文件。这很容易做到 在
<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>
答案 4 :(得分:3)
覆盖ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP中的isTriggeringEvent()方法应该可以很好地工作。只需在第一次调用isTriggeringEvent()方法时返回'true'。
答案 5 :(得分:2)
Ceki的解决方案似乎对我不起作用,但似乎至少在那里有所作为。
它爆炸了,因为它在启动TimeBasedFileNamingAndTriggeringPolicyBase
时看不到滚动策略。有一些hackery我得到它做一些日志记录,并有一些我得到它来观察触发器,但然后它再次破坏,因为它无法解析其中一个文件名属性...包是一个logback所以我可以到达一些内部,复制SizeAndTimeBasedFNATP#isTriggeringEvent
中的一些逻辑并调用computeCurrentPeriodsHighestCounterValue
。我觉得这些方面的东西可能有用,但还没有找到神奇的组合。我真的希望我做的事情很愚蠢,因为否则我认为这或者意味着要么为子类化打开一些细节,要么直接将其作为另一个滚动/触发政策进行回溯。
logback.xml:在triggeringPolicy
内外尝试了TimeBasedFileNamingAndTriggeringPolicy
,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>
触发政策:
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]
答案 6 :(得分:1)
创建自己的ch.qos.logback.core.rolling.TimeBasedRollingPolicy
子类并覆盖其start
public class MyPolicy
extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy
{
public void start ( )
{
super.start( );
rollover( );
}
}
答案 7 :(得分:1)
我得到了以下工作(结合以前答案的想法)。注意我正在处理基于大小的文件,而不是基于时间的,但我猜相同的解决方案有效。
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;
}
}
答案 8 :(得分:1)
我终于明白了。我可以按大小,时间和启动来滚动。这是解决方案:
1st创建自己的类
@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 );
};
}
第二次配置回溯
<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>
答案 9 :(得分:1)
这个解决方案确实有效,非常感谢。 但是,有一个令人讨厌的故障:当您第一次运行程序时,日志在创建后立即滚动,当它为空或几乎为空时。 所以我建议修复:检查日志文件是否存在,并且在调用方法时不是空的。 此外,还有一个美化修复:重命名“已启动”变量,因为它隐藏了具有相同名称的继承成员。
@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中,它使用指定的时区正确命名文件,但在午夜的默认时区仍然会发生翻转。
答案 10 :(得分:0)
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的字段的日志,所以我发现这是不可能的。所以我不得不从头开始做很多事情。我保持简单,并没有实现压缩等功能 - 我很乐意拥有它们,但我只是想保持简单。
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;
}
}
然后配置看起来像
<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
(它已经好几年了,对我来说这绝对是关键功能,虽然我知道很多其他框架也失败了)
答案 11 :(得分:0)
我找到了一种方法,不需要在配置中注入自定义类。它利用测试API诱使添加程序认为是时候滚动文件了。
此示例假设您在名为RollingFileAppender
的XML中配置了ROLLING
,并将其设置为使用SizeAndTimeBasedRollingPolicy
进行每日翻转:
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>./logs/${app-name}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>./logs/${app-name}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>5</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
下面的代码将找到滚动策略并触发滚动。请注意,这将在短时间内全局改写追加器的时钟,因此在任何其他线程可能潜在地写入消息时,请勿调用它。
// get the root logger
ch.qos.logback.classic.Logger _logger = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
// get the triggering policy from the rolling appender
RollingFileAppender<?> _appender = (RollingFileAppender<?>)_logger.getAppender("ROLLING");
SizeAndTimeBasedRollingPolicy<?> _policy = (SizeAndTimeBasedRollingPolicy<?>)_appender.getRollingPolicy();
TimeBasedFileNamingAndTriggeringPolicy<?> _trigger = _policy.getTimeBasedFileNamingAndTriggeringPolicy();
// trick the appender into thinking it is time to rollover
_trigger.setCurrentTime(System.currentTimeMillis() + 24*60*60*1000);
// this message will trigger the rollover
LOG.info("Initializing log for app: {}", _appName);
// turn off fake time
_trigger.setCurrentTime(0);