Skip to content

Commit 9f46aae

Browse files
authored
Consolidating logging initialization in cli launcher (#85920)
Serveral mechanisms exist for intializing logging in cli tools. Some base Command classes exist which initialize logging. But they do this late, when they are constructed, which may be after static init has occured for classes grabbing a Logger. Other CLIs like node tool explicitly initialize logging to avoid that problem. This commit removes all the of the LoggingAware classes, and unifies logging configuration to occur at the very beginning of the cli launcher. relates #85758
1 parent 7a99254 commit 9f46aae

File tree

25 files changed

+55
-155
lines changed

25 files changed

+55
-155
lines changed

distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/CliToolLauncher.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
package org.elasticsearch.launcher;
1010

11+
import org.apache.logging.log4j.Level;
1112
import org.elasticsearch.cli.CliToolProvider;
1213
import org.elasticsearch.cli.Command;
1314
import org.elasticsearch.cli.Terminal;
15+
import org.elasticsearch.common.logging.LogConfigurator;
16+
import org.elasticsearch.common.settings.Settings;
1417
import org.elasticsearch.core.SuppressForbidden;
1518

1619
import java.util.Map;
@@ -43,6 +46,10 @@ class CliToolLauncher {
4346
*/
4447
public static void main(String[] args) throws Exception {
4548
Map<String, String> sysprops = getSystemProperties();
49+
50+
// configure logging as early as possible
51+
configureLoggingWithoutConfig(sysprops);
52+
4653
String toolname = getToolName(sysprops);
4754
String libs = sysprops.getOrDefault("cli.libs", "");
4855

@@ -76,4 +83,15 @@ private static Map<String, String> getSystemProperties() {
7683
private static void exit(int status) {
7784
System.exit(status);
7885
}
86+
87+
/**
88+
* Configures logging without Elasticsearch configuration files based on the system property "es.logger.level" only. As such, any
89+
* logging will be written to the console.
90+
*/
91+
private static void configureLoggingWithoutConfig(Map<String, String> sysprops) {
92+
// initialize default for es.logger.level because we will not read the log4j2.properties
93+
final String loggerLevel = sysprops.getOrDefault("es.logger.level", Level.INFO.name());
94+
final Settings settings = Settings.builder().put("logger.level", loggerLevel).build();
95+
LogConfigurator.configureWithoutConfig(settings);
96+
}
7997
}

distribution/tools/geoip-cli/src/main/java/org/elasticsearch/geoip/GeoIpCli.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class GeoIpCli extends Command {
4747
private final OptionSpec<String> targetDirectory;
4848

4949
public GeoIpCli() {
50-
super("A CLI tool to prepare local GeoIp database service", () -> {});
50+
super("A CLI tool to prepare local GeoIp database service");
5151
sourceDirectory = parser.acceptsAll(Arrays.asList("s", "source"), "Source directory").withRequiredArg().required();
5252
targetDirectory = parser.acceptsAll(Arrays.asList("t", "target"), "Target directory").withRequiredArg();
5353

distribution/tools/keystore-cli/src/main/java/org/elasticsearch/cli/keystore/KeyStoreCli.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
package org.elasticsearch.cli.keystore;
1010

11-
import org.elasticsearch.common.cli.LoggingAwareMultiCommand;
11+
import org.elasticsearch.cli.MultiCommand;
1212

1313
/**
1414
* A cli tool for managing secrets in the elasticsearch keystore.
1515
*/
16-
class KeyStoreCli extends LoggingAwareMultiCommand {
16+
class KeyStoreCli extends MultiCommand {
1717

1818
KeyStoreCli() {
1919
super("A tool for managing settings stored in the elasticsearch keystore");

distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/PluginCli.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
package org.elasticsearch.plugins.cli;
1010

1111
import org.elasticsearch.cli.Command;
12-
import org.elasticsearch.common.cli.LoggingAwareMultiCommand;
12+
import org.elasticsearch.cli.MultiCommand;
1313
import org.elasticsearch.core.internal.io.IOUtils;
1414

1515
import java.io.IOException;
@@ -19,7 +19,7 @@
1919
/**
2020
* A cli tool for adding, removing and listing plugins for elasticsearch.
2121
*/
22-
class PluginCli extends LoggingAwareMultiCommand {
22+
class PluginCli extends MultiCommand {
2323

2424
private final Collection<Command> commands;
2525

libs/cli/src/main/java/org/elasticsearch/cli/Command.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public abstract class Command implements Closeable {
3333
/** A description of the command, used in the help output. */
3434
protected final String description;
3535

36-
private final Runnable beforeMain;
37-
3836
// these are the system properties and env vars from the environment,
3937
// but they can be overriden by tests. Really though Command should be stateless,
4038
// so the signature of main should take them in, which can happen once the entrypoint
@@ -52,13 +50,11 @@ public abstract class Command implements Closeable {
5250

5351
/**
5452
* Construct the command with the specified command description and runnable to execute before main is invoked.
53+
* @param description the command description
5554
*
56-
* @param description the command description
57-
* @param beforeMain the before-main runnable
5855
*/
59-
public Command(final String description, final Runnable beforeMain) {
56+
public Command(final String description) {
6057
this.description = description;
61-
this.beforeMain = beforeMain;
6258
this.sysprops = captureSystemProperties();
6359
this.envVars = captureEnvironmentVariables();
6460
}
@@ -86,8 +82,6 @@ public final int main(String[] args, Terminal terminal) throws Exception {
8682
Runtime.getRuntime().addShutdownHook(shutdownHookThread);
8783
}
8884

89-
beforeMain.run();
90-
9185
try {
9286
mainWithoutErrorHandling(args, terminal);
9387
} catch (OptionException e) {

libs/cli/src/main/java/org/elasticsearch/cli/MultiCommand.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@ public class MultiCommand extends Command {
3434

3535
/**
3636
* Construct the multi-command with the specified command description and runnable to execute before main is invoked.
37+
* @param description the multi-command description
3738
*
38-
* @param description the multi-command description
39-
* @param beforeMain the before-main runnable
4039
*/
41-
public MultiCommand(final String description, final Runnable beforeMain) {
42-
super(description, beforeMain);
40+
public MultiCommand(final String description) {
41+
super(description);
4342
this.settingOption = parser.accepts("E", "Configure a setting").withRequiredArg().ofType(KeyValuePair.class);
4443
parser.posixlyCorrect(true);
4544
}

qa/evil-tests/src/test/java/org/elasticsearch/cli/EvilCommandTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class EvilCommandTests extends ESTestCase {
2424
public void testCommandShutdownHook() throws Exception {
2525
final AtomicBoolean closed = new AtomicBoolean();
2626
final boolean shouldThrow = randomBoolean();
27-
final Command command = new Command("test-command-shutdown-hook", () -> {}) {
27+
final Command command = new Command("test-command-shutdown-hook") {
2828
@Override
2929
protected void execute(Terminal terminal, OptionSet options) throws Exception {
3030

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Elasticsearch extends EnvironmentAwareCommand {
4242

4343
// visible for testing
4444
Elasticsearch() {
45-
super("Starts Elasticsearch", () -> {}); // we configure logging later so we override the base class from configuring logging
45+
super("Starts Elasticsearch"); // we configure logging later so we override the base class from configuring logging
4646
versionOption = parser.acceptsAll(Arrays.asList("V", "version"), "Prints Elasticsearch version information and exits");
4747
daemonizeOption = parser.acceptsAll(Arrays.asList("d", "daemonize"), "Starts Elasticsearch in the background")
4848
.availableUnless(versionOption);

server/src/main/java/org/elasticsearch/cluster/coordination/NodeToolCli.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,13 @@
88
package org.elasticsearch.cluster.coordination;
99

1010
import org.elasticsearch.cli.MultiCommand;
11-
import org.elasticsearch.common.cli.CommandLoggingConfigurator;
1211
import org.elasticsearch.env.NodeRepurposeCommand;
1312
import org.elasticsearch.env.OverrideNodeVersionCommand;
1413

15-
// NodeToolCli does not extend LoggingAwareCommand, because LoggingAwareCommand performs logging initialization
16-
// after LoggingAwareCommand instance is constructed.
17-
// It's too late for us, because before UnsafeBootstrapMasterCommand is added to the list of subcommands
18-
// log4j2 initialization will happen, because it has static reference to Logger class.
19-
// Even if we avoid making a static reference to Logger class, there is no nice way to avoid declaring
20-
// UNSAFE_BOOTSTRAP, which depends on ClusterService, which in turn has static Logger.
21-
// TODO execute CommandLoggingConfigurator.configureLoggingWithoutConfig() in the constructor of commands, not in beforeMain
2214
class NodeToolCli extends MultiCommand {
2315

2416
NodeToolCli() {
25-
super("A CLI tool to do unsafe cluster and index manipulations on current node", () -> {});
26-
CommandLoggingConfigurator.configureLoggingWithoutConfig();
17+
super("A CLI tool to do unsafe cluster and index manipulations on current node");
2718
subcommands.put("repurpose", new NodeRepurposeCommand());
2819
subcommands.put("unsafe-bootstrap", new UnsafeBootstrapMasterCommand());
2920
subcommands.put("detach-cluster", new DetachClusterCommand());

server/src/main/java/org/elasticsearch/common/cli/CommandLoggingConfigurator.java

Lines changed: 0 additions & 32 deletions
This file was deleted.

server/src/main/java/org/elasticsearch/common/cli/EnvironmentAwareCommand.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,7 @@ public abstract class EnvironmentAwareCommand extends Command {
3939
* @param description the command description
4040
*/
4141
public EnvironmentAwareCommand(final String description) {
42-
this(description, CommandLoggingConfigurator::configureLoggingWithoutConfig);
43-
}
44-
45-
/**
46-
* Construct the command with the specified command description and runnable to execute before main is invoked. Commands constructed
47-
* with this constructor must take ownership of configuring logging.
48-
*
49-
* @param description the command description
50-
* @param beforeMain the before-main runnable
51-
*/
52-
public EnvironmentAwareCommand(final String description, final Runnable beforeMain) {
53-
super(description, beforeMain);
42+
super(description);
5443
this.settingOption = parser.accepts("E", "Configure a setting").withRequiredArg().ofType(KeyValuePair.class);
5544
}
5645

server/src/main/java/org/elasticsearch/common/cli/LoggingAwareCommand.java

Lines changed: 0 additions & 29 deletions
This file was deleted.

server/src/main/java/org/elasticsearch/common/cli/LoggingAwareMultiCommand.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

server/src/main/java/org/elasticsearch/index/shard/ShardToolCli.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
*/
88
package org.elasticsearch.index.shard;
99

10-
import org.elasticsearch.common.cli.LoggingAwareMultiCommand;
10+
import org.elasticsearch.cli.MultiCommand;
1111

1212
/**
1313
* Class encapsulating and dispatching commands from the {@code elasticsearch-shard} command line tool
1414
*/
15-
class ShardToolCli extends LoggingAwareMultiCommand {
15+
class ShardToolCli extends MultiCommand {
1616

1717
ShardToolCli() {
1818
super("A CLI tool to remove corrupted parts of unrecoverable shards");

server/src/test/java/org/elasticsearch/cli/CommandTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static class DummyCommand extends Command {
3434
Exception exception = null;
3535

3636
DummyCommand() {
37-
super("Does nothing", () -> {});
37+
super("Does nothing");
3838
}
3939

4040
@Override

server/src/test/java/org/elasticsearch/cli/MultiCommandTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static class DummyMultiCommand extends MultiCommand {
3030
final AtomicBoolean closed = new AtomicBoolean();
3131

3232
DummyMultiCommand() {
33-
super("A dummy multi command", () -> {});
33+
super("A dummy multi command");
3434
}
3535

3636
@Override
@@ -56,7 +56,7 @@ static class DummySubCommand extends Command {
5656
}
5757

5858
DummySubCommand(final boolean throwsExceptionOnClose) {
59-
super("A dummy subcommand", () -> {});
59+
super("A dummy subcommand");
6060
this.throwsExceptionOnClose = throwsExceptionOnClose;
6161
}
6262

@@ -203,7 +203,7 @@ public void testCloseWhenSubCommandCloseThrowsException() throws Exception {
203203

204204
static class ErrorThrowingSubCommand extends Command {
205205
ErrorThrowingSubCommand() {
206-
super("error throwing", () -> {});
206+
super("error throwing");
207207
}
208208

209209
@Override

x-pack/license-tools/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
import joptsimple.OptionSet;
1010
import joptsimple.OptionSpec;
1111

12+
import org.elasticsearch.cli.Command;
1213
import org.elasticsearch.cli.ExitCodes;
1314
import org.elasticsearch.cli.Terminal;
1415
import org.elasticsearch.cli.UserException;
15-
import org.elasticsearch.common.cli.LoggingAwareCommand;
1616
import org.elasticsearch.core.PathUtils;
1717
import org.elasticsearch.core.SuppressForbidden;
1818

@@ -24,7 +24,7 @@
2424

2525
import static org.elasticsearch.license.CryptUtils.writeEncryptedPrivateKey;
2626

27-
public class KeyPairGeneratorTool extends LoggingAwareCommand {
27+
public class KeyPairGeneratorTool extends Command {
2828

2929
private final OptionSpec<String> publicKeyPathOption;
3030
private final OptionSpec<String> privateKeyPathOption;

x-pack/license-tools/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
import joptsimple.OptionSet;
1010
import joptsimple.OptionSpec;
1111

12+
import org.elasticsearch.cli.Command;
1213
import org.elasticsearch.cli.ExitCodes;
1314
import org.elasticsearch.cli.Terminal;
1415
import org.elasticsearch.cli.UserException;
1516
import org.elasticsearch.common.Strings;
1617
import org.elasticsearch.common.bytes.BytesArray;
17-
import org.elasticsearch.common.cli.LoggingAwareCommand;
1818
import org.elasticsearch.core.PathUtils;
1919
import org.elasticsearch.core.SuppressForbidden;
2020
import org.elasticsearch.license.License;
@@ -28,7 +28,7 @@
2828
import java.nio.file.Files;
2929
import java.nio.file.Path;
3030

31-
public class LicenseGeneratorTool extends LoggingAwareCommand {
31+
public class LicenseGeneratorTool extends Command {
3232

3333
private final OptionSpec<String> publicKeyPathOption;
3434
private final OptionSpec<String> privateKeyPathOption;

0 commit comments

Comments
 (0)