Skip to content

Commit

Permalink
Logging: add the ability to specify an alternate logging configuratio…
Browse files Browse the repository at this point in the history
…n file via system property

Closes elastic#2044
  • Loading branch information
neowulf authored and javanna committed May 28, 2015
1 parent 91e9caa commit 8c41df6
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 7 deletions.
14 changes: 14 additions & 0 deletions docs/reference/setup/configuration.asciidoc
Expand Up @@ -338,6 +338,20 @@ Additional Appenders and other logging classes provided by
http://logging.apache.org/log4j/extras/[log4j-extras] are also available,
out of the box.

Optionally, the location of the configuration file can be set externally using
a system property, for example:

[source,sh]
--------------------------------------------------
$ elasticsearch -Des.logging=/abs/path/to/logging/file.yml
--------------------------------------------------

or

[source,sh]
--------------------------------------------------
$ elasticsearch -Des.logging=log_config_file_in_classpath.yml
[float]
[[deprecation-logging]]
==== Deprecation logging
Expand Down
Expand Up @@ -24,13 +24,16 @@

import org.apache.log4j.PropertyConfigurator;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.FailedToResolveConfigException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.EnumSet;
Expand All @@ -47,6 +50,8 @@ public class LogConfigurator {

static final List<String> ALLOWED_SUFFIXES = ImmutableList.of(".yml", ".yaml", ".json", ".properties");

static final String ES_LOGGING_SYSPROP = "es.logging";

private static boolean loaded;

private static ImmutableMap<String, String> replacements = new MapBuilder<String, String>()
Expand Down Expand Up @@ -121,7 +126,15 @@ public static void reset() {
public static void resolveConfig(Environment env, final Settings.Builder settingsBuilder) {

try {
Files.walkFileTree(env.configFile(), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
Path startingPath;
final String esLoggingDir = System.getProperty(ES_LOGGING_SYSPROP);
if (Strings.hasText(esLoggingDir)) {
startingPath = PathUtils.get(env.resolveConfig(esLoggingDir).toURI());
} else {
startingPath = env.configFile();
}

Files.walkFileTree(startingPath, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileName = file.getFileName().toString();
Expand All @@ -136,8 +149,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
return FileVisitResult.CONTINUE;
}
});
} catch (IOException ioe) {
throw new ElasticsearchException("Failed to load logging configuration", ioe);
} catch (IOException | URISyntaxException e) {
throw new ElasticsearchException("Failed to load logging configuration", e);
}
}

Expand Down
Expand Up @@ -24,17 +24,17 @@
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.FailedToResolveConfigException;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.*;

/**
*
Expand Down Expand Up @@ -148,7 +148,78 @@ public void testResolveConfigInvalidFilename() throws Exception {
LogConfigurator.resolveConfig(environment, builder);

Settings logSettings = builder.build();
assertThat(logSettings.get("yml"), Matchers.nullValue());
assertThat(logSettings.get("yml"), nullValue());
}

@Test
public void testResolveLoggingDirFromSystemProperty() throws Exception {
Path tempDir = createTempDir();
Path customLogConfig1 = tempDir.resolve(LoggingConfigurationTests.loggingConfiguration("yml"));
Files.write(customLogConfig1, "action: WARN".getBytes(StandardCharsets.UTF_8));
Path customLogConfig2 = tempDir.resolve(LoggingConfigurationTests.loggingConfiguration("yml"));
Files.write(customLogConfig2, "transport: TRACE".getBytes(StandardCharsets.UTF_8));
if (randomBoolean()) {
//gets ignored because the filename doesn't start with the "logging." prefix
Path ignoredLogConfig = tempDir.resolve("invalid_logging.yml");
Files.write(ignoredLogConfig, "invalid: TRACE".getBytes(StandardCharsets.UTF_8));
}
if (randomBoolean()) {
//gets ignored because the filename doesn't end with one of the allowed suffixes
Path ignoredLogConfig = tempDir.resolve("logging.unknown");
Files.write(ignoredLogConfig, "invalid: TRACE".getBytes(StandardCharsets.UTF_8));
}

try {
System.setProperty(LogConfigurator.ES_LOGGING_SYSPROP, tempDir.toString());
Environment environment = new Environment(Settings.EMPTY);
Settings.Builder builder = Settings.builder();
LogConfigurator.resolveConfig(environment, builder);

Settings logSettings = builder.build();
assertThat(logSettings.names().size(), equalTo(2));
assertThat(logSettings.get("action"), is("WARN"));
assertThat(logSettings.get("transport"), is("TRACE"));
assertThat(logSettings.get("invalid"), nullValue());
} finally {
System.clearProperty(LogConfigurator.ES_LOGGING_SYSPROP);
}
}

@Test
public void testResolveLoggingFileFromSystemProperty() throws Exception {
Path tempDir = createTempDir();
Path customLogConfig = tempDir.resolve(LoggingConfigurationTests.loggingConfiguration("yml"));
Files.write(customLogConfig, "action: WARN".getBytes(StandardCharsets.UTF_8));
if (randomBoolean()) {
//gets ignored because the sysprop points directly to the above file
Path ignoredLogConfig = tempDir.resolve(LoggingConfigurationTests.loggingConfiguration("yml"));
Files.write(ignoredLogConfig, "transport: TRACE".getBytes(StandardCharsets.UTF_8));
}

try {
System.setProperty(LogConfigurator.ES_LOGGING_SYSPROP, customLogConfig.toString());
Environment environment = new Environment(Settings.EMPTY);
Settings.Builder builder = Settings.builder();
LogConfigurator.resolveConfig(environment, builder);

Settings logSettings = builder.build();
assertThat(logSettings.names().size(), equalTo(1));
assertThat(logSettings.get("action"), is("WARN"));
} finally {
System.clearProperty(LogConfigurator.ES_LOGGING_SYSPROP);
}
}

@Test(expected = FailedToResolveConfigException.class)
public void testResolveNonExistingLoggingFileFromSystemProperty() throws IOException {
try {
System.setProperty(LogConfigurator.ES_LOGGING_SYSPROP, "non_existing.yml");
Environment environment = new Environment(Settings.builder().build());
Settings.Builder builder = Settings.builder();
LogConfigurator.resolveConfig(environment, builder);
} finally {
System.clearProperty(LogConfigurator.ES_LOGGING_SYSPROP);
}
}

private static String loggingConfiguration(String suffix) {
Expand Down

0 comments on commit 8c41df6

Please sign in to comment.