All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.dropwizard.logging.FileAppenderFactory Maven / Gradle / Ivy

There is a newer version: 5.0.0-alpha.5
Show newest version
package io.dropwizard.logging;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.OutputStreamAppender;
import ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import ch.qos.logback.core.util.FileSize;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.dropwizard.util.DataSize;
import io.dropwizard.validation.MinDataSize;
import io.dropwizard.validation.ValidationMethod;

import javax.annotation.Nullable;
import javax.validation.constraints.Min;

import static java.util.Objects.requireNonNull;

/**
 * An {@link AppenderFactory} implementation which provides an appender that writes events to a file, archiving older
 * files as it goes.
 * 

* Configuration Parameters: *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameDefaultDescription
{@code type}REQUIREDThe appender type. Must be {@code file}.
{@code threshold}{@code ALL}The lowest level of events to write to the file.
{@code currentLogFilename}REQUIREDThe filename where current events are logged.
{@code archive}{@code true}Whether or not to archive old events in separate files.
{@code archivedLogFilenamePattern}REQUIRED if {@code archive} is {@code true}. * The filename pattern for archived files. * If {@code maxFileSize} is specified, rollover is size-based, and the pattern must contain {@code %i} for * an integer index of the archived file. * Otherwise rollover is date-based, and the pattern must contain {@code %d}, which is replaced with the * date in {@code yyyy-MM-dd} form. * If the pattern ends with {@code .gz} or {@code .zip}, files will be compressed as they are archived. *
{@code archivedFileCount}{@code 5} * The number of archived files to keep. Must be greater than or equal to {@code 0}. Zero is a * special value signifying to keep infinite logs (use with caution) *
{@code maxFileSize}(unlimited) * The maximum size of the currently active file before a rollover is triggered. The value can be expressed * with SI and IEC prefixes, see {@link io.dropwizard.util.DataSizeUnit}. * Examples include 100MiB, 1GiB, 1TiB. Sizes can also be spelled out, such as 100 mebibytes, * 1 gibibyte, 1 tebibyte. *
{@code totalSizeCap}(unlimited) * Controls the total size of all files. Oldest archives are deleted asynchronously when the total * size cap is exceeded. *
{@code timeZone}{@code UTC}The time zone to which event timestamps will be converted.
{@code logFormat}the default format * The Logback pattern with which events will be formatted. See * the Logback documentation * for details. *
{@code bufferSize}8KiB * The buffer size of the underlying FileAppender (setting added in logback 1.1.10). Increasing this from * the default of 8KiB to 256KiB is reported to significantly reduce thread contention. *
{@code immediateFlush}{@code true} * If set to true, log events will be immediately flushed to disk. Immediate flushing is safer, but * it degrades logging throughput. * See the Logback documentation * for details. *
* * @see AbstractAppenderFactory */ @JsonTypeName("file") public class FileAppenderFactory extends AbstractOutputStreamAppenderFactory { @Nullable private String currentLogFilename; private boolean archive = true; @Nullable private String archivedLogFilenamePattern; @Min(0) private int archivedFileCount = 5; @Nullable private DataSize maxFileSize; @Nullable private DataSize totalSizeCap; @MinDataSize(1) private DataSize bufferSize = DataSize.bytes(FileAppender.DEFAULT_BUFFER_SIZE); private boolean immediateFlush = true; @JsonProperty @Nullable public String getCurrentLogFilename() { return currentLogFilename; } @JsonProperty public void setCurrentLogFilename(@Nullable String currentLogFilename) { this.currentLogFilename = currentLogFilename; } @JsonProperty public boolean isArchive() { return archive; } @JsonProperty public void setArchive(boolean archive) { this.archive = archive; } @JsonProperty @Nullable public String getArchivedLogFilenamePattern() { return archivedLogFilenamePattern; } @JsonProperty public void setArchivedLogFilenamePattern(String archivedLogFilenamePattern) { this.archivedLogFilenamePattern = archivedLogFilenamePattern; } @JsonProperty public int getArchivedFileCount() { return archivedFileCount; } @JsonProperty public void setArchivedFileCount(int archivedFileCount) { this.archivedFileCount = archivedFileCount; } @JsonProperty @Nullable public DataSize getMaxFileSize() { return maxFileSize; } @JsonProperty public void setMaxFileSize(@Nullable DataSize maxFileSize) { this.maxFileSize = maxFileSize; } @JsonProperty @Nullable public DataSize getTotalSizeCap() { return totalSizeCap; } @JsonProperty public void setTotalSizeCap(@Nullable DataSize totalSizeCap) { this.totalSizeCap = totalSizeCap; } @JsonProperty public DataSize getBufferSize() { return bufferSize; } @JsonProperty public void setBufferSize(DataSize bufferSize) { this.bufferSize = bufferSize; } public boolean isImmediateFlush() { return immediateFlush; } @JsonProperty public void setImmediateFlush(boolean immediateFlush) { this.immediateFlush = immediateFlush; } @JsonIgnore @ValidationMethod(message = "totalSizeCap has no effect when using maxFileSize and an archivedLogFilenamePattern without %d, as archivedFileCount implicitly controls the total size cap") public boolean isTotalSizeCapValid() { return !archive || totalSizeCap == null || !(maxFileSize != null && !requireNonNull(archivedLogFilenamePattern).contains("%d")); } @JsonIgnore @ValidationMethod(message = "must have archivedLogFilenamePattern if archive is true") public boolean isValidArchiveConfiguration() { return !archive || (archivedLogFilenamePattern != null); } @JsonIgnore @ValidationMethod(message = "when specifying maxFileSize, archivedLogFilenamePattern must contain %i") public boolean isValidForMaxFileSizeSetting() { return !archive || maxFileSize == null || (archivedLogFilenamePattern != null && archivedLogFilenamePattern.contains("%i")); } @JsonIgnore @ValidationMethod(message = "when archivedLogFilenamePattern contains %i, maxFileSize must be specified") public boolean isMaxFileSizeSettingSpecified() { return !archive || !(archivedLogFilenamePattern != null && archivedLogFilenamePattern.contains("%i")) || maxFileSize != null; } @JsonIgnore @ValidationMethod(message = "currentLogFilename can only be null when archiving is enabled") public boolean isValidFileConfiguration() { return archive || currentLogFilename != null; } @Override protected OutputStreamAppender appender(LoggerContext context) { final FileAppender appender = buildAppender(context); appender.setName("file-appender"); appender.setAppend(true); appender.setContext(context); appender.setImmediateFlush(immediateFlush); appender.setPrudent(false); return appender; } protected FileAppender buildAppender(LoggerContext context) { if (archive) { final RollingFileAppender appender = new RollingFileAppender<>(); appender.setContext(context); appender.setFile(currentLogFilename); appender.setBufferSize(new FileSize(bufferSize.toBytes())); if (maxFileSize != null && !requireNonNull(archivedLogFilenamePattern).contains("%d")) { final FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy(); rollingPolicy.setContext(context); rollingPolicy.setMaxIndex(getArchivedFileCount()); rollingPolicy.setFileNamePattern(getArchivedLogFilenamePattern()); rollingPolicy.setParent(appender); rollingPolicy.start(); appender.setRollingPolicy(rollingPolicy); final SizeBasedTriggeringPolicy triggeringPolicy = new SizeBasedTriggeringPolicy<>(); triggeringPolicy.setMaxFileSize(new FileSize(maxFileSize.toBytes())); triggeringPolicy.setContext(context); triggeringPolicy.start(); appender.setTriggeringPolicy(triggeringPolicy); return appender; } else { final TimeBasedRollingPolicy rollingPolicy; if (maxFileSize == null) { rollingPolicy = new TimeBasedRollingPolicy<>(); final TimeBasedFileNamingAndTriggeringPolicy triggeringPolicy = new DefaultTimeBasedFileNamingAndTriggeringPolicy<>(); triggeringPolicy.setContext(context); triggeringPolicy.setTimeBasedRollingPolicy(rollingPolicy); appender.setTriggeringPolicy(triggeringPolicy); } else { // Creating a size and time policy does not need a separate triggering policy set // on the appender because this policy registers the trigger policy final SizeAndTimeBasedRollingPolicy sizeAndTimeBasedRollingPolicy = new SizeAndTimeBasedRollingPolicy<>(); sizeAndTimeBasedRollingPolicy.setMaxFileSize(new FileSize(maxFileSize.toBytes())); rollingPolicy = sizeAndTimeBasedRollingPolicy; } if (totalSizeCap != null) { rollingPolicy.setTotalSizeCap(new FileSize(totalSizeCap.toBytes())); } rollingPolicy.setContext(context); rollingPolicy.setFileNamePattern(archivedLogFilenamePattern); rollingPolicy.setMaxHistory(archivedFileCount); appender.setRollingPolicy(rollingPolicy); rollingPolicy.setParent(appender); rollingPolicy.start(); return appender; } } final FileAppender appender = new FileAppender<>(); appender.setContext(context); appender.setFile(currentLogFilename); appender.setBufferSize(new FileSize(bufferSize.toBytes())); return appender; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy