Expose logs base path

For certain situations, end-users need the base path for Elasticsearch
logs. Exposing this as a property is better than hard-coding the path
into the logging configuration file as otherwise the logging
configuration file could easily diverge from the Elasticsearch
configuration file. Additionally, Elasticsearch will only have
permissions to write to the log directory configured in the
Elasticsearch configuration file. This commit adds a property that
exposes this base path.

One use-case for this is configuring a rollover strategy to retain logs
for a certain period of time. As such, we add an example of this to the
documentation.

Additionally, we expose the property es.logs.cluster_name as this is
used as the name of the log files in the default configuration.

Finally, we expose es.logs.node_name in cases where node.name is
explicitly set in case users want to include the node name as part of
the name of the log files.

Relates #22625
This commit is contained in:
Jason Tedor 2017-01-16 07:39:37 -05:00 committed by GitHub
parent 9ae5410ea6
commit fc3280b3cf
8 changed files with 127 additions and 31 deletions

View File

@ -36,6 +36,7 @@ import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.Node;
import java.io.IOException;
import java.nio.file.FileVisitOption;
@ -97,7 +98,7 @@ public class LogConfigurator {
final Set<FileVisitOption> options = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
Files.walkFileTree(configsPath, options, Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
if (file.getFileName().toString().equals("log4j2.properties")) {
configurations.add((PropertiesConfiguration) factory.getConfiguration(context, file.toString(), file.toUri()));
}
@ -143,9 +144,32 @@ public class LogConfigurator {
}
}
/**
* Set system properties that can be used in configuration files to specify paths and file patterns for log files. We expose three
* properties here:
* <ul>
* <li>
* {@code es.logs.base_path} the base path containing the log files
* </li>
* <li>
* {@code es.logs.cluster_name} the cluster name, used as the prefix of log filenames in the default configuration
* </li>
* <li>
* {@code es.logs.node_name} the node name, can be used as part of log filenames (only exposed if {@link Node#NODE_NAME_SETTING} is
* explicitly set)
* </li>
* </ul>
*
* @param logsPath the path to the log files
* @param settings the settings to extract the cluster and node names
*/
@SuppressForbidden(reason = "sets system property for logging configuration")
private static void setLogConfigurationSystemProperty(final Path logsPath, final Settings settings) {
System.setProperty("es.logs", logsPath.resolve(ClusterName.CLUSTER_NAME_SETTING.get(settings).value()).toString());
System.setProperty("es.logs.base_path", logsPath.toString());
System.setProperty("es.logs.cluster_name", ClusterName.CLUSTER_NAME_SETTING.get(settings).value());
if (Node.NODE_NAME_SETTING.exists(settings)) {
System.setProperty("es.logs.node_name", Node.NODE_NAME_SETTING.get(settings));
}
}
}

View File

@ -11,10 +11,10 @@ appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
appender.rolling.type = RollingFile
appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs}.log
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
appender.rolling.filePattern = ${sys:es.logs}-%d{yyyy-MM-dd}.log
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1
@ -26,10 +26,10 @@ rootLogger.appenderRef.rolling.ref = rolling
appender.deprecation_rolling.type = RollingFile
appender.deprecation_rolling.name = deprecation_rolling
appender.deprecation_rolling.fileName = ${sys:es.logs}_deprecation.log
appender.deprecation_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_rolling.layout.type = PatternLayout
appender.deprecation_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
appender.deprecation_rolling.filePattern = ${sys:es.logs}_deprecation-%i.log.gz
appender.deprecation_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation-%i.log.gz
appender.deprecation_rolling.policies.type = Policies
appender.deprecation_rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.deprecation_rolling.policies.size.size = 1GB
@ -43,10 +43,10 @@ logger.deprecation.additivity = false
appender.index_search_slowlog_rolling.type = RollingFile
appender.index_search_slowlog_rolling.name = index_search_slowlog_rolling
appender.index_search_slowlog_rolling.fileName = ${sys:es.logs}_index_search_slowlog.log
appender.index_search_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog.log
appender.index_search_slowlog_rolling.layout.type = PatternLayout
appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_search_slowlog_rolling.filePattern = ${sys:es.logs}_index_search_slowlog-%d{yyyy-MM-dd}.log
appender.index_search_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog-%d{yyyy-MM-dd}.log
appender.index_search_slowlog_rolling.policies.type = Policies
appender.index_search_slowlog_rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.index_search_slowlog_rolling.policies.time.interval = 1
@ -59,10 +59,10 @@ logger.index_search_slowlog_rolling.additivity = false
appender.index_indexing_slowlog_rolling.type = RollingFile
appender.index_indexing_slowlog_rolling.name = index_indexing_slowlog_rolling
appender.index_indexing_slowlog_rolling.fileName = ${sys:es.logs}_index_indexing_slowlog.log
appender.index_indexing_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog.log
appender.index_indexing_slowlog_rolling.layout.type = PatternLayout
appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_indexing_slowlog_rolling.filePattern = ${sys:es.logs}_index_indexing_slowlog-%d{yyyy-MM-dd}.log
appender.index_indexing_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog-%d{yyyy-MM-dd}.log
appender.index_indexing_slowlog_rolling.policies.type = Policies
appender.index_indexing_slowlog_rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.index_indexing_slowlog_rolling.policies.time.interval = 1

