package grails.plugin.lightweightdeploy.logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.OutputStreamAppender;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.FilterReply;
import com.google.common.collect.ImmutableSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Borrowed heavily from com.yammer.dropwizard.logging.LogbackFactory.
*/
public class LogbackFactory {
private LogbackFactory() { /* singleton */ }
// TODO: duplication with below method
public static ConsoleAppender<ILoggingEvent> buildConsoleAppender(ConsoleLoggingConfiguration config,
LoggerContext context) {
final LogFormatter formatter = new LogFormatter(context, config.getTimeZone());
for (String format : config.getLogFormat().asSet()) {
formatter.setPattern(format);
}
formatter.start();
final ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
appender.setContext(context);
appender.setLayout(formatter);
addThresholdFilter(appender, config.getThreshold());
appender.start();
return appender;
}
public static FileAppender<ILoggingEvent> buildFileAppender(FileLoggingConfiguration file,
LoggerContext context) {
final LogFormatter formatter = new LogFormatter(context, file.getTimeZone());
for (String format : file.getLogFormat().asSet()) {
formatter.setPattern(format);
}
formatter.start();
final FileAppender<ILoggingEvent> appender =
file.isArchive() ? new RollingFileAppender<ILoggingEvent>() :
new FileAppender<ILoggingEvent>();
appender.setAppend(true);
appender.setContext(context);
appender.setLayout(formatter);
appender.setFile(file.getCurrentLogFilename());
appender.setPrudent(false);
addThresholdFilter(appender, file.getThreshold());
if (file.isArchive()) {
final DefaultTimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent> triggeringPolicy =
new DefaultTimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent>();
triggeringPolicy.setContext(context);
final TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new TimeBasedRollingPolicy<ILoggingEvent>();
rollingPolicy.setContext(context);
rollingPolicy.setFileNamePattern(file.getArchivedLogFilenamePattern());
rollingPolicy.setTimeBasedFileNamingAndTriggeringPolicy(
triggeringPolicy);
triggeringPolicy.setTimeBasedRollingPolicy(rollingPolicy);
rollingPolicy.setMaxHistory(file.getArchivedFileCount());
((RollingFileAppender<ILoggingEvent>) appender).setRollingPolicy(rollingPolicy);
((RollingFileAppender<ILoggingEvent>) appender).setTriggeringPolicy(triggeringPolicy);
rollingPolicy.setParent(appender);
rollingPolicy.start();
}
appender.stop();
appender.start();
return appender;
}
public static OutputStreamAppender<ILoggingEvent> buildFilteredAppender(final FilteredLoggingConfiguration filtered,
LoggerContext context) {
AbstractLoggingConfiguration appenderConfig = filtered.getAppender();
OutputStreamAppender<ILoggingEvent> appender = buildAppender(appenderConfig, context);
appender.addFilter(new LogEventFilter(filtered));
return appender;
}
private static void addThresholdFilter(FilterAttachable<ILoggingEvent> appender, Level threshold) {
final ThresholdFilter filter = new ThresholdFilter();
filter.setLevel(threshold.toString());
filter.start();
appender.addFilter(filter);
}
public static Set<OutputStreamAppender<ILoggingEvent>> buildAppenders(LoggingConfiguration configuration,
LoggerContext context) {
final Set<OutputStreamAppender<ILoggingEvent>> appenders = new HashSet<OutputStreamAppender<ILoggingEvent>>();
List<AbstractLoggingConfiguration> appenderConfigs = configuration.getAppenderConfigurations();
for (AbstractLoggingConfiguration appenderConfig : appenderConfigs) {
appenders.add(buildAppender(appenderConfig, context));
}
return appenders;
}
private static OutputStreamAppender<ILoggingEvent> buildAppender(AbstractLoggingConfiguration appenderConfig,
LoggerContext context) {
if (appenderConfig instanceof ConsoleLoggingConfiguration) {
return buildConsoleAppender((ConsoleLoggingConfiguration) appenderConfig, context);
} else if (appenderConfig instanceof FileLoggingConfiguration) {
return buildFileAppender((FileLoggingConfiguration) appenderConfig, context);
} else if (appenderConfig instanceof FilteredLoggingConfiguration) {
return buildFilteredAppender((FilteredLoggingConfiguration) appenderConfig, context);
} else {
throw new IllegalArgumentException("Unrecognised appender config type: " + appenderConfig.getClass());
}
}
private static class LogEventFilter extends Filter<ILoggingEvent> {
private final Set<String> includedLoggerNames;
private final Set<String> excludedLoggerNames;
public LogEventFilter(FilteredLoggingConfiguration filtered) {
includedLoggerNames = ImmutableSet.copyOf(filtered.getInclusions());
excludedLoggerNames = ImmutableSet.copyOf(filtered.getExclusions());
}
@Override
public FilterReply decide(ILoggingEvent event) {
String loggerName = event.getLoggerName();
if (!includedLoggerNames.isEmpty() && !includedLoggerNames.contains(loggerName)) {
return FilterReply.DENY;
} else if (excludedLoggerNames.contains(loggerName)) {
return FilterReply.DENY;
} else {
return FilterReply.NEUTRAL;
}
}
}
}