Prints configuration overview (#4451)

* print configuration overview at startup

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
pull/4721/head
Daniel Lehrner 2 years ago committed by GitHub
parent 376ce82181
commit 49f32ca22d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 1
      besu/build.gradle
  3. 54
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  4. 140
      besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java
  5. 45
      besu/src/main/java/org/hyperledger/besu/cli/NetworkDeprecationMessage.java
  6. 2
      besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java
  7. 5
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java
  8. 2
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  9. 118
      besu/src/test/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilderTest.java
  10. 2
      besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java
  11. 1
      ethereum/eth/build.gradle
  12. 11
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/SyncMode.java
  13. 8
      ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/peers/StaticNodesParser.java
  14. 3
      gradle/check-licenses.gradle
  15. 21
      gradle/verification-metadata.xml
  16. 2
      gradle/versions.gradle
  17. 4
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBPlugin.java
  18. 4
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/RocksDBCLIOptions.java
  19. 1
      util/build.gradle
  20. 72
      util/src/main/java/org/hyperledger/besu/util/log/FramedLogMessage.java
  21. 55
      util/src/main/java/org/hyperledger/besu/util/platform/PlatformDetector.java

@ -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) - 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) - 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) - 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 ### Bug Fixes

@ -62,6 +62,7 @@ dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8'
implementation 'com.github.oshi:oshi-core'
implementation 'com.google.guava:guava' implementation 'com.google.guava:guava'
implementation 'com.graphql-java:graphql-java' implementation 'com.graphql-java:graphql-java'
implementation 'info.picocli:picocli' implementation 'info.picocli:picocli'

@ -317,6 +317,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider; private final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider;
private GenesisConfigOptions genesisConfigOptions; private GenesisConfigOptions genesisConfigOptions;
private RocksDBPlugin rocksDBPlugin;
// CLI options defined by user at runtime. // CLI options defined by user at runtime.
// Options parsing is done with CLI library Picocli https://picocli.info/ // Options parsing is done with CLI library Picocli https://picocli.info/
@ -1414,13 +1416,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
setMergeConfigOptions(); setMergeConfigOptions();
instantiateSignatureAlgorithmFactory(); 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 // Need to create vertx after cmdline has been parsed, such that metricsSystem is configurable
vertx = createVertx(createVertxOptions(metricsSystem.get())); vertx = createVertx(createVertxOptions(metricsSystem.get()));
validateOptions(); validateOptions();
configure(); configure();
configureNativeLibs();
initController(); initController();
besuPluginContext.beforeExternalServices(); besuPluginContext.beforeExternalServices();
@ -1544,7 +1547,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl);
// register built-in plugins // register built-in plugins
new RocksDBPlugin().register(besuPluginContext); rocksDBPlugin = new RocksDBPlugin();
rocksDBPlugin.register(besuPluginContext);
new InMemoryStoragePlugin().register(besuPluginContext); new InMemoryStoragePlugin().register(besuPluginContext);
besuPluginContext.registerPlugins(pluginsDir()); besuPluginContext.registerPlugins(pluginsDir());
@ -1724,7 +1728,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private void configureNativeLibs() { private void configureNativeLibs() {
if (unstableNativeLibraryOptions.getNativeAltbn128() if (unstableNativeLibraryOptions.getNativeAltbn128()
&& AbstractAltBnPrecompiledContract.isNative()) { && AbstractAltBnPrecompiledContract.isNative()) {
logger.info("Using LibEthPairings native alt bn128"); logger.info("Using the native implementation of alt bn128");
} else { } else {
AbstractAltBnPrecompiledContract.disableNative(); AbstractAltBnPrecompiledContract.disableNative();
logger.info("Using the Java implementation of alt bn128"); logger.info("Using the Java implementation of alt bn128");
@ -2014,8 +2018,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
permissioningConfiguration = permissioningConfiguration(); permissioningConfiguration = permissioningConfiguration();
staticNodes = loadStaticNodes(); staticNodes = loadStaticNodes();
logger.info("Connecting to {} static nodes.", staticNodes.size());
logger.trace("Static Nodes = {}", staticNodes);
final List<EnodeURL> enodeURIs = ethNetworkConfig.getBootNodes(); final List<EnodeURL> enodeURIs = ethNetworkConfig.getBootNodes();
permissioningConfiguration permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig) .flatMap(PermissioningConfiguration::getLocalConfig)
@ -2026,8 +2028,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.ifPresent(p -> ensureAllNodesAreInAllowlist(staticNodes, p)); .ifPresent(p -> ensureAllNodesAreInAllowlist(staticNodes, p));
metricsConfiguration = metricsConfiguration(); metricsConfiguration = metricsConfiguration();
logger.info("Security Module: {}", securityModuleName);
instantiateSignatureAlgorithmFactory(); 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( private JsonRpcIpcConfiguration jsonRpcIpcConfiguration(
@ -2186,7 +2192,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
&& java.nio.file.Files.exists(engineRPCOptionGroup.engineJwtKeyFile)) { && java.nio.file.Files.exists(engineRPCOptionGroup.engineJwtKeyFile)) {
engineConfig.setAuthenticationPublicKeyFile(engineRPCOptionGroup.engineJwtKeyFile.toFile()); engineConfig.setAuthenticationPublicKeyFile(engineRPCOptionGroup.engineJwtKeyFile.toFile());
} else { } else {
logger.info( logger.warn(
"Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir"); "Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir");
} }
} }
@ -3084,7 +3090,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final String staticNodesFilename = "static-nodes.json"; final String staticNodesFilename = "static-nodes.json";
staticNodesPath = dataDir().resolve(staticNodesFilename); staticNodesPath = dataDir().resolve(staticNodesFilename);
} }
logger.info("Static Nodes file = {}", staticNodesPath); logger.debug("Static Nodes file = {}", staticNodesPath);
return StaticNodesParser.fromPath(staticNodesPath, getEnodeDnsConfiguration()); return StaticNodesParser.fromPath(staticNodesPath, getEnodeDnsConfiguration());
} }
@ -3331,4 +3337,34 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
? SyncMode.FAST ? SyncMode.FAST
: SyncMode.FULL); : 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();
}
} }