View File

@ -112,22 +112,30 @@ command line with `es.node.name` or in the config file with `node.name`.
Elasticsearch uses http://logging.apache.org/log4j/2.x/[Log4j 2] for
logging. Log4j 2 can be configured using the log4j2.properties
file. Elasticsearch exposes a single property `${sys:es.logs}` that can be
referenced in the configuration file to determine the location of the log files;
this will resolve to a prefix for the Elasticsearch log file at runtime.
file. Elasticsearch exposes three properties, `${sys:es.logs.base_path},
`${sys:es.logs.cluster_name}`, and `${sys:es.logs.node_name} (if the node name
is explicitly set via `node.name`) that can be referenced in the configuration
file to determine the location of the log files. The property
`${sys:es.logs.base_path}` will resolve to the log directory,
`${sys:es.logs.cluster_name}` will resolve to the cluster name (used as the
prefix of log filenames in the default configuration), and
`${sys:es.logs.node_name}` will resolve to the node name (if the node name is
explicitly set).
For example, if your log directory (`path.logs`) is `/var/log/elasticsearch` and
your cluster is named `production` then `${sys:es.logs}` will resolve to
`/var/log/elasticsearch/production`.
your cluster is named `production` then `${sys:es.logs.base_path}` will resolve
to `/var/log/elasticsearch` and
`${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log`
will resolve to `/var/log/elasticsearch/production.log`.
[source,properties]
--------------------------------------------------
appender.rolling.type = RollingFile <1>
appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs}.log <2>
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log <2>
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
appender.rolling.filePattern = ${sys:es.logs}-%d{yyyy-MM-dd}.log <3>
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log <3>
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy <4>
appender.rolling.policies.time.interval = 1 <5>
@ -145,6 +153,31 @@ appender.rolling.policies.time.modulate = true <6>
If you append `.gz` or `.zip` to `appender.rolling.filePattern`, then the logs
will be compressed as they are rolled.
If you want to retain log files for a specified period of time, you can use a
rollover strategy with a delete action.
[source,properties]
--------------------------------------------------
appender.rolling.strategy.type = DefaultRolloverStrategy <1>
appender.rolling.strategy.action.type = Delete <2>
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path} <3>
appender.rolling.strategy.action.condition.type = IfLastModified <4>
appender.rolling.strategy.action.condition.age = 7D <5>
appender.rolling.strategy.action.PathConditions.type = IfFileName <6>
appender.rolling.strategy.action.PathConditions.glob = ${sys:es.logs.cluster_name}-* <7>
--------------------------------------------------
<1> Configure the `DefaultRolloverStrategy`
<2> Configure the `Delete` action for handling rollovers
<3> The base path to the Elasticsearch logs
<4> The condition to apply when handling rollovers
<5> Retain logs for seven days
<6> Only delete files older than seven days if they match the specified glob
<7> Delete files from the base path matching the glob
`${sys:es.logs.cluster_name}-*`; this is the glob that log files are rolled
to; this is needed to only delete the rolled Elasticsearch logs but not also
delete the deprecation and slow logs
Multiple configuration files can be loaded (in which case they will get merged)
as long as they are named `log4j2.properties` and have the Elasticsearch config
directory as an ancestor; this is useful for plugins that expose additional

View File

@ -29,9 +29,11 @@ import org.apache.logging.log4j.core.appender.CountingNoOpAppender;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.elasticsearch.cli.UserException;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.Node;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.hamcrest.RegexMatcher;
@ -70,7 +72,11 @@ public class EvilLoggerTests extends ESTestCase {
testLogger.info("This is an info message");
testLogger.debug("This is a debug message");
testLogger.trace("This is a trace message");
final String path = System.getProperty("es.logs") + ".log";
final String path =
System.getProperty("es.logs.base_path") +
System.getProperty("file.separator") +
System.getProperty("es.logs.cluster_name") +
".log";
final List<String> events = Files.readAllLines(PathUtils.get(path));
assertThat(events.size(), equalTo(5));
final String location = "org.elasticsearch.common.logging.EvilLoggerTests.testLocationInfoTest";
@ -88,7 +94,11 @@ public class EvilLoggerTests extends ESTestCase {
final DeprecationLogger deprecationLogger = new DeprecationLogger(ESLoggerFactory.getLogger("deprecation"));
deprecationLogger.deprecated("This is a deprecation message");
final String deprecationPath = System.getProperty("es.logs") + "_deprecation.log";
final String deprecationPath =
System.getProperty("es.logs.base_path") +
System.getProperty("file.separator") +
System.getProperty("es.logs.cluster_name") +
"_deprecation.log";
final List<String> deprecationEvents = Files.readAllLines(PathUtils.get(deprecationPath));
assertThat(deprecationEvents.size(), equalTo(1));
assertLogLine(
@ -123,7 +133,11 @@ public class EvilLoggerTests extends ESTestCase {
final Exception e = new Exception("exception");
logger.info(new ParameterizedMessage("{}", "test"), e);
final String path = System.getProperty("es.logs") + ".log";
final String path =
System.getProperty("es.logs.base_path") +
System.getProperty("file.separator") +
System.getProperty("es.logs.cluster_name") +
".log";
final List<String> events = Files.readAllLines(PathUtils.get(path));
final StringWriter sw = new StringWriter();
@ -141,14 +155,39 @@ public class EvilLoggerTests extends ESTestCase {
}
}
public void testProperties() throws IOException, UserException {
final Settings.Builder builder = Settings.builder().put("cluster.name", randomAsciiOfLength(16));
if (randomBoolean()) {
builder.put("node.name", randomAsciiOfLength(16));
}
final Settings settings = builder.build();
setupLogging("minimal", settings);
assertNotNull(System.getProperty("es.logs.base_path"));
assertThat(System.getProperty("es.logs.cluster_name"), equalTo(ClusterName.CLUSTER_NAME_SETTING.get(settings).value()));
if (Node.NODE_NAME_SETTING.exists(settings)) {
assertThat(System.getProperty("es.logs.node_name"), equalTo(Node.NODE_NAME_SETTING.get(settings)));
} else {
assertNull(System.getProperty("es.logs.node_name"));
}
}
private void setupLogging(final String config) throws IOException, UserException {
setupLogging(config, Settings.EMPTY);
}
private void setupLogging(final String config, final Settings settings) throws IOException, UserException {
assert !Environment.PATH_CONF_SETTING.exists(settings);
assert !Environment.PATH_HOME_SETTING.exists(settings);
final Path configDir = getDataPath(config);
// need to set custom path.conf so we can use a custom log4j2.properties file for the test
final Settings settings = Settings.builder()
final Settings mergedSettings = Settings.builder()
.put(settings)
.put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
.build();
final Environment environment = new Environment(settings);
final Environment environment = new Environment(mergedSettings);
LogConfigurator.configure(environment);
}

View File

@ -5,7 +5,7 @@ appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs}.log
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
@ -21,7 +21,7 @@ logger.test.additivity = false
appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs}_deprecation.log
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n

View File

@ -5,7 +5,7 @@ appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs}.log
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
@ -15,7 +15,7 @@ rootLogger.appenderRef.file.ref = file
appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs}_deprecation.log
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n

View File

@ -5,7 +5,7 @@ appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs}.log
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n

View File

@ -5,7 +5,7 @@ appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs}.log
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = %marker%m%n