Skip to content

Commit

Permalink
Prints configuration overview (hyperledger#4451)
Browse files Browse the repository at this point in the history
* print configuration overview at startup

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
  • Loading branch information
daniellehrner authored Nov 22, 2022
1 parent 376ce82 commit 49f32ca
Show file tree
Hide file tree
Showing 21 changed files with 500 additions and 52 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Shanghai implementation of EIP-3540 and EIP-3670 Ethereum Object Format and Code Validation [#4644](https://github.com/hyperledger/besu/pull/4644)
- Remove some log statements that are keeping some objects live in heap for a long time, to reduce the amount of memory required during initial sync [#4705](https://github.com/hyperledger/besu/pull/4705)
- Add field `type` to Transaction receipt object (eth_getTransactionReceipt) [#4505](https://github.com/hyperledger/besu/issues/4505)
- Print an overview of configuration and system information at startup [#4451](https://github.com/hyperledger/besu/pull/4451)

### Bug Fixes

Expand Down
1 change: 1 addition & 0 deletions besu/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {

implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8'
implementation 'com.github.oshi:oshi-core'
implementation 'com.google.guava:guava'
implementation 'com.graphql-java:graphql-java'
implementation 'info.picocli:picocli'
Expand Down
54 changes: 45 additions & 9 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider;
private GenesisConfigOptions genesisConfigOptions;

private RocksDBPlugin rocksDBPlugin;

// CLI options defined by user at runtime.
// Options parsing is done with CLI library Picocli https://picocli.info/

Expand Down Expand Up @@ -1414,13 +1416,14 @@ public void run() {
setMergeConfigOptions();

instantiateSignatureAlgorithmFactory();
configureNativeLibs();
logger.info("Starting Besu version: {}", BesuInfo.nodeName(identityString));

logger.info("Starting Besu");
// Need to create vertx after cmdline has been parsed, such that metricsSystem is configurable
vertx = createVertx(createVertxOptions(metricsSystem.get()));

validateOptions();
configure();
configureNativeLibs();
initController();

besuPluginContext.beforeExternalServices();
Expand Down Expand Up @@ -1544,7 +1547,8 @@ private void preparePlugins() {
besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl);

// register built-in plugins
new RocksDBPlugin().register(besuPluginContext);
rocksDBPlugin = new RocksDBPlugin();
rocksDBPlugin.register(besuPluginContext);
new InMemoryStoragePlugin().register(besuPluginContext);

besuPluginContext.registerPlugins(pluginsDir());
Expand Down Expand Up @@ -1724,7 +1728,7 @@ public static Optional<Boolean> getColorEnabled() {
private void configureNativeLibs() {
if (unstableNativeLibraryOptions.getNativeAltbn128()
&& AbstractAltBnPrecompiledContract.isNative()) {
logger.info("Using LibEthPairings native alt bn128");
logger.info("Using the native implementation of alt bn128");
} else {
AbstractAltBnPrecompiledContract.disableNative();
logger.info("Using the Java implementation of alt bn128");
Expand Down Expand Up @@ -2014,8 +2018,6 @@ private void configure() throws Exception {
permissioningConfiguration = permissioningConfiguration();
staticNodes = loadStaticNodes();

logger.info("Connecting to {} static nodes.", staticNodes.size());
logger.trace("Static Nodes = {}", staticNodes);
final List<EnodeURL> enodeURIs = ethNetworkConfig.getBootNodes();
permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
Expand All @@ -2026,8 +2028,12 @@ private void configure() throws Exception {
.ifPresent(p -> ensureAllNodesAreInAllowlist(staticNodes, p));
metricsConfiguration = metricsConfiguration();

logger.info("Security Module: {}", securityModuleName);
instantiateSignatureAlgorithmFactory();

logger.info(generateConfigurationOverview());
logger.info("Connecting to {} static nodes.", staticNodes.size());
logger.trace("Static Nodes = {}", staticNodes);
logger.info("Security Module: {}", securityModuleName);
}

private JsonRpcIpcConfiguration jsonRpcIpcConfiguration(
Expand Down Expand Up @@ -2186,7 +2192,7 @@ private JsonRpcConfiguration createEngineJsonRpcConfiguration(
&& java.nio.file.Files.exists(engineRPCOptionGroup.engineJwtKeyFile)) {
engineConfig.setAuthenticationPublicKeyFile(engineRPCOptionGroup.engineJwtKeyFile.toFile());
} else {
logger.info(
logger.warn(
"Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir");
}
}
Expand Down Expand Up @@ -3084,7 +3090,7 @@ private Set<EnodeURL> loadStaticNodes() throws IOException {
final String staticNodesFilename = "static-nodes.json";
staticNodesPath = dataDir().resolve(staticNodesFilename);
}
logger.info("Static Nodes file = {}", staticNodesPath);
logger.debug("Static Nodes file = {}", staticNodesPath);
return StaticNodesParser.fromPath(staticNodesPath, getEnodeDnsConfiguration());
}

Expand Down Expand Up @@ -3331,4 +3337,34 @@ private SyncMode getDefaultSyncModeIfNotSet(final SyncMode syncMode) {
? SyncMode.FAST
: SyncMode.FULL);
}

private String generateConfigurationOverview() {
final ConfigurationOverviewBuilder builder = new ConfigurationOverviewBuilder();

if (network != null) {
builder.setNetwork(network.normalize());
}

builder
.setDataStorage(dataStorageOptions.normalizeDataStorageFormat())
.setSyncMode(syncMode.normalize());

if (jsonRpcConfiguration != null && jsonRpcConfiguration.isEnabled()) {
builder
.setRpcPort(jsonRpcConfiguration.getPort())
.setRpcHttpApis(jsonRpcConfiguration.getRpcApis());
}

if (engineJsonRpcConfiguration != null && engineJsonRpcConfiguration.isEnabled()) {
builder
.setEnginePort(engineJsonRpcConfiguration.getPort())
.setEngineApis(engineJsonRpcConfiguration.getRpcApis());
}

if (rocksDBPlugin.isHighSpecEnabled()) {
builder.setHighSpecEnabled();
}

return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli;

import org.hyperledger.besu.BesuInfo;
import org.hyperledger.besu.util.log.FramedLogMessage;
import org.hyperledger.besu.util.platform.PlatformDetector;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import oshi.PlatformEnum;
import oshi.SystemInfo;
import oshi.hardware.HardwareAbstractionLayer;

public class ConfigurationOverviewBuilder {
private String network;
private String dataStorage;
private String syncMode;
private Integer rpcPort;
private Collection<String> rpcHttpApis;
private Integer enginePort;
private Collection<String> engineApis;
private boolean isHighSpec = false;

public ConfigurationOverviewBuilder setNetwork(final String network) {
this.network = network;
return this;
}

public ConfigurationOverviewBuilder setDataStorage(final String dataStorage) {
this.dataStorage = dataStorage;
return this;
}

public ConfigurationOverviewBuilder setSyncMode(final String syncMode) {
this.syncMode = syncMode;
return this;
}

public ConfigurationOverviewBuilder setRpcPort(final Integer rpcPort) {
this.rpcPort = rpcPort;
return this;
}

public ConfigurationOverviewBuilder setRpcHttpApis(final Collection<String> rpcHttpApis) {
this.rpcHttpApis = rpcHttpApis;
return this;
}

public ConfigurationOverviewBuilder setEnginePort(final Integer enginePort) {
this.enginePort = enginePort;
return this;
}

public ConfigurationOverviewBuilder setEngineApis(final Collection<String> engineApis) {
this.engineApis = engineApis;
return this;
}

public ConfigurationOverviewBuilder setHighSpecEnabled() {
isHighSpec = true;
return this;
}

public String build() {
final List<String> lines = new ArrayList<>();
lines.add("Besu " + BesuInfo.class.getPackage().getImplementationVersion());
lines.add("");
lines.add("Configuration:");

if (network != null) {
lines.add("Network: " + network);
}

if (dataStorage != null) {
lines.add("Data storage: " + dataStorage);
}

if (syncMode != null) {
lines.add("Sync mode: " + syncMode);
}

if (rpcHttpApis != null) {
lines.add("RPC HTTP APIs: " + String.join(",", rpcHttpApis));
}
if (rpcPort != null) {
lines.add("RPC HTTP port: " + rpcPort);
}

if (engineApis != null) {
lines.add("Engine APIs: " + String.join(",", engineApis));
}
if (enginePort != null) {
lines.add("Engine port: " + enginePort);
}

if (isHighSpec) {
lines.add("High spec configuration enabled");
}

lines.add("");
lines.add("Host:");

lines.add("Java: " + PlatformDetector.getVM());
lines.add("Maximum heap size: " + normalizeSize(Runtime.getRuntime().maxMemory()));
lines.add("OS: " + PlatformDetector.getOS());

if (SystemInfo.getCurrentPlatform() == PlatformEnum.LINUX) {
final String glibcVersion = PlatformDetector.getGlibc();
if (glibcVersion != null) {
lines.add("glibc: " + glibcVersion);
}
}

final HardwareAbstractionLayer hardwareInfo = new SystemInfo().getHardware();

lines.add("Total memory: " + normalizeSize(hardwareInfo.getMemory().getTotal()));
lines.add("CPU cores: " + hardwareInfo.getProcessor().getLogicalProcessorCount());

return FramedLogMessage.generate(lines);
}

private String normalizeSize(final long size) {
return String.format("%.02f", (double) (size) / 1024 / 1024 / 1024) + " GB";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,24 @@
package org.hyperledger.besu.cli;

import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.util.log.FramedLogMessage;

import org.apache.commons.lang3.StringUtils;
import java.util.List;

public class NetworkDeprecationMessage {
private static final int MAX_LINE_LENGTH = 80;

public static String generate(final NetworkName network) {
if (network.getDeprecationDate().isEmpty()) {
throw new AssertionError("Deprecation date is not set. Cannot print a deprecation message");
}

final StringBuilder messageBuilder = new StringBuilder("\n");
messageBuilder
.append("#".repeat(MAX_LINE_LENGTH))
.append(emptyLine())
.append(
String.format(
"#%s#",
StringUtils.center(
deprecationDetails(
network.humanReadableNetworkName(), network.getDeprecationDate().get()),
MAX_LINE_LENGTH - 2)))
.append(emptyLine())
.append(
String.format(
"#%s#\n", StringUtils.center("For more details please go to", MAX_LINE_LENGTH - 2)))
.append(
String.format(
"#%s#",
StringUtils.center(
"https://blog.ethereum.org/2022/06/21/testnet-deprecation/",
MAX_LINE_LENGTH - 2)))
.append(emptyLine())
.append("#".repeat(MAX_LINE_LENGTH));

return messageBuilder.toString();
}

private static String deprecationDetails(final String networkName, final String deprecationDate) {
return networkName + " is deprecated and will be shutdown " + deprecationDate;
}

private static String emptyLine() {
return String.format("\n#%s#\n", StringUtils.center("", MAX_LINE_LENGTH - 2));
return FramedLogMessage.generateCentered(
List.of(
network.normalize()
+ " is deprecated and will be shutdown "
+ network.getDeprecationDate().get(),
"",
"For more details please go to",
"https://blog.ethereum.org/2022/06/21/testnet-deprecation/"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public boolean canFastSync() {
return canFastSync;
}

public String humanReadableNetworkName() {
public String normalize() {
return StringUtils.capitalize(name().toLowerCase());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import picocli.CommandLine.Option;

public class DataStorageOptions implements CLIOptions<DataStorageConfiguration> {
Expand Down Expand Up @@ -85,4 +86,8 @@ public List<String> getCLIOptions() {
BONSAI_STORAGE_FORMAT_USE_SNAPSHOTS,
bonsaiUseSnapshots.toString());
}

public String normalizeDataStorageFormat() {
return StringUtils.capitalize(dataStorageFormat.toString().toLowerCase());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5287,7 +5287,7 @@ public void nativeLibrariesAreEnabledByDefault() {
verify(mockLogger).info("Using the native implementation of the signature algorithm");

assertThat(AbstractAltBnPrecompiledContract.isNative()).isTrue();
verify(mockLogger).info("Using LibEthPairings native alt bn128");
verify(mockLogger).info("Using the native implementation of alt bn128");
}

@Test
Expand Down
Loading

0 comments on commit 49f32ca

Please sign in to comment.