RollingFileOutputBuilder.java
package io.jstach.rainbowgum.rolling;
import io.jstach.rainbowgum.LogProperties;
import io.jstach.rainbowgum.LogProperty;
/**
* Builder to create {@link io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput> }.
* Creates a rolling file output provider.
* <table class="table">
* <caption><strong>Properties retrieved from LogProperties</strong></caption>
* <tr>
* <th>Property Pattern</th>
* <th>Type</th>
* <th>Required</th>
* <th>Default</th>
* <th>Description</th>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_fileName }</code></td>
* <td><code>String</code></td>
* <td><code>false</code></td>
* <td><code>null</code></td>
* <td>File name.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_append }</code></td>
* <td><code>Boolean</code></td>
* <td><code>false</code></td>
* <td><code>null</code></td>
* <td>Whether or not to append to an existing file when first opened.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_prudent }</code></td>
* <td><code>Boolean</code></td>
* <td><code>false</code></td>
* <td><code>null</code></td>
* <td>Logback prudent mode where files are locked on each write.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_bufferSize }</code></td>
* <td><code>String (converted)</code></td>
* <td><code>true</code></td>
* <td>{@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_BUFFER_SIZE }</td>
* <td>Buffer size, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 8KB}. Zero means unbuffered.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_maxFileSize }</code></td>
* <td><code>String (converted)</code></td>
* <td><code>true</code></td>
* <td>{@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_MAX_FILE_SIZE }</td>
* <td>Max file size before a roll is triggered, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 10MB}.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_maxHistory }</code></td>
* <td><code>Integer</code></td>
* <td><code>true</code></td>
* <td>{@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_MAX_HISTORY }</td>
* <td>Number of archives to retain.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_totalSizeCap }</code></td>
* <td><code>String (converted)</code></td>
* <td><code>true</code></td>
* <td>{@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_TOTAL_SIZE_CAP }</td>
* <td>Total archive size cap; zero means unlimited.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_cleanHistoryOnStart }</code></td>
* <td><code>Boolean</code></td>
* <td><code>true</code></td>
* <td>{@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_CLEAN_HISTORY_ON_START }</td>
* <td>Whether pruning also runs once at start, not just after each roll.</td>
* </tr>
* <tr>
* <td><code>{@value PROPERTY_fileNamePattern }</code></td>
* <td><code>String</code></td>
* <td><code>true</code></td>
* <td>{@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_FILE_NAME_PATTERN }</td>
* <td>Archive naming pattern; must contain <code>%i</code> and must not contain <code>%d</code> (date based rotation is not supported).</td>
* </tr>
* </table>
*/
public final class RollingFileOutputBuilder implements io.jstach.rainbowgum.LogBuilder<RollingFileOutputBuilder,io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput>> {
/**
* The properties to be retrieved from config will have
* this prefix.
*/
static final String PROPERTY_PREFIX = "logging.appender.{name}.output.rolling.";
/**
* <code>{@value #PROPERTY_fileName } = java.lang.String</code> File name.
*/
static final String PROPERTY_fileName = PROPERTY_PREFIX + "fileName";
/**
* <code>{@value #PROPERTY_append } = java.lang.Boolean</code> Whether or not to append to an existing file when first opened.
*/
static final String PROPERTY_append = PROPERTY_PREFIX + "append";
/**
* <code>{@value #PROPERTY_prudent } = java.lang.Boolean</code> Logback prudent mode where files are locked on each write.
*/
static final String PROPERTY_prudent = PROPERTY_PREFIX + "prudent";
/**
* <code>{@value #PROPERTY_bufferSize } = io.jstach.rainbowgum.file.DataSize</code> Buffer size, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 8KB}. Zero means unbuffered.
*/
static final String PROPERTY_bufferSize = PROPERTY_PREFIX + "bufferSize";
/**
* <code>{@value #PROPERTY_maxFileSize } = io.jstach.rainbowgum.file.DataSize</code> Max file size before a roll is triggered, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 10MB}.
*/
static final String PROPERTY_maxFileSize = PROPERTY_PREFIX + "maxFileSize";
/**
* <code>{@value #PROPERTY_maxHistory } = java.lang.Integer</code> Number of archives to retain.
*/
static final String PROPERTY_maxHistory = PROPERTY_PREFIX + "maxHistory";
/**
* <code>{@value #PROPERTY_totalSizeCap } = io.jstach.rainbowgum.file.DataSize</code> Total archive size cap; zero means unlimited.
*/
static final String PROPERTY_totalSizeCap = PROPERTY_PREFIX + "totalSizeCap";
/**
* <code>{@value #PROPERTY_cleanHistoryOnStart } = java.lang.Boolean</code> Whether pruning also runs once at start, not just after each roll.
*/
static final String PROPERTY_cleanHistoryOnStart = PROPERTY_PREFIX + "cleanHistoryOnStart";
/**
* <code>{@value #PROPERTY_fileNamePattern } = java.lang.String</code> Archive naming pattern; must contain <code>%i</code> and must not contain <code>%d</code> (date based rotation is not supported).
*/
static final String PROPERTY_fileNamePattern = PROPERTY_PREFIX + "fileNamePattern";
private final String propertyPrefix;
final String property_fileName;
final String property_append;
final String property_prudent;
final String property_bufferSize;
final String property_maxFileSize;
final String property_maxHistory;
final String property_totalSizeCap;
final String property_cleanHistoryOnStart;
final String property_fileNamePattern;
private final java.lang.String name;
private java.net.@org.jspecify.annotations.Nullable URI uri;
private java.lang.@org.jspecify.annotations.Nullable String fileName = null;
private java.lang.@org.jspecify.annotations.Nullable Boolean append = null;
private java.lang.@org.jspecify.annotations.Nullable Boolean prudent = null;
private io.jstach.rainbowgum.file.DataSize bufferSize = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_BUFFER_SIZE;
private io.jstach.rainbowgum.file.DataSize maxFileSize = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_MAX_FILE_SIZE;
private java.lang.Integer maxHistory = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_MAX_HISTORY;
private io.jstach.rainbowgum.file.DataSize totalSizeCap = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_TOTAL_SIZE_CAP;
private java.lang.Boolean cleanHistoryOnStart = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_CLEAN_HISTORY_ON_START;
private java.lang.String fileNamePattern = io.jstach.rainbowgum.rolling.RollingFileOutput.DEFAULT_FILE_NAME_PATTERN;
/**
* Create a builder for {@code io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput> }.
* @param name will fill <code>{name}</code> in <code>logging.appender.{name}.output.rolling.</code>. Name of output, not file name.
*/
public RollingFileOutputBuilder(
java.lang.String name
) {
try {
java.util.Map<String,String> prefixParameters = java.util.Map.of(
"name", name
);
this.propertyPrefix = LogProperties.interpolateKey(PROPERTY_PREFIX, prefixParameters);
this.name = name;
property_fileName = LogProperties.interpolateKey(PROPERTY_fileName, prefixParameters);
property_append = LogProperties.interpolateKey(PROPERTY_append, prefixParameters);
property_prudent = LogProperties.interpolateKey(PROPERTY_prudent, prefixParameters);
property_bufferSize = LogProperties.interpolateKey(PROPERTY_bufferSize, prefixParameters);
property_maxFileSize = LogProperties.interpolateKey(PROPERTY_maxFileSize, prefixParameters);
property_maxHistory = LogProperties.interpolateKey(PROPERTY_maxHistory, prefixParameters);
property_totalSizeCap = LogProperties.interpolateKey(PROPERTY_totalSizeCap, prefixParameters);
property_cleanHistoryOnStart = LogProperties.interpolateKey(PROPERTY_cleanHistoryOnStart, prefixParameters);
property_fileNamePattern = LogProperties.interpolateKey(PROPERTY_fileNamePattern, prefixParameters);
}
catch (IllegalArgumentException e) {
throw LogProperty.ValidationException.of(this.getClass(), e);
}
}
/**
* Sets uri.
* File uri, set by the appender from its <code>output.uri</code>.
* Default is <code>null</code>.
* @param uri not configurable through properties File uri, set by the appender from its <code>output.uri</code>.
* @return this builder.
*/
public RollingFileOutputBuilder uri(java.net.@org.jspecify.annotations.Nullable URI uri) {
this.uri = uri;
return this;
}
/**
* Sets fileName.
* File name.
* Default is <code>null</code>.
* @param fileName <code>{@value #PROPERTY_fileName } = java.lang.String</code> File name.
* @return this builder.
*/
public RollingFileOutputBuilder fileName(java.lang.@org.jspecify.annotations.Nullable String fileName) {
this.fileName = fileName;
return this;
}
/**
* Sets append.
* Whether or not to append to an existing file when first opened.
* Default is <code>null</code>.
* @param append <code>{@value #PROPERTY_append } = java.lang.Boolean</code> Whether or not to append to an existing file when first opened.
* @return this builder.
*/
public RollingFileOutputBuilder append(java.lang.@org.jspecify.annotations.Nullable Boolean append) {
this.append = append;
return this;
}
/**
* Sets prudent.
* Logback prudent mode where files are locked on each write.
* Default is <code>null</code>.
* @param prudent <code>{@value #PROPERTY_prudent } = java.lang.Boolean</code> Logback prudent mode where files are locked on each write.
* @return this builder.
*/
public RollingFileOutputBuilder prudent(java.lang.@org.jspecify.annotations.Nullable Boolean prudent) {
this.prudent = prudent;
return this;
}
/**
* Sets <strong>required</strong> bufferSize.
* Buffer size, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 8KB}. Zero means unbuffered.
* Default is {@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_BUFFER_SIZE }.
* @param bufferSize <code>{@value #PROPERTY_bufferSize } = io.jstach.rainbowgum.file.DataSize</code> Buffer size, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 8KB}. Zero means unbuffered.
* @return this builder.
*/
public RollingFileOutputBuilder bufferSize(io.jstach.rainbowgum.file.DataSize bufferSize) {
this.bufferSize = bufferSize;
return this;
}
/**
* Sets <strong>required</strong> maxFileSize.
* Max file size before a roll is triggered, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 10MB}.
* Default is {@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_MAX_FILE_SIZE }.
* @param maxFileSize <code>{@value #PROPERTY_maxFileSize } = io.jstach.rainbowgum.file.DataSize</code> Max file size before a roll is triggered, in {@link io.jstach.rainbowgum.file.DataSize#parse(String)} format when set by property, e.g. {@code 10MB}.
* @return this builder.
*/
public RollingFileOutputBuilder maxFileSize(io.jstach.rainbowgum.file.DataSize maxFileSize) {
this.maxFileSize = maxFileSize;
return this;
}
/**
* Sets <strong>required</strong> maxHistory.
* Number of archives to retain.
* Default is {@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_MAX_HISTORY }.
* @param maxHistory <code>{@value #PROPERTY_maxHistory } = java.lang.Integer</code> Number of archives to retain.
* @return this builder.
*/
public RollingFileOutputBuilder maxHistory(java.lang.Integer maxHistory) {
this.maxHistory = maxHistory;
return this;
}
/**
* Sets <strong>required</strong> totalSizeCap.
* Total archive size cap; zero means unlimited.
* Default is {@link io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_TOTAL_SIZE_CAP }.
* @param totalSizeCap <code>{@value #PROPERTY_totalSizeCap } = io.jstach.rainbowgum.file.DataSize</code> Total archive size cap; zero means unlimited.
* @return this builder.
*/
public RollingFileOutputBuilder totalSizeCap(io.jstach.rainbowgum.file.DataSize totalSizeCap) {
this.totalSizeCap = totalSizeCap;
return this;
}
/**
* Sets <strong>required</strong> cleanHistoryOnStart.
* Whether pruning also runs once at start, not just after each roll.
* Default is {@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_CLEAN_HISTORY_ON_START }.
* @param cleanHistoryOnStart <code>{@value #PROPERTY_cleanHistoryOnStart } = java.lang.Boolean</code> Whether pruning also runs once at start, not just after each roll.
* @return this builder.
*/
public RollingFileOutputBuilder cleanHistoryOnStart(java.lang.Boolean cleanHistoryOnStart) {
this.cleanHistoryOnStart = cleanHistoryOnStart;
return this;
}
/**
* Sets <strong>required</strong> fileNamePattern.
* Archive naming pattern; must contain <code>%i</code> and must not contain <code>%d</code> (date based rotation is not supported).
* Default is {@value io.jstach.rainbowgum.rolling.RollingFileOutput#DEFAULT_FILE_NAME_PATTERN }.
* @param fileNamePattern <code>{@value #PROPERTY_fileNamePattern } = java.lang.String</code> Archive naming pattern; must contain <code>%i</code> and must not contain <code>%d</code> (date based rotation is not supported).
* @return this builder.
*/
public RollingFileOutputBuilder fileNamePattern(java.lang.String fileNamePattern) {
this.fileNamePattern = fileNamePattern;
return this;
}
/**
* Creates {@code io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput> } from this builder.
* @return {@code io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput> }.
*/
public io.jstach.rainbowgum.LogProvider<io.jstach.rainbowgum.rolling.RollingFileOutput> build() {
try {
return io.jstach.rainbowgum.rolling.RollingFileOutput.of(
this.name
, this.uri
, this.fileName
, this.append
, this.prudent
, io.jstach.rainbowgum.LogProperty.require(property_bufferSize, this.bufferSize)
, io.jstach.rainbowgum.LogProperty.require(property_maxFileSize, this.maxFileSize)
, io.jstach.rainbowgum.LogProperty.require(property_maxHistory, this.maxHistory)
, io.jstach.rainbowgum.LogProperty.require(property_totalSizeCap, this.totalSizeCap)
, io.jstach.rainbowgum.LogProperty.require(property_cleanHistoryOnStart, this.cleanHistoryOnStart)
, io.jstach.rainbowgum.LogProperty.require(property_fileNamePattern, this.fileNamePattern)
);
}
catch (IllegalArgumentException | LogProperty.PropertyMissingException e) {
throw LogProperty.ValidationException.of(this.getClass(), e);
}
}
@Override
public RollingFileOutputBuilder fromProperties(LogProperties properties) {
var __v = LogProperty.Validator.of(this.getClass());
var _fileName = properties.forKey(property_fileName).ofString().or(this.fileName).validateIfError(__v);
var _append = properties.forKey(property_append).ofBoolean().or(this.append).validateIfError(__v);
var _prudent = properties.forKey(property_prudent).ofBoolean().or(this.prudent).validateIfError(__v);
var _bufferSize = properties.forKey(property_bufferSize).ofString().map(_v -> io.jstach.rainbowgum.rolling.RollingFileOutput.parseDataSize(_v)).or(this.bufferSize).validate(__v);
var _maxFileSize = properties.forKey(property_maxFileSize).ofString().map(_v -> io.jstach.rainbowgum.rolling.RollingFileOutput.parseDataSize(_v)).or(this.maxFileSize).validate(__v);
var _maxHistory = properties.forKey(property_maxHistory).ofInt().or(this.maxHistory).validate(__v);
var _totalSizeCap = properties.forKey(property_totalSizeCap).ofString().map(_v -> io.jstach.rainbowgum.rolling.RollingFileOutput.parseDataSize(_v)).or(this.totalSizeCap).validate(__v);
var _cleanHistoryOnStart = properties.forKey(property_cleanHistoryOnStart).ofBoolean().or(this.cleanHistoryOnStart).validate(__v);
var _fileNamePattern = properties.forKey(property_fileNamePattern).ofString().or(this.fileNamePattern).validate(__v);
__v.validate();
this.fileName = _fileName.valueOrNull();
this.append = _append.valueOrNull();
this.prudent = _prudent.valueOrNull();
this.bufferSize = _bufferSize.value();
this.maxFileSize = _maxFileSize.value();
this.maxHistory = _maxHistory.value();
this.totalSizeCap = _totalSizeCap.value();
this.cleanHistoryOnStart = _cleanHistoryOnStart.value();
this.fileNamePattern = _fileNamePattern.value();
return this;
}
/**
* The interpolated property prefix: {@value #PROPERTY_PREFIX}.
* @return resolved prefix which should end with a "<code>.</code>".
*/
@Override
public String propertyPrefix() {
return this.propertyPrefix;
}
}