@ -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";
}
}

@ -15,49 +15,24 @@
package org.hyperledger.besu.cli; package org.hyperledger.besu.cli;
import org.hyperledger.besu.cli.config.NetworkName; 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 { public class NetworkDeprecationMessage {
private static final int MAX_LINE_LENGTH = 80;
public static String generate(final NetworkName network) { public static String generate(final NetworkName network) {
if (network.getDeprecationDate().isEmpty()) { if (network.getDeprecationDate().isEmpty()) {
throw new AssertionError("Deprecation date is not set. Cannot print a deprecation message"); throw new AssertionError("Deprecation date is not set. Cannot print a deprecation message");
} }
final StringBuilder messageBuilder = new StringBuilder("\n"); return FramedLogMessage.generateCentered(
messageBuilder List.of(
.append("#".repeat(MAX_LINE_LENGTH)) network.normalize()
.append(emptyLine()) + " is deprecated and will be shutdown "
.append( + network.getDeprecationDate().get(),
String.format( "",
"#%s#", "For more details please go to",
StringUtils.center( "https://blog.ethereum.org/2022/06/21/testnet-deprecation/"));
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));
} }
} }

@ -76,7 +76,7 @@ public enum NetworkName {
return canFastSync; return canFastSync;
} }
public String humanReadableNetworkName() { public String normalize() {
return StringUtils.capitalize(name().toLowerCase()); return StringUtils.capitalize(name().toLowerCase());
} }

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguratio
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import picocli.CommandLine.Option; import picocli.CommandLine.Option;
public class DataStorageOptions implements CLIOptions<DataStorageConfiguration> { public class DataStorageOptions implements CLIOptions<DataStorageConfiguration> {
@ -85,4 +86,8 @@ public class DataStorageOptions implements CLIOptions<DataStorageConfiguration>
BONSAI_STORAGE_FORMAT_USE_SNAPSHOTS, BONSAI_STORAGE_FORMAT_USE_SNAPSHOTS,
bonsaiUseSnapshots.toString()); bonsaiUseSnapshots.toString());
} }
public String normalizeDataStorageFormat() {
return StringUtils.capitalize(dataStorageFormat.toString().toLowerCase());
}
} }

