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:
parent
9ae5410ea6
commit
fc3280b3cf
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue