The API has changed (for example setMaxFileSize no longer exists) and a lot of the stuff above doesn't seem to work, but I have something that is working for me against logback 1.1.8 (the latest at this time).
I wanted to roll on startup and roll on size, but not time. This does it:
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);
}
}
With this you also need a rolling policy. FixedWindowRollingPolicy would probably do, but I don't like it because I want to keep a large number of files and it is very inefficient for that. Something that numbers incrementally up (instead of sliding like FixedWindow) would work, but that doesn't exist. As long as I am writing my own I decided to use time instead of count. I wanted to extend current logback code, but for the time based stuff the rolling and triggering policies are often combined into one class, and there is logs of nesting and circular stuff and fields with no getters, so I found that rather impossible. So I had to do a lot from scratch. I keep it simple and didn't implement features like compression - I'd love to have them but I am just trying to keep it simple.
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;
}
}
And then config looks like
<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>
if you're frustrated this is not solved natively, vote for it at
http://jira.qos.ch/browse/LOGBACK-204
http://jira.qos.ch/browse/LOGBACK-215
(it's been years, and to me this is absolutely critical functionality, although I know many other frameworks fail at it also)