Java 如何在logback中启动时滚动日志文件
我想将logback配置为执行以下操作Java 如何在logback中启动时滚动日志文件,java,startup,logback,appender,Java,Startup,Logback,Appender,我想将logback配置为执行以下操作 登录到文件 当文件达到50MB时滚动文件 只保存7天的日志 启动时始终生成新文件(滚动) 除了最后一个项目,启动卷,我所有的工作。有人知道如何做到这一点吗?这是配置 %d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg\(%文件:%line\)%n server.log 服务器%d{yyyy-MM-dd}.log 7. 50MB 创建自己的ch.qos.logback.core.rolling.TimeBased
- 登录到文件
- 当文件达到50MB时滚动文件
- 只保存7天的日志
- 启动时始终生成新文件(滚动)
%d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg\(%文件:%line\)%n
server.log
服务器%d{yyyy-MM-dd}.log
7.
50MB
创建自己的ch.qos.logback.core.rolling.TimeBasedRollingPolicy的子类
,并覆盖它的开始
public class MyPolicy
extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy
{
public void start ( )
{
super.start( );
rollover( );
}
}
重写ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP中的isTriggeringEvent()方法应该可以很好地工作。只要在第一次调用isTriggeringEvent()方法时返回'true'。Ceki的解决方案似乎对我不起作用,但至少在某种程度上似乎起到了作用 启动
TimebasedFileName和TriggeringPolicyBase
时,它无法看到滚动策略,因此会发生故障。通过一些黑客技术,我让它做了一些日志记录,再加上一些,我让它观察触发器,但后来它又坏了,因为它无法解析其中一个文件名属性。。。该包是一个logback包,因此我可以访问一些内部,以复制SizeAndTimeBasedFNATP#isTriggeringEvent
中的一些逻辑,并调用computeCurrentPeriodsHighestCounterValue
。我认为这些方法可能会奏效,只是还没有找到神奇的组合。我真的希望我在做一些愚蠢的事情,因为否则我认为这将意味着要么为子类打开一些细节,要么将其作为另一个滚动/触发策略直接放回日志中
logback.xml:尝试了触发策略
、基于时间的事件和触发策略
在滚动策略
内外的各种顺序
${LOG\u DIR}/${LOG\u FILE\u BASE}.LOG
${LOG\u DIR}/${LOG\u FILE\u BASE}.%d{yyyy-MM-dd}.%i.LOG
7.
信息
%消息%n
触发策略:
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;
}
}
它适用于我,使用以下类作为TimeBasedFileName和TriggeringPolicy:
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);
}
}
导入java.io.File;
导入java.util.concurrent.AtomicBoolean;
导入ch.qos.logback.core.joran.spi.NoAutoStart;
导入ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP;
@无自动启动
公共类触发器扩展SizeAndTimeBasedFNATP
{
私有最终AtomicBoolean触发器=新的AtomicBoolean();
公共布尔isTriggeringEvent(最终文件activeFile,最终E事件){
if(trigger.compareAndSet(false,true)&&activeFile.length()>0){
字符串maxFileSize=getMaxFileSize();
setMaxFileSize(“1”);
super.isTriggeringEvent(activeFile,event);
setMaxFileSize(maxFileSize);
返回true;
}
返回super.isTriggeringEvent(activeFile,event);
}
}
我做了以下工作(结合前面答案的想法)。注意,我处理的是基于大小的文件,而不是基于时间的文件,但我猜同样的解决方案也适用
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;
}
公共类StartupSizeBaedTriggeringPolicy扩展了ch.qos.logback.core.rolling.SizeBaedTriggeringPolicy{
私有最终原子引用isFirstTime=新原子引用(true);
@凌驾
公共布尔isTriggeringEvent(最终文件activeFile,最终E事件){
//此方法似乎有副作用,因此始终调用
布尔结果=super.isTriggeringEvent(activeFile,event);
返回是第一次。比较数据集(真、假)| |结果;
}
}其他建议都不适合我的情况。我不想使用基于大小和时间的解决方案,因为它需要配置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
}
}
}
@NoAutoStart
公共类StartupTimeBasedTriggeringPolicy
扩展DefaultTimeBasedFileName和TriggeringPolicy{
@凌驾
公开作废开始(){
super.start();
nextCheck=0升;
isTriggeringEvent(null,null);
试一试{
tbrp.rollover();
}捕捉(翻转失败){
//无所事事
}
}
}
诀窍是将nextCheck time设置为0L,以便isTriggeringEvent()认为是时候将日志文件回滚了。因此,它将执行计算文件名所需的代码,并方便地重置nextCheck时间值。对rollover()的后续调用将导致滚动日志文件。由于这只发生在启动时,因此它比在isTriggerEvent()中执行比较的解决方案更为理想。无论这种比较有多小,当在每个日志消息上执行时,它仍然会略微降低性能。这还强制在启动时立即发生滚动,而不是等待第一个日志事件
@NoAutoStart注释对于防止Joran在所有其他初始化完成之前执行start()方法非常重要。否则,将得到一个NullPointerException
以下是配置:
${LOG_文件}
${LOG_FILE}.%d{yyyyymmdd}{uu%d{HHmmss,aux}
%d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg%n
希望这有帮助 我终于明白了。我可以按大小、时间和启动进行滚动。以下是解决方案: 首先创建自己的类
@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 );
};
}
@NoAutoStart
公共类StartupSizeTimeBasedTriggeringPolicy扩展了SizeAndTimeBasedFNATP{
private boolean start=false;
@凌驾
公共布尔isTriggeringEvent(文件activeFile,E事件){
如果(!已启动){
nextCheck=0升;
返回开始=t
@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>
@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);
}
}
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;
}
}
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);
}
}
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>
<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);