package io.dropwizard.logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.TextNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import io.dropwizard.configuration.FileConfigurationSourceProvider;
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.configuration.YamlConfigurationFactory;
import io.dropwizard.jackson.Jackson;
import io.dropwizard.logging.filter.FilterFactory;
import io.dropwizard.validation.BaseValidator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.assertj.core.data.MapEntry;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
public class DefaultLoggingFactoryTest {
private final ObjectMapper objectMapper = Jackson.newObjectMapper();
private final YamlConfigurationFactory<DefaultLoggingFactory> factory = new YamlConfigurationFactory<>(
DefaultLoggingFactory.class,
BaseValidator.newValidator(),
objectMapper, "dw");
private DefaultLoggingFactory config;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Before
public void setUp() throws Exception {
objectMapper.getSubtypeResolver().registerSubtypes(ConsoleAppenderFactory.class,
FileAppenderFactory.class,
SyslogAppenderFactory.class);
config = factory.build(new File(Resources.getResource("yaml/logging.yml").toURI()));
}
@Test
public void hasADefaultLevel() throws Exception {
assertThat(config.getLevel()).isEqualTo(Level.INFO);
}
@Test
public void canParseNewLoggerFormat() throws Exception {
final DefaultLoggingFactory config = factory.build(
new File(Resources.getResource("yaml/logging_advanced.yml").toURI()));
assertThat(config.getLoggers()).contains(MapEntry.entry("com.example.app", new TextNode("INFO")));
final JsonNode newApp = config.getLoggers().get("com.example.newApp");
assertThat(newApp).isNotNull();
final LoggerConfiguration newAppConfiguration = objectMapper.treeToValue(newApp, LoggerConfiguration.class);
assertThat(newAppConfiguration.getLevel()).isEqualTo(Level.DEBUG);
assertThat(newAppConfiguration.getAppenders()).hasSize(1);
final AppenderFactory<ILoggingEvent> appenderFactory = newAppConfiguration.getAppenders().get(0);
assertThat(appenderFactory).isInstanceOf(FileAppenderFactory.class);
final FileAppenderFactory<ILoggingEvent> fileAppenderFactory = (FileAppenderFactory<ILoggingEvent>) appenderFactory;
assertThat(fileAppenderFactory.getCurrentLogFilename()).isEqualTo("${new_app}.log");
assertThat(fileAppenderFactory.getArchivedLogFilenamePattern()).isEqualTo("${new_app}-%d.log.gz");
assertThat(fileAppenderFactory.getArchivedFileCount()).isEqualTo(5);
assertThat(fileAppenderFactory.getBufferSize().toKilobytes()).isEqualTo(256);
final ImmutableList<FilterFactory<ILoggingEvent>> filterFactories = fileAppenderFactory.getFilterFactories();
assertThat(filterFactories).hasSize(2);
assertThat(filterFactories.get(0)).isExactlyInstanceOf(TestFilterFactory.class);
assertThat(filterFactories.get(1)).isExactlyInstanceOf(SecondTestFilterFactory.class);
final JsonNode legacyApp = config.getLoggers().get("com.example.legacyApp");
assertThat(legacyApp).isNotNull();
final LoggerConfiguration legacyAppConfiguration = objectMapper.treeToValue(legacyApp, LoggerConfiguration.class);
assertThat(legacyAppConfiguration.getLevel()).isEqualTo(Level.DEBUG);
// We should not create additional appenders, if they are not specified
assertThat(legacyAppConfiguration.getAppenders()).isEmpty();
}
@Test
public void testConfigure() throws Exception {
final File newAppLog = folder.newFile("example-new-app.log");
final File newAppNotAdditiveLog = folder.newFile("example-new-app-not-additive.log");
final File defaultLog = folder.newFile("example.log");
final StrSubstitutor substitutor = new StrSubstitutor(ImmutableMap.of(
"new_app", StringUtils.removeEnd(newAppLog.getAbsolutePath(), ".log"),
"new_app_not_additive", StringUtils.removeEnd(newAppNotAdditiveLog.getAbsolutePath(), ".log"),
"default", StringUtils.removeEnd(defaultLog.getAbsolutePath(), ".log")
));
final String configPath = Resources.getResource("yaml/logging_advanced.yml").getFile();
final DefaultLoggingFactory config = factory.build(
new SubstitutingSourceProvider(new FileConfigurationSourceProvider(), substitutor),
configPath);
config.configure(new MetricRegistry(), "test-logger");
LoggerFactory.getLogger("com.example.app").debug("Application debug log");
LoggerFactory.getLogger("com.example.app").info("Application log");
LoggerFactory.getLogger("com.example.newApp").debug("New application debug log");
LoggerFactory.getLogger("com.example.newApp").info("New application info log");
LoggerFactory.getLogger("com.example.legacyApp").debug("Legacy application debug log");
LoggerFactory.getLogger("com.example.legacyApp").info("Legacy application info log");
LoggerFactory.getLogger("com.example.notAdditive").debug("Not additive application debug log");
LoggerFactory.getLogger("com.example.notAdditive").info("Not additive application info log");
config.stop();
assertThat(Files.readLines(defaultLog, StandardCharsets.UTF_8)).containsOnly(
"INFO com.example.app: Application log",
"DEBUG com.example.newApp: New application debug log",
"INFO com.example.newApp: New application info log",
"DEBUG com.example.legacyApp: Legacy application debug log",
"INFO com.example.legacyApp: Legacy application info log");
assertThat(Files.readLines(newAppLog, StandardCharsets.UTF_8)).containsOnly(
"DEBUG com.example.newApp: New application debug log",
"INFO com.example.newApp: New application info log");
assertThat(Files.readLines(newAppNotAdditiveLog, StandardCharsets.UTF_8)).containsOnly(
"DEBUG com.example.notAdditive: Not additive application debug log",
"INFO com.example.notAdditive: Not additive application info log");
}
}