@ -5287,7 +5287,7 @@ public class BesuCommandTest extends CommandTestAbstract {
verify(mockLogger).info("Using the native implementation of the signature algorithm"); verify(mockLogger).info("Using the native implementation of the signature algorithm");
assertThat(AbstractAltBnPrecompiledContract.isNative()).isTrue(); assertThat(AbstractAltBnPrecompiledContract.isNative()).isTrue();
verify(mockLogger).info("Using LibEthPairings native alt bn128"); verify(mockLogger).info("Using the native implementation of alt bn128");
} }
@Test @Test

@ -0,0 +1,118 @@
/*
* 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 static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ConfigurationOverviewBuilderTest {
private ConfigurationOverviewBuilder builder;
@BeforeEach
void setUp() {
builder = new ConfigurationOverviewBuilder();
}
@Test
void setNetwork() {
final String noNetworkSet = builder.build();
assertThat(noNetworkSet).doesNotContain("Network:");
builder.setNetwork("foobar");
final String networkSet = builder.build();
assertThat(networkSet).contains("Network: foobar");
}
@Test
void setDataStorage() {
final String noDataStorageSet = builder.build();
assertThat(noDataStorageSet).doesNotContain("Data storage:");
builder.setDataStorage("bonsai");
final String dataStorageSet = builder.build();
assertThat(dataStorageSet).contains("Data storage: bonsai");
}
@Test
void setSyncMode() {
final String noSyncModeSet = builder.build();
assertThat(noSyncModeSet).doesNotContain("Sync mode:");
builder.setSyncMode("fast");
final String syncModeSet = builder.build();
assertThat(syncModeSet).contains("Sync mode: fast");
}
@Test
void setRpcPort() {
final String noRpcPortSet = builder.build();
assertThat(noRpcPortSet).doesNotContain("RPC HTTP port:");
builder.setRpcPort(42);
final String rpcPortSet = builder.build();
assertThat(rpcPortSet).contains("RPC HTTP port: 42");
}
@Test
void setRpcHttpApis() {
final String noRpcApisSet = builder.build();
assertThat(noRpcApisSet).doesNotContain("RPC HTTP APIs:");
final Collection<String> rpcApis = new ArrayList<>();
rpcApis.add("api1");
rpcApis.add("api2");
builder.setRpcHttpApis(rpcApis);
final String rpcApisSet = builder.build();
assertThat(rpcApisSet).contains("RPC HTTP APIs: api1,api2");
}
@Test
void setEnginePort() {
final String noEnginePortSet = builder.build();
assertThat(noEnginePortSet).doesNotContain("Engine port:");
builder.setEnginePort(42);
final String enginePortSet = builder.build();
assertThat(enginePortSet).contains("Engine port: 42");
}
@Test
void setEngineApis() {
final String noEngineApisSet = builder.build();
assertThat(noEngineApisSet).doesNotContain("Engine APIs:");
final Collection<String> engineApis = new ArrayList<>();
engineApis.add("api1");
engineApis.add("api2");
builder.setEngineApis(engineApis);
final String engineApisSet = builder.build();
assertThat(engineApisSet).contains("Engine APIs: api1,api2");
}
@Test
void setHighSpecEnabled() {
final String highSpecNotEnabled = builder.build();
assertThat(highSpecNotEnabled).doesNotContain("High spec configuration enabled");
builder.setHighSpecEnabled();
final String highSpecEnabled = builder.build();
assertThat(highSpecEnabled).contains("High spec configuration enabled");
}
}

@ -30,7 +30,7 @@ class NetworkDeprecationMessageTest {
names = {"RINKEBY", "ROPSTEN", "KILN"}) names = {"RINKEBY", "ROPSTEN", "KILN"})
void shouldGenerateDeprecationMessageForDeprecatedNetworks(final NetworkName network) { void shouldGenerateDeprecationMessageForDeprecatedNetworks(final NetworkName network) {
assertThat(NetworkDeprecationMessage.generate(network)) assertThat(NetworkDeprecationMessage.generate(network))
.contains(network.humanReadableNetworkName() + " is deprecated and will be shutdown"); .contains(network.normalize() + " is deprecated and will be shutdown");
} }
@ParameterizedTest @ParameterizedTest

@ -54,6 +54,7 @@ dependencies {
implementation 'com.google.guava:guava' implementation 'com.google.guava:guava'
implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-core'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.apache.tuweni:tuweni-bytes' implementation 'org.apache.tuweni:tuweni-bytes'
implementation 'org.apache.tuweni:tuweni-units' implementation 'org.apache.tuweni:tuweni-units'
implementation 'org.apache.tuweni:tuweni-rlp' implementation 'org.apache.tuweni:tuweni-rlp'

@ -16,6 +16,8 @@ package org.hyperledger.besu.ethereum.eth.sync;
import java.util.EnumSet; import java.util.EnumSet;
import org.apache.commons.lang3.StringUtils;
public enum SyncMode { public enum SyncMode {
// Fully validate all blocks as they sync // Fully validate all blocks as they sync
FULL, FULL,
@ -26,6 +28,15 @@ public enum SyncMode {
// Perform snapsync but starting from a checkpoint instead of starting from genesis // Perform snapsync but starting from a checkpoint instead of starting from genesis
X_CHECKPOINT; X_CHECKPOINT;
public String normalize() {
if (this.toString().startsWith("X_")) {
// removes X_ at the beginning
return StringUtils.capitalize(this.toString().substring(2).toLowerCase());
}
return StringUtils.capitalize(this.toString().toLowerCase());
}
public static boolean isFullSync(final SyncMode syncMode) { public static boolean isFullSync(final SyncMode syncMode) {
return !EnumSet.of(SyncMode.FAST, SyncMode.X_SNAP, SyncMode.X_CHECKPOINT).contains(syncMode); return !EnumSet.of(SyncMode.FAST, SyncMode.X_SNAP, SyncMode.X_CHECKPOINT).contains(syncMode);
} }

@ -44,16 +44,16 @@ public class StaticNodesParser {
try { try {
return readEnodesFromPath(path, enodeDnsConfiguration); return readEnodesFromPath(path, enodeDnsConfiguration);
} catch (FileNotFoundException | NoSuchFileException ex) { } catch (FileNotFoundException | NoSuchFileException ex) {
LOG.info("StaticNodes file {} does not exist, no static connections will be created.", path); LOG.debug("StaticNodes file {} does not exist, no static connections will be created.", path);
return emptySet(); return emptySet();
} catch (IOException ex) { } catch (IOException ex) {
LOG.info("Unable to parse static nodes file ({})", path); LOG.warn("Unable to parse static nodes file ({})", path);
throw ex; throw ex;
} catch (DecodeException ex) { } catch (DecodeException ex) {
LOG.info("Content of ({}} was invalid json, and could not be decoded.", path); LOG.warn("Content of ({}} was invalid json, and could not be decoded.", path);
throw ex; throw ex;
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
LOG.info("Parsing ({}) has failed due incorrectly formatted enode element.", path); LOG.warn("Parsing ({}) has failed due incorrectly formatted enode element.", path);
throw ex; throw ex;
} }
} }

@ -132,6 +132,7 @@ downloadLicenses {
'MIT', 'MIT',
'The MIT License', 'The MIT License',
'The MIT License (MIT)', 'The MIT License (MIT)',
'SPDX-License-Identifier: MIT',
], ],
] ]
licenses = [ licenses = [
@ -199,7 +200,7 @@ task checkLicenses {
if (!acceptedLicenses.contains((license.@name).toLowerCase())) { if (!acceptedLicenses.contains((license.@name).toLowerCase())) {
def depStrings = [] def depStrings = []
license.dependency.each { depStrings << it.text() } license.dependency.each { depStrings << it.text() }
bads = bads + depStrings + " => ${license.@name} \n" bads = bads + depStrings + " => ${license.@name} \n"
} }
} }
if (bads != "") { if (bads != "") {

@ -516,6 +516,19 @@
<sha256 value="b0642ce69c2b945e143fffd74b4cd3ce53b520c8cd535bbe53dcdc488873c00d" origin="Generated by Gradle"/> <sha256 value="b0642ce69c2b945e143fffd74b4cd3ce53b520c8cd535bbe53dcdc488873c00d" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.github.oshi" name="oshi-core" version="6.2.2">
<artifact name="oshi-core-6.2.2.jar">
<sha256 value="efbca93df18f3eb16964a92d8342f0674dd5d90da575ef8e04ef2e4eabec6910" origin="Generated by Gradle"/>
</artifact>
<artifact name="oshi-core-6.2.2.pom">
<sha256 value="fa00adfd6d2f5bd3731711c318ab9c0f4ed6963b72af5491377e6f479d45d5b3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.github.oshi" name="oshi-parent" version="6.2.2">
<artifact name="oshi-parent-6.2.2.pom">
<sha256 value="1737e6df75ac8106130bdfa3a911a5909009f5a1500635773a6a6659a36c9ab3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.github.spotbugs" name="spotbugs-annotations" version="4.0.2"> <component group="com.github.spotbugs" name="spotbugs-annotations" version="4.0.2">
<artifact name="spotbugs-annotations-4.0.2.jar"> <artifact name="spotbugs-annotations-4.0.2.jar">
<sha256 value="3ef6c9f822b601aa151e10e123b49e5604243a4a99bcc47e4e1f9eea9781dc63" origin="Generated by Gradle"/> <sha256 value="3ef6c9f822b601aa151e10e123b49e5604243a4a99bcc47e4e1f9eea9781dc63" origin="Generated by Gradle"/>
@ -2661,6 +2674,14 @@
<sha256 value="65ff25849bad859554b50317792f5689adb4529ae4031e9a5246319cb2b85356" origin="Generated by Gradle"/> <sha256 value="65ff25849bad859554b50317792f5689adb4529ae4031e9a5246319cb2b85356" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="net.java.dev.jna" name="jna-platform" version="5.12.1">
<artifact name="jna-platform-5.12.1.jar">
<sha256 value="8ce969116cac95bd61b07a8d5e07174b352e63301473caac72c395e3c08488d2" origin="Generated by Gradle"/>
</artifact>
<artifact name="jna-platform-5.12.1.pom">
<sha256 value="c279ffa3b5168e2203087231c638919a7cec7458006b1cda66959747860fb457" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="net.javacrumbs.json-unit" name="json-unit-core" version="2.33.0"> <component group="net.javacrumbs.json-unit" name="json-unit-core" version="2.33.0">
<artifact name="json-unit-core-2.33.0.jar"> <artifact name="json-unit-core-2.33.0.jar">
<sha256 value="e01daccdb4c8f9df22ae5a9c7f80f6744cf8546b9c71b57193f7f5d7fd6d62f7" origin="Generated by Gradle"/> <sha256 value="e01daccdb4c8f9df22ae5a9c7f80f6744cf8546b9c71b57193f7f5d7fd6d62f7" origin="Generated by Gradle"/>

@ -206,5 +206,7 @@ dependencyManagement {
dependency 'org.yaml:snakeyaml:1.32' dependency 'org.yaml:snakeyaml:1.32'
dependency 'tech.pegasys.discovery:discovery:22.2.0' dependency 'tech.pegasys.discovery:discovery:22.2.0'
dependency 'com.github.oshi:oshi-core:6.2.2'
} }
} }

@ -95,6 +95,10 @@ public class RocksDBPlugin implements BesuPlugin {
} }
} }
public boolean isHighSpecEnabled() {
return options.isHighSpec();
}
private void createAndRegister(final StorageService service) { private void createAndRegister(final StorageService service) {
final List<SegmentIdentifier> segments = service.getAllSegmentIdentifiers(); final List<SegmentIdentifier> segments = service.getAllSegmentIdentifiers();

@ -94,6 +94,10 @@ public class RocksDBCLIOptions {
maxOpenFiles, maxBackgroundCompactions, backgroundThreadCount, cacheCapacity, isHighSpec); maxOpenFiles, maxBackgroundCompactions, backgroundThreadCount, cacheCapacity, isHighSpec);
} }
public boolean isHighSpec() {
return isHighSpec;
}
@Override @Override
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)

@ -32,6 +32,7 @@ dependencies {
api 'org.slf4j:slf4j-api' api 'org.slf4j:slf4j-api'
implementation 'com.google.guava:guava' implementation 'com.google.guava:guava'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.apache.logging.log4j:log4j-core' implementation 'org.apache.logging.log4j:log4j-core'
implementation 'org.apache.logging.log4j:log4j-slf4j-impl' implementation 'org.apache.logging.log4j:log4j-slf4j-impl'
implementation 'org.xerial.snappy:snappy-java' implementation 'org.xerial.snappy:snappy-java'

@ -0,0 +1,72 @@
/*
* 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.util.log;
import java.util.List;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
public class FramedLogMessage {
private static final int MAX_LINE_LENGTH = 100;
private FramedLogMessage() {}
public static String generate(final List<String> logLines) {
final StringBuilder builder = new StringBuilder("\n");
appendHeader(builder);
logLines.forEach(
logLine ->
Splitter.fixedLength(76)
.split(logLine)
.forEach(
splitLogLine ->
builder.append(
String.format(
"# %s #\n",
StringUtils.rightPad(splitLogLine, MAX_LINE_LENGTH - 4)))));
appendFooter(builder);
return builder.toString();
}
public static String generateCentered(final List<String> logLines) {
final StringBuilder builder = new StringBuilder("\n");
appendHeader(builder);
logLines.forEach(
logLine ->
builder.append(
String.format("#%s#\n", StringUtils.center(logLine, MAX_LINE_LENGTH - 2))));
appendFooter(builder);
return builder.toString();
}
private static void appendHeader(final StringBuilder builder) {
builder.append("#".repeat(MAX_LINE_LENGTH) + "\n").append(emptyLine());
}
private static void appendFooter(final StringBuilder builder) {
builder.append(emptyLine()).append("#".repeat(MAX_LINE_LENGTH));
}
private static String emptyLine() {
return String.format("#%s#\n", StringUtils.center("", MAX_LINE_LENGTH - 2));
}
}

@ -14,7 +14,14 @@
*/ */
package org.hyperledger.besu.util.platform; package org.hyperledger.besu.util.platform;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* Detects OS and VMs. * Detects OS and VMs.
@ -28,6 +35,7 @@ public class PlatformDetector {
private static String _osType; private static String _osType;
private static String _vm; private static String _vm;
private static String _arch; private static String _arch;
private static String _glibc;
public static String getOSType() { public static String getOSType() {
if (_osType == null) { if (_osType == null) {
@ -57,6 +65,14 @@ public class PlatformDetector {
return _vm; return _vm;
} }
public static String getGlibc() {
if (_glibc == null) {
detectGlibc();
}
return _glibc;
}
private static final String UNKNOWN = "unknown"; private static final String UNKNOWN = "unknown";
private static void detect() { private static void detect() {
@ -213,4 +229,43 @@ public class PlatformDetector {
} }
return System.getProperty(value).toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", ""); return System.getProperty(value).toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
} }
private static void detectGlibc() {
final ProcessBuilder processBuilder =
new ProcessBuilder("/bin/bash").command("/usr/bin/ldd", "--version");
processBuilder.redirectErrorStream(true);
final StringBuilder rawGlibcVersionBuilder;
try {
final Process process = processBuilder.start();
rawGlibcVersionBuilder = readGlibcVersionStream(process.getInputStream());
} catch (IOException e) {
return;
}
_glibc = normalizeGLibcVersion(rawGlibcVersionBuilder.toString());
}
private static StringBuilder readGlibcVersionStream(final InputStream iStream)
throws IOException {
final StringBuilder builder = new StringBuilder();
String line;
try (BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(iStream, Charset.defaultCharset()))) {
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
}
return builder;
}
private static String normalizeGLibcVersion(final String rawGlibcVersion) {
final Pattern pattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");
final Matcher matcher = pattern.matcher(rawGlibcVersion);
return matcher.find() ? matcher.group() : null;
}
} }

Loading…
Cancel
Save