
org.kiwiproject.beta.dropwizard.DefaultingFileAppenderFactory Maven / Gradle / Ivy
package org.kiwiproject.beta.dropwizard;
import static org.apache.commons.lang3.StringUtils.isBlank;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.annotations.Beta;
import io.dropwizard.logging.common.AppenderFactory;
import io.dropwizard.logging.common.DropwizardLayout;
import io.dropwizard.logging.common.FileAppenderFactory;
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
import io.dropwizard.logging.common.filter.LevelFilterFactory;
import io.dropwizard.logging.common.layout.LayoutFactory;
import lombok.Getter;
import lombok.Setter;
import org.kiwiproject.jar.KiwiJars;
import java.io.File;
import java.util.Optional;
import java.util.TimeZone;
/**
* A Dropwizard {@link AppenderFactory} implementation which extends {@link FileAppenderFactory} to provide default
* values for the current log file name, archive log file name pattern, and log format if they are not explicitly
* configured. Once the appender is built, these values can be retrieved from the factory instance using
* {@link #getCurrentLogFilename()}, {@link #getArchivedLogFilenamePattern()}, and {@link #getLogFormat()}.
*
* This factory provides the same properties available in {@link FileAppenderFactory} and one additional property
* which allows you to easily use the default Dropwizard log format instead of the one provided here.
*
* To use this in a Dropwizard application, the FQCN must be listed in a {@code META-INF/services/io.dropwizard.logging.common.AppenderFactory}
* file. Dropwizard already provides this file with its own implementations (in the {@code dropwizard-logging} JAR).
* This library also provides the same file with our implementation. These two files (and any others from other providers)
* must all be combined so the resulting file contains all implementations. We generally use the
* Maven Shade Plugin with the
* ServicesResourceTransformer
* to combine these service files.
*
* Last, in the logging configuration
* of your Dropwizard configuration file, you can add an {@code appender} of type {@code rollingWithDefaults}.
*
* @see AppenderFactory
* @see FileAppenderFactory
* @see RollingFileAppender
*/
@Beta
@Getter
@Setter
@JsonTypeName("rollingWithDefaults")
public class DefaultingFileAppenderFactory extends FileAppenderFactory {
private static final String DEFAULT_LOG_FORMAT = "%-5level [%date] [%thread] %logger{5}: %message%n";
/**
* If true, uses the default Dropwizard log format provided by {@link DropwizardLayout}.
*/
private boolean useDefaultDropwizardLogFormat;
@Override
public Appender build(LoggerContext context,
String applicationName,
LayoutFactory layoutFactory,
LevelFilterFactory levelFilterFactory,
AsyncAppenderFactory asyncAppenderFactory) {
var nonNullApplicationName = Optional.ofNullable(applicationName).orElse("service");
if (isBlank(getCurrentLogFilename())) {
setCurrentLogFilename(filePathFor(nonNullApplicationName));
}
if (isBlank(getArchivedLogFilenamePattern())) {
setArchivedLogFilenamePattern(archiveFileNamePatternFor(nonNullApplicationName));
}
if (isBlank(getLogFormat())) {
var logFormat = newLogFormat(isUseDefaultDropwizardLogFormat(), getTimeZone());
setLogFormat(logFormat);
}
return super.build(context, applicationName, layoutFactory, levelFilterFactory, asyncAppenderFactory);
}
private static String filePathFor(String applicationName) {
return logPathFor(applicationName, ".log");
}
private static String archiveFileNamePatternFor(String applicationName) {
return logPathFor(applicationName, "-%d.log.gz");
}
private static String logPathFor(String applicationName, String suffix) {
var path = KiwiJars.getDirectoryPath(DefaultingFileAppenderFactory.class).orElse("./");
return String.join(File.separator, path, applicationName) + suffix;
}
private static String newLogFormat(boolean useDefaultDropwizardLogFormat, TimeZone timeZone) {
if (useDefaultDropwizardLogFormat) {
var dropwizardLayout = new DropwizardLayout(new LoggerContext(), timeZone);
return dropwizardLayout.getPattern();
}
return DEFAULT_LOG_FORMAT;
}
}