diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 67a360a882f..a0e99db69fa 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -25,10 +25,6 @@ import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT; import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE; -import static org.hyperledger.besu.metrics.BesuMetricCategory.DEFAULT_METRIC_CATEGORIES; -import static org.hyperledger.besu.metrics.MetricsProtocol.PROMETHEUS; -import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAULT_METRICS_PORT; -import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAULT_METRICS_PUSH_PORT; import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER; import org.hyperledger.besu.BesuInfo; @@ -54,6 +50,7 @@ import org.hyperledger.besu.cli.options.stable.GraphQlOptions; import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions; import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; +import org.hyperledger.besu.cli.options.stable.MetricsOptionGroup; import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption; import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions; import org.hyperledger.besu.cli.options.stable.PermissionsOptions; @@ -314,7 +311,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { final MiningOptions miningOptions = MiningOptions.create(); private final RunnerBuilder runnerBuilder; - private final BesuController.Builder controllerBuilderFactory; + private final BesuController.Builder controllerBuilder; private final BesuPluginContextImpl besuPluginContext; private final StorageServiceImpl storageService; private final SecurityModuleServiceImpl securityModuleService; @@ -746,81 +743,6 @@ static class PrivacyOptionGroup { @CommandLine.ArgGroup(validate = false, heading = "@|bold Metrics Options|@%n") MetricsOptionGroup metricsOptionGroup = new MetricsOptionGroup(); - static class MetricsOptionGroup { - @Option( - names = {"--metrics-enabled"}, - description = "Set to start the metrics exporter (default: ${DEFAULT-VALUE})") - private final Boolean isMetricsEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-protocol"}, - description = - "Metrics protocol, one of PROMETHEUS, OPENTELEMETRY or NONE. (default: ${DEFAULT-VALUE})") - private MetricsProtocol metricsProtocol = PROMETHEUS; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String metricsHost; - - @Option( - names = {"--metrics-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPort = DEFAULT_METRICS_PORT; - - @Option( - names = {"--metrics-category", "--metrics-categories"}, - paramLabel = "", - split = ",", - arity = "1..*", - description = - "Comma separated list of categories to track metrics for (default: ${DEFAULT-VALUE})") - private final Set metricCategories = DEFAULT_METRIC_CATEGORIES; - - @Option( - names = {"--metrics-push-enabled"}, - description = "Enable the metrics push gateway integration (default: ${DEFAULT-VALUE})") - private final Boolean isMetricsPushEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-push-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = - "Host of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private String metricsPushHost; - - @Option( - names = {"--metrics-push-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = - "Port of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPushPort = DEFAULT_METRICS_PUSH_PORT; - - @Option( - names = {"--metrics-push-interval"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Interval in seconds to push metrics when in push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPushInterval = 15; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-push-prometheus-job"}, - description = "Job name to use when in push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private String metricsPrometheusJob = "besu-client"; - } - @Option( names = {"--host-allowlist"}, paramLabel = "[,...]... or * or all", @@ -962,7 +884,7 @@ static class MetricsOptionGroup { * @param jsonBlockImporterFactory instance of {@code Function} * @param rlpBlockExporterFactory instance of {@code Function} * @param runnerBuilder instance of RunnerBuilder - * @param controllerBuilderFactory instance of BesuController.Builder + * @param controllerBuilder instance of BesuController.Builder * @param besuPluginContext instance of BesuPluginContextImpl * @param environment Environment variables map */ @@ -972,7 +894,7 @@ public BesuCommand( final Function jsonBlockImporterFactory, final Function rlpBlockExporterFactory, final RunnerBuilder runnerBuilder, - final BesuController.Builder controllerBuilderFactory, + final BesuController.Builder controllerBuilder, final BesuPluginContextImpl besuPluginContext, final Map environment) { this( @@ -981,7 +903,7 @@ public BesuCommand( jsonBlockImporterFactory, rlpBlockExporterFactory, runnerBuilder, - controllerBuilderFactory, + controllerBuilder, besuPluginContext, environment, new StorageServiceImpl(), @@ -1003,7 +925,7 @@ public BesuCommand( * @param jsonBlockImporterFactory instance of {@code Function} * @param rlpBlockExporterFactory instance of {@code Function} * @param runnerBuilder instance of RunnerBuilder - * @param controllerBuilderFactory instance of BesuController.Builder + * @param controllerBuilder instance of BesuController.Builder * @param besuPluginContext instance of BesuPluginContextImpl * @param environment Environment variables map * @param storageService instance of StorageServiceImpl @@ -1023,7 +945,7 @@ protected BesuCommand( final Function jsonBlockImporterFactory, final Function rlpBlockExporterFactory, final RunnerBuilder runnerBuilder, - final BesuController.Builder controllerBuilderFactory, + final BesuController.Builder controllerBuilder, final BesuPluginContextImpl besuPluginContext, final Map environment, final StorageServiceImpl storageService, @@ -1041,7 +963,7 @@ protected BesuCommand( this.rlpBlockExporterFactory = rlpBlockExporterFactory; this.jsonBlockImporterFactory = jsonBlockImporterFactory; this.runnerBuilder = runnerBuilder; - this.controllerBuilderFactory = controllerBuilderFactory; + this.controllerBuilder = controllerBuilder; this.besuPluginContext = besuPluginContext; this.environment = environment; this.storageService = storageService; @@ -1911,7 +1833,7 @@ public BesuControllerBuilder getControllerBuilder() { .withMiningParameters(miningParametersSupplier.get()) .withJsonRpcHttpOptions(jsonRpcHttpOptions); final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); - return controllerBuilderFactory + return controllerBuilder .fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet()) .synchronizerConfiguration(buildSyncConfig()) .ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject()) @@ -1987,7 +1909,7 @@ private void checkPrivacyTlsOptionsDependencies() { * @return instance of MetricsConfiguration. */ public MetricsConfiguration metricsConfiguration() { - if (metricsOptionGroup.isMetricsEnabled && metricsOptionGroup.isMetricsPushEnabled) { + if (metricsOptionGroup.getMetricsEnabled() && metricsOptionGroup.getMetricsPushEnabled()) { throw new ParameterException( this.commandLine, "--metrics-enabled option and --metrics-push-enabled option can't be used at the same " @@ -1998,14 +1920,14 @@ public MetricsConfiguration metricsConfiguration() { logger, commandLine, "--metrics-enabled", - !metricsOptionGroup.isMetricsEnabled, + !metricsOptionGroup.getMetricsEnabled(), asList("--metrics-host", "--metrics-port")); CommandLineUtils.checkOptionDependencies( logger, commandLine, "--metrics-push-enabled", - !metricsOptionGroup.isMetricsPushEnabled, + !metricsOptionGroup.getMetricsPushEnabled(), asList( "--metrics-push-host", "--metrics-push-port", @@ -2014,23 +1936,23 @@ public MetricsConfiguration metricsConfiguration() { return unstableMetricsCLIOptions .toDomainObject() - .enabled(metricsOptionGroup.isMetricsEnabled) + .enabled(metricsOptionGroup.getMetricsEnabled()) .host( - Strings.isNullOrEmpty(metricsOptionGroup.metricsHost) + Strings.isNullOrEmpty(metricsOptionGroup.getMetricsHost()) ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() - : metricsOptionGroup.metricsHost) - .port(metricsOptionGroup.metricsPort) - .protocol(metricsOptionGroup.metricsProtocol) - .metricCategories(metricsOptionGroup.metricCategories) - .pushEnabled(metricsOptionGroup.isMetricsPushEnabled) + : metricsOptionGroup.getMetricsHost()) + .port(metricsOptionGroup.getMetricsPort()) + .protocol(metricsOptionGroup.getMetricsProtocol()) + .metricCategories(metricsOptionGroup.getMetricCategories()) + .pushEnabled(metricsOptionGroup.getMetricsPushEnabled()) .pushHost( - Strings.isNullOrEmpty(metricsOptionGroup.metricsPushHost) + Strings.isNullOrEmpty(metricsOptionGroup.getMetricsPushHost()) ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() - : metricsOptionGroup.metricsPushHost) - .pushPort(metricsOptionGroup.metricsPushPort) - .pushInterval(metricsOptionGroup.metricsPushInterval) + : metricsOptionGroup.getMetricsPushHost()) + .pushPort(metricsOptionGroup.getMetricsPushPort()) + .pushInterval(metricsOptionGroup.getMetricsPushInterval()) .hostsAllowlist(hostsAllowlist) - .prometheusJob(metricsOptionGroup.metricsPrometheusJob) + .prometheusJob(metricsOptionGroup.getMetricsPrometheusJob()) .build(); } @@ -2662,7 +2584,9 @@ private List getEffectivePorts() { effectivePorts, rpcWebsocketOptions.getRpcWsPort(), rpcWebsocketOptions.isRpcWsEnabled()); addPortIfEnabled(effectivePorts, engineRPCOptionGroup.engineRpcPort, isEngineApiEnabled()); addPortIfEnabled( - effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled); + effectivePorts, + metricsOptionGroup.getMetricsPort(), + metricsOptionGroup.getMetricsEnabled()); addPortIfEnabled( effectivePorts, miningParametersSupplier.get().getStratumPort(), diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptionGroup.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptionGroup.java new file mode 100644 index 00000000000..add2bf16553 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptionGroup.java @@ -0,0 +1,197 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * 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.options.stable; + +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP; +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_INTEGER_FORMAT_HELP; +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP; +import static org.hyperledger.besu.metrics.BesuMetricCategory.DEFAULT_METRIC_CATEGORIES; +import static org.hyperledger.besu.metrics.MetricsProtocol.PROMETHEUS; +import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAULT_METRICS_PORT; +import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAULT_METRICS_PUSH_PORT; + +import org.hyperledger.besu.metrics.MetricsProtocol; +import org.hyperledger.besu.plugin.services.metrics.MetricCategory; + +import java.util.Set; + +import picocli.CommandLine; + +/** Command line options for configuring metrics. */ +public class MetricsOptionGroup { + @CommandLine.Option( + names = {"--metrics-enabled"}, + description = "Set to start the metrics exporter (default: ${DEFAULT-VALUE})") + private final Boolean isMetricsEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--metrics-protocol"}, + description = + "Metrics protocol, one of PROMETHEUS, OPENTELEMETRY or NONE. (default: ${DEFAULT-VALUE})") + private MetricsProtocol metricsProtocol = PROMETHEUS; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--metrics-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "Host for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsHost; + + @CommandLine.Option( + names = {"--metrics-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPort = DEFAULT_METRICS_PORT; + + @CommandLine.Option( + names = {"--metrics-category", "--metrics-categories"}, + paramLabel = "", + split = ",", + arity = "1..*", + description = + "Comma separated list of categories to track metrics for (default: ${DEFAULT-VALUE})") + private final Set metricCategories = DEFAULT_METRIC_CATEGORIES; + + @CommandLine.Option( + names = {"--metrics-push-enabled"}, + description = "Enable the metrics push gateway integration (default: ${DEFAULT-VALUE})") + private final Boolean isMetricsPushEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--metrics-push-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "Host of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsPushHost; + + @CommandLine.Option( + names = {"--metrics-push-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPushPort = DEFAULT_METRICS_PUSH_PORT; + + @CommandLine.Option( + names = {"--metrics-push-interval"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Interval in seconds to push metrics when in push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPushInterval = 15; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--metrics-push-prometheus-job"}, + description = "Job name to use when in push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsPrometheusJob = "besu-client"; + + /** Returns a newly created {@link MetricsOptionGroup} with default values. */ + public MetricsOptionGroup() {} + + /** + * Returns whether metrics are enabled. + * + * @return true if metrics are enabled, otherwise false + */ + public Boolean getMetricsEnabled() { + return isMetricsEnabled; + } + + /** + * Returns the metrics protocol. + * + * @return the metrics protocol + */ + public MetricsProtocol getMetricsProtocol() { + return metricsProtocol; + } + + /** + * Returns the metrics host. + * + * @return the metrics host + */ + public String getMetricsHost() { + return metricsHost; + } + + /** + * Returns the metrics port. + * + * @return the metrics port + */ + public Integer getMetricsPort() { + return metricsPort; + } + + /** + * Returns the metric categories. + * + * @return the metric categories + */ + public Set getMetricCategories() { + return metricCategories; + } + + /** + * Returns whether metrics push is enabled. + * + * @return true if metrics push is enabled, otherwise false + */ + public Boolean getMetricsPushEnabled() { + return isMetricsPushEnabled; + } + + /** + * Returns the metrics push host. + * + * @return the metrics push host + */ + public String getMetricsPushHost() { + return metricsPushHost; + } + + /** + * Returns the metrics push port. + * + * @return the metrics push port + */ + public Integer getMetricsPushPort() { + return metricsPushPort; + } + + /** + * Returns the metrics push interval. + * + * @return the metrics push interval + */ + public Integer getMetricsPushInterval() { + return metricsPushInterval; + } + + /** + * Returns the metrics prometheus job. + * + * @return the metrics prometheus job + */ + public String getMetricsPrometheusJob() { + return metricsPrometheusJob; + } +}