Skip to content

Commit

Permalink
Add quiet option to disable console logging (#20422)
Browse files Browse the repository at this point in the history
This commit adds a -q/--quiet option to Elasticsearch so that it does not log anything in the console and closes stdout & stderr streams. This is useful for SystemD to avoid duplicate logs in both journalctl and /var/log/elasticsearch/elasticsearch.log while still allows the JVM to print error messages in stdout/stderr if needed.

closes #17220

(cherry picked from commit 6090c51)
  • Loading branch information
tlrx committed Sep 13, 2016
1 parent 29c721e commit ffbf7d3
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 29 deletions.
4 changes: 2 additions & 2 deletions TESTING.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ These are the linux flavors the Vagrantfile currently supports:
* debian-8 aka jessie, the current debian stable distribution
* centos-6
* centos-7
* fedora-22
* fedora-24
* oel-6 aka Oracle Enterprise Linux 6
* oel-7 aka Oracle Enterprise Linux 7
* sles-12
* opensuse-13
Expand All @@ -377,7 +378,6 @@ We're missing the following from the support matrix because there aren't high
quality boxes available in vagrant atlas:

* sles-11
* oel-6

We're missing the follow because our tests are very linux/bash centric:

Expand Down
9 changes: 5 additions & 4 deletions core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,12 @@ static void initLoggerPrefix() {
}

/**
* This method is invoked by {@link Elasticsearch#main(String[])}
* to startup elasticsearch.
* This method is invoked by {@link Elasticsearch#main(String[])} to startup elasticsearch.
*/
static void init(
final boolean foreground,
final Path pidFile,
final boolean quiet,
final Map<String, String> esSettings) throws BootstrapException, NodeValidationException {
// Set the system property before anything has a chance to trigger its use
initLoggerPrefix();
Expand All @@ -259,8 +259,9 @@ static void init(
}
}

final boolean closeStandardStreams = (foreground == false) || quiet;
try {
if (!foreground) {
if (closeStandardStreams) {
final Logger rootLogger = ESLoggerFactory.getRootLogger();
final Appender maybeConsoleAppender = Loggers.findAppender(rootLogger, ConsoleAppender.class);
if (maybeConsoleAppender != null) {
Expand All @@ -285,7 +286,7 @@ static void init(

INSTANCE.start();

if (!foreground) {
if (closeStandardStreams) {
closeSysError();
}
} catch (NodeValidationException | RuntimeException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* Wrapper exception for checked exceptions thrown during the bootstrap process. Methods invoked
* during bootstrap should explicitly declare the checked exceptions that they can throw, rather
* than declaring the top-level checked exception {@link Exception}. This exception exists to wrap
* these checked exceptions so that {@link Bootstrap#init(boolean, Path, Map)} does not have to
* these checked exceptions so that {@link Bootstrap#init(boolean, Path, boolean, Map)} does not have to
* declare all of these checked exceptions.
*/
class BootstrapException extends Exception {
Expand Down
13 changes: 10 additions & 3 deletions core/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Elasticsearch extends SettingCommand {
private final OptionSpecBuilder versionOption;
private final OptionSpecBuilder daemonizeOption;
private final OptionSpec<Path> pidfileOption;
private final OptionSpecBuilder quietOption;

// visible for testing
Elasticsearch() {
Expand All @@ -58,6 +59,10 @@ class Elasticsearch extends SettingCommand {
.availableUnless(versionOption)
.withRequiredArg()
.withValuesConvertedBy(new PathConverter());
quietOption = parser.acceptsAll(Arrays.asList("q", "quiet"),
"Turns off standard ouput/error streams logging in console")
.availableUnless(versionOption)
.availableUnless(daemonizeOption);
}

/**
Expand Down Expand Up @@ -92,17 +97,19 @@ protected void execute(Terminal terminal, OptionSet options, Map<String, String>

final boolean daemonize = options.has(daemonizeOption);
final Path pidFile = pidfileOption.value(options);
final boolean quiet = options.has(quietOption);

try {
init(daemonize, pidFile, settings);
init(daemonize, pidFile, quiet, settings);
} catch (NodeValidationException e) {
throw new UserException(ExitCodes.CONFIG, e.getMessage());
}
}

void init(final boolean daemonize, final Path pidFile, final Map<String, String> esSettings) throws NodeValidationException {
void init(final boolean daemonize, final Path pidFile, final boolean quiet, final Map<String, String> esSettings)
throws NodeValidationException {
try {
Bootstrap.init(!daemonize, pidFile, esSettings);
Bootstrap.init(!daemonize, pidFile, quiet, esSettings);
} catch (BootstrapException | RuntimeException e) {
// format exceptions to the console in a special way
// to avoid 2MB stacktraces from guice, etc.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public void testVersion() throws Exception {
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "--daemonize");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "-p", "/tmp/pid");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "--pidfile", "/tmp/pid");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "-q");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "--quiet");

runTestThatVersionIsReturned("-V");
runTestThatVersionIsReturned("--version");
}
Expand All @@ -66,29 +69,29 @@ private void runTestThatVersionIsReturned(String... args) throws Exception {
}

private void runTestVersion(int expectedStatus, Consumer<String> outputConsumer, String... args) throws Exception {
runTest(expectedStatus, false, outputConsumer, (foreground, pidFile, esSettings) -> {}, args);
runTest(expectedStatus, false, outputConsumer, (foreground, pidFile, quiet, esSettings) -> {}, args);
}

public void testPositionalArgs() throws Exception {
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Positional arguments not allowed, found [foo]")),
(foreground, pidFile, esSettings) -> {},
(foreground, pidFile, quiet, esSettings) -> {},
"foo"
);
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Positional arguments not allowed, found [foo, bar]")),
(foreground, pidFile, esSettings) -> {},
(foreground, pidFile, quiet, esSettings) -> {},
"foo", "bar"
);
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Positional arguments not allowed, found [foo]")),
(foreground, pidFile, esSettings) -> {},
(foreground, pidFile, quiet, esSettings) -> {},
"-E", "foo=bar", "foo", "-E", "baz=qux"
);
}
Expand All @@ -109,7 +112,7 @@ private void runPidFileTest(final int expectedStatus, final boolean expectedInit
expectedStatus,
expectedInit,
outputConsumer,
(foreground, pidFile, esSettings) -> assertThat(pidFile.toString(), equalTo(expectedPidFile.toString())),
(foreground, pidFile, quiet, esSettings) -> assertThat(pidFile.toString(), equalTo(expectedPidFile.toString())),
args);
}

Expand All @@ -124,7 +127,22 @@ private void runDaemonizeTest(final boolean expectedDaemonize, final String... a
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> assertThat(foreground, equalTo(!expectedDaemonize)),
(foreground, pidFile, quiet, esSettings) -> assertThat(foreground, equalTo(!expectedDaemonize)),
args);
}

public void testThatParsingQuietOptionWorks() throws Exception {
runQuietTest(true, "-q");
runQuietTest(true, "--quiet");
runQuietTest(false);
}

private void runQuietTest(final boolean expectedQuiet, final String... args) throws Exception {
runTest(
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, quiet, esSettings) -> assertThat(quiet, equalTo(expectedQuiet)),
args);
}

Expand All @@ -133,7 +151,7 @@ public void testElasticsearchSettings() throws Exception {
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> {
(foreground, pidFile, quiet, esSettings) -> {
assertThat(esSettings.size(), equalTo(2));
assertThat(esSettings, hasEntry("foo", "bar"));
assertThat(esSettings, hasEntry("baz", "qux"));
Expand All @@ -147,7 +165,7 @@ public void testElasticsearchSettingCanNotBeEmpty() throws Exception {
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Setting [foo] must not be empty")),
(foreground, pidFile, esSettings) -> {},
(foreground, pidFile, quiet, esSettings) -> {},
"-E", "foo="
);
}
Expand All @@ -157,7 +175,7 @@ public void testUnknownOption() throws Exception {
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("network.host is not a recognized option")),
(foreground, pidFile, esSettings) -> {},
(foreground, pidFile, quiet, esSettings) -> {},
"--network.host");
}

Expand Down
7 changes: 7 additions & 0 deletions distribution/src/main/packaging/systemd/elasticsearch.service
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec

ExecStart=/usr/share/elasticsearch/bin/elasticsearch \
-p ${PID_DIR}/elasticsearch.pid \
--quiet \
-Edefault.path.logs=${LOG_DIR} \
-Edefault.path.data=${DATA_DIR} \
-Edefault.path.conf=${CONF_DIR}

# StandardOutput is configured to redirect to journalctl since
# some error messages may be logged in standard output before
# elasticsearch logging system is initialized. Elasticsearch
# stores its logs in /var/log/elasticsearch and does not use
# journalctl by default. If you also want to enable journalctl
# logging, you can simply remove the "quiet" option from ExecStart.
StandardOutput=journal
StandardError=inherit

Expand Down
29 changes: 26 additions & 3 deletions docs/reference/setup/install/systemd.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,36 @@ sudo systemctl stop elasticsearch.service
--------------------------------------------

These commands provide no feedback as to whether Elasticsearch was started
successfully or not. Instead, this information will be written to the
`systemd` journal, which can be tailed as follows:
successfully or not. Instead, this information will be written in the log
files located in `/var/log/elasticsearch/`.

By default the Elasticsearch service doesn't log information in the `systemd`
journal. To enable `journalctl` logging, the `--quiet` option must be removed
from the `ExecStart` command line in the `elasticsearch.service` file.

When `systemd` logging is enabled, the logging information are available using
the `journalctl` commands:

To tail the journal:

[source,sh]
--------------------------------------------
sudo journalctl -f
--------------------------------------------

Log files can be found in `/var/log/elasticsearch/`.
To list journal entries for the elasticsearch service:

[source,sh]
--------------------------------------------
sudo journalctl --unit elasticsearch
--------------------------------------------

To list journal entries for the elasticsearch service starting from a given time:

[source,sh]
--------------------------------------------
sudo journalctl --unit elasticsearch --since "2016-10-30 18:17:16"
--------------------------------------------

Check `man journalctl` or https://www.freedesktop.org/software/systemd/man/journalctl.html for
more command line options.
7 changes: 5 additions & 2 deletions docs/reference/setup/install/zip-targz.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ Elasticsearch can be started from the command line as follows:
./bin/elasticsearch
--------------------------------------------

By default, Elasticsearch runs in the foreground, prints its logs to `STDOUT`,
and can be stopped by pressing `Ctrl-C`.
By default, Elasticsearch runs in the foreground, prints its logs to the
standard output (`stdout`), and can be stopped by pressing `Ctrl-C`.

include::check-running.asciidoc[]

Log printing to `stdout` can be disabled using the `-q` or `--quiet`
option on the command line.

[[setup-installation-daemon]]
==== Running as a daemon

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void testPathHome() throws Exception {
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> {
(foreground, pidFile, quiet, esSettings) -> {
assertThat(esSettings.size(), equalTo(1));
assertThat(esSettings, hasEntry("path.home", value));
});
Expand All @@ -49,7 +49,7 @@ public void testPathHome() throws Exception {
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> {
(foreground, pidFile, quiet, esSettings) -> {
assertThat(esSettings.size(), equalTo(1));
assertThat(esSettings, hasEntry("path.home", commandLineValue));
},
Expand Down
15 changes: 15 additions & 0 deletions qa/vagrant/src/test/resources/packaging/scripts/60_systemd.bats
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,24 @@ setup() {
# starting Elasticsearch so we don't have to wait for elasticsearch to scan for
# them.
install_elasticsearch_test_scripts

# Capture the current epoch in millis
run date +%s
epoch="$output"

systemctl start elasticsearch.service
wait_for_elasticsearch_status
assert_file_exist "/var/run/elasticsearch/elasticsearch.pid"
assert_file_exist "/var/log/elasticsearch/elasticsearch.log"

# Converts the epoch back in a human readable format
run date --date=@$epoch "+%Y-%m-%d %H:%M:%S"
since="$output"

# Verifies that no new entries in journald have been added
# since the last start
run journalctl _SYSTEMD_UNIT=elasticsearch.service --since "$since"
[ "$status" -eq 1 ]
}

@test "[SYSTEMD] start (running)" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
abstract class ESElasticsearchCliTestCase extends ESTestCase {

interface InitConsumer {
void accept(final boolean foreground, final Path pidFile, final Map<String, String> esSettings);
void accept(final boolean foreground, final Path pidFile, final boolean quiet, final Map<String, String> esSettings);
}

void runTest(
Expand All @@ -46,9 +46,9 @@ void runTest(
final AtomicBoolean init = new AtomicBoolean();
final int status = Elasticsearch.main(args, new Elasticsearch() {
@Override
void init(final boolean daemonize, final Path pidFile, final Map<String, String> esSettings) {
void init(final boolean daemonize, final Path pidFile, final boolean quiet, final Map<String, String> esSettings) {
init.set(true);
initConsumer.accept(!daemonize, pidFile, esSettings);
initConsumer.accept(!daemonize, pidFile, quiet, esSettings);
}
}, terminal);
assertThat(status, equalTo(expectedStatus));
Expand Down

0 comments on commit ffbf7d3

Please sign in to comment.