From 244ca2b73ce21d39c41336cb227b8497d60ed55b Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:10:04 +0900 Subject: [PATCH 01/19] [chore] #4323: remove `iroha_config/tokio-console` feature Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- config/Cargo.toml | 3 --- config/src/parameters/defaults.rs | 1 - config/src/parameters/user.rs | 6 +----- config/src/parameters/user/boilerplate.rs | 10 +--------- logger/Cargo.toml | 2 +- logger/src/lib.rs | 1 - 6 files changed, 3 insertions(+), 20 deletions(-) diff --git a/config/Cargo.toml b/config/Cargo.toml index 8c354f4372b..fd23c7f8cad 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -42,6 +42,3 @@ stacker = "0.1.15" expect-test = { workspace = true } trybuild = { workspace = true } hex = { workspace = true } - -[features] -tokio-console = [] diff --git a/config/src/parameters/defaults.rs b/config/src/parameters/defaults.rs index ff55704ee09..a3893c19cdc 100644 --- a/config/src/parameters/defaults.rs +++ b/config/src/parameters/defaults.rs @@ -24,7 +24,6 @@ pub mod kura { pub const DEFAULT_STORE_DIR: &str = "./storage"; } -#[cfg(feature = "tokio-console")] pub mod logger { use iroha_primitives::addr::{socket_addr, SocketAddr}; diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index d395f50fbb6..7b92127c31b 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -461,7 +461,6 @@ pub struct Queue { pub future_threshold: Duration, } -#[allow(missing_copy_implementations)] // triggered without tokio-console #[derive(Debug, Clone)] pub struct Logger { /// Level of logging verbosity @@ -471,18 +470,15 @@ pub struct Logger { pub level: Level, /// Output format pub format: LoggerFormat, - #[cfg(feature = "tokio-console")] - /// Address of tokio console (only available under "tokio-console" feature) + /// Address of tokio console pub tokio_console_address: SocketAddr, } -#[allow(clippy::derivable_impls)] // triggers in absence of `tokio-console` feature impl Default for Logger { fn default() -> Self { Self { level: Level::default(), format: LoggerFormat::default(), - #[cfg(feature = "tokio-console")] tokio_console_address: super::defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR, } } diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 34474918934..825607c1540 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -500,18 +500,11 @@ impl UnwrapPartial for QueuePartial { impl FromEnvDefaultFallback for QueuePartial {} -/// 'Logger' configuration. #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Default, Merge)] -// `tokio_console_addr` is not `Copy`, but warning appears without `tokio-console` feature -#[allow(missing_copy_implementations)] #[serde(deny_unknown_fields, default)] pub struct LoggerPartial { - /// Level of logging verbosity pub level: UserField, - /// Output format pub format: UserField, - #[cfg(feature = "tokio-console")] - /// Address of tokio console (only available under "tokio-console" feature) pub tokio_console_address: UserField, } @@ -522,9 +515,8 @@ impl UnwrapPartial for LoggerPartial { Ok(Logger { level: self.level.unwrap_or_default(), format: self.format.unwrap_or_default(), - #[cfg(feature = "tokio-console")] tokio_console_address: self.tokio_console_address.get().unwrap_or_else(|| { - super::super::defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR.clone() + defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR.clone() }), }) } diff --git a/logger/Cargo.toml b/logger/Cargo.toml index 83aba591aea..4c3cdbfa343 100644 --- a/logger/Cargo.toml +++ b/logger/Cargo.toml @@ -32,6 +32,6 @@ tokio = { workspace = true, features = ["macros", "time", "rt"] } [features] -tokio-console = ["dep:console-subscriber", "tokio/tracing", "iroha_config/tokio-console"] +tokio-console = ["dep:console-subscriber", "tokio/tracing"] # Workaround to avoid activating `tokio-console` with `--all-features` flag, because `tokio-console` require `tokio_unstable` rustc flag no-tokio-console = [] diff --git a/logger/src/lib.rs b/logger/src/lib.rs index 87a5ac3ed60..d00550e7447 100644 --- a/logger/src/lib.rs +++ b/logger/src/lib.rs @@ -82,7 +82,6 @@ pub fn test_logger() -> LoggerHandle { // with ENV vars rather than by extending `test_logger` signature. This will both remain // `test_logger` simple and also will emphasise isolation which is necessary anyway in // case of singleton mocking (where the logger is the singleton). - #[allow(clippy::needless_update)] // triggers without "tokio-console" feature let config = Config { level: Level::DEBUG, format: Format::Pretty, From 05b28e670a3ca403e546fc72105d63a54cbbad24 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:57:29 +0900 Subject: [PATCH 02/19] [chore]: format Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- config/src/parameters/user/boilerplate.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 825607c1540..84c4a12e542 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -515,9 +515,10 @@ impl UnwrapPartial for LoggerPartial { Ok(Logger { level: self.level.unwrap_or_default(), format: self.format.unwrap_or_default(), - tokio_console_address: self.tokio_console_address.get().unwrap_or_else(|| { - defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR.clone() - }), + tokio_console_address: self + .tokio_console_address + .get() + .unwrap_or_else(|| defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR.clone()), }) } } From a933736f665ebca41f48987d9643d69835a82daf Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:49:32 +0900 Subject: [PATCH 03/19] [refactor]: re-arrange telemetry features - remove `tokio_console_address` configuration - leverage default ENVs for tokio console config - `iroha_logger/tokio-console` feature fully controls whether it is enabled - refactoring chores Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- Cargo.toml | 248 +++++++++++++++++----- cli/Cargo.toml | 10 +- cli/src/lib.rs | 131 ++++++++---- cli/src/main.rs | 54 +---- config/src/parameters/actual.rs | 4 +- config/src/parameters/defaults.rs | 6 - config/src/parameters/user.rs | 20 +- config/src/parameters/user/boilerplate.rs | 6 +- config/tests/fixtures.rs | 2 +- core/Cargo.toml | 13 +- logger/Cargo.toml | 5 +- logger/src/lib.rs | 52 +++-- logger/tests/setting_logger.rs | 6 +- telemetry/src/dev.rs | 35 +-- 14 files changed, 359 insertions(+), 233 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index abf3a6e5b03..5f013909f54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ categories = ["cryptography::cryptocurrencies"] [workspace.dependencies] iroha = { path = "cli" } -iroha_dsl = { version = "=2.0.0-pre-rc.20", path = "dsl" } iroha_torii = { version = "=2.0.0-pre-rc.20", path = "torii" } iroha_torii_derive = { version = "=2.0.0-pre-rc.20", path = "torii/derive" } iroha_torii_const = { version = "=2.0.0-pre-rc.20", path = "torii/const" } @@ -51,14 +50,10 @@ iroha_wasm_builder = { version = "=2.0.0-pre-rc.20", path = "wasm_builder" } iroha_smart_contract = { version = "=2.0.0-pre-rc.20", path = "smart_contract" } iroha_smart_contract_derive = { version = "=2.0.0-pre-rc.20", path = "smart_contract/derive" } iroha_smart_contract_utils = { version = "=2.0.0-pre-rc.20", path = "smart_contract/utils" } -iroha_executor = { version = "=2.0.0-pre-rc.20", path = "smart_contract/executor" } iroha_executor_derive = { version = "=2.0.0-pre-rc.20", path = "smart_contract/executor/derive" } -iroha_trigger = { version = "=2.0.0-pre-rc.20", path = "smart_contract/trigger" } iroha_trigger_derive = { version = "=2.0.0-pre-rc.20", path = "smart_contract/trigger/derive" } test_network = { version = "=2.0.0-pre-rc.20", path = "core/test_network" } - -proc-macro-error = "1.0.4" proc-macro2 = "1.0.69" syn = { version = "2.0.38", default-features = false } quote = "1.0.33" @@ -71,8 +66,6 @@ tokio = "1.33.0" tokio-stream = "0.1.14" tokio-tungstenite = "0.20.1" tungstenite = "0.20.1" - -crossbeam = "0.8.2" crossbeam-queue = "0.3.8" parking_lot = { version = "0.12.1" } @@ -98,10 +91,8 @@ owo-colors = "3.5.0" supports-color = "2.1.0" inquire = "0.6.2" spinoff = "0.8.0" -duct = "0.13.6" criterion = "0.5.1" -proptest = "1.3.1" expect-test = "1.4.1" eyre = "0.6.8" @@ -140,117 +131,256 @@ storage = { git = "https://github.com/Erigara/storage.git", rev = "e0afe4b42810e rustdoc.private_doc_tests = "deny" rust.anonymous_parameters = "deny" + rust.future_incompatible = "deny" + rust.missing_copy_implementations = "deny" + rust.missing_docs = "deny" + rust.nonstandard_style = "deny" + rust.rust_2018_idioms = "deny" + rust.trivial_casts = "deny" + rust.trivial_numeric_casts = "deny" + rust.unsafe_code = "deny" + rust.unused = "deny" + rust.unused_import_braces = "deny" + rust.variant_size_differences = "deny" + rust.explicit_outlives_requirements = "deny" + rust.non_ascii_idents = "deny" + rust.elided_lifetimes_in_paths = "allow" + rust.unknown_lints = "warn" + rust.single_use_lifetimes = "warn" + rust.unused_lifetimes = "warn" # TODO: reenable # rust.unsafe_op_in_unsafe_fn = "deny" # pedantic clippy.pedantic = { level = "warn", priority = -1 } +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.match_wildcard_for_single_variants = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.semicolon_if_nothing_returned = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.wildcard_imports = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.manual_let_else = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.enum_glob_use = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.module_name_repetitions = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.must_use_candidate = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.missing_panics_doc = "allow" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" -# restriction +# pedantic clippy.dbg_macro = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" -# nursery +# pedantic clippy.debug_assert_with_mut_call = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.derive_partial_eq_without_eq = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.empty_line_after_outer_attr = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.fallible_impl_from = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.future_not_send = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.iter_with_drain = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.mutex_integer = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.needless_collect = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.path_buf_push_overwrite = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.suboptimal_flops = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.trailing_empty_array = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.transmute_undefined_repr = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.trivial_regex = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.unused_peekable = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.unused_rounding = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.option_if_let_else = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.or_fun_call = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.redundant_pub_crate = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.string_lit_as_bytes = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.suspicious_operation_groupings = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.useless_let_if_seq = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" -#cargo +# pedantic clippy.redundant_feature_names = "deny" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.wildcard_dependencies = "deny" [workspace] resolver = "2" members = [ - "cli", - "client", - "client_cli", - "config", - "config/base", - "core", - "core/test_network", - "crypto", - "data_model", - "genesis", - "primitives", - "primitives/derive", - "primitives/numeric", - "ffi", - "ffi/derive", - "futures", - "futures/derive", - "logger", - "macro", - "macro/derive", - "macro/utils", - "p2p", - "schema", - "schema/derive", - "schema/gen", - "smart_contract", - "smart_contract/derive", - "smart_contract/trigger", - "smart_contract/trigger/derive", - "smart_contract/utils", - "smart_contract/executor", - "smart_contract/executor/derive", - "telemetry", - "tools/kagami", - "tools/kura_inspector", - "tools/parity_scale_decoder", - "tools/swarm", - "tools/wasm_builder_cli", - "tools/wasm_test_runner", - "torii", - "torii/derive", - "torii/const", - "version", - "version/derive", - "wasm_codec", - "wasm_codec/derive", - "wasm_builder", + "cli", + "client", + "client_cli", + "config", + "config/base", + "core", + "core/test_network", + "crypto", + "data_model", + "genesis", + "primitives", + "primitives/derive", + "primitives/numeric", + "ffi", + "ffi/derive", + "futures", + "futures/derive", + "logger", + "macro", + "macro/derive", + "macro/utils", + "p2p", + "schema", + "schema/derive", + "schema/gen", + "smart_contract", + "smart_contract/derive", + "smart_contract/trigger", + "smart_contract/trigger/derive", + "smart_contract/utils", + "smart_contract/executor", + "smart_contract/executor/derive", + "telemetry", + "tools/kagami", + "tools/kura_inspector", + "tools/parity_scale_decoder", + "tools/swarm", + "tools/wasm_builder_cli", + "tools/wasm_test_runner", + "torii", + "torii/derive", + "torii/const", + "version", + "version/derive", + "wasm_codec", + "wasm_codec/derive", + "wasm_builder", ] [profile.deploy] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 4ab631e22e2..bb21b2c8a12 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -24,7 +24,9 @@ default = ["telemetry", "schema-endpoint"] telemetry = ["iroha_telemetry", "iroha_core/telemetry", "iroha_torii/telemetry"] # Support developer-specific telemetry. # Should not be enabled on production builds. -dev-telemetry = ["iroha_core/dev-telemetry", "iroha_telemetry"] +# Tokio Console is configured via ENV: +# https://docs.rs/console-subscriber/0.2.0/console_subscriber/struct.Builder.html#method.with_default_env +dev-telemetry = ["telemetry", "iroha_telemetry/dev-telemetry", "iroha_logger/tokio-console"] # Support schema generation from the `schema` endpoint in the local binary. # Useful for debugging issues with decoding in SDKs. schema-endpoint = ["iroha_torii/schema"] @@ -79,8 +81,8 @@ vergen = { workspace = true, features = ["cargo"] } [package.metadata.cargo-all-features] denylist = [ - "schema-endpoint", - "telemetry", - "test-network", + "schema-endpoint", + "telemetry", + "test-network", ] skip_optional_dependencies = true diff --git a/cli/src/lib.rs b/cli/src/lib.rs index eb631467a21..dbca39e8a81 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -6,8 +6,9 @@ //! should be constructed externally: (see `main.rs`). #[cfg(debug_assertions)] use core::sync::atomic::{AtomicBool, Ordering}; -use std::{path::Path, sync::Arc}; +use std::{path::PathBuf, sync::Arc}; +use clap::Parser; use color_eyre::eyre::{eyre, Result, WrapErr}; use iroha_config::parameters::{actual::Root as Config, user::CliContext}; use iroha_core::{ @@ -28,7 +29,7 @@ use iroha_core::{ }; use iroha_data_model::prelude::*; use iroha_genesis::{GenesisNetwork, RawGenesisBlock}; -use iroha_logger::actor::LoggerHandle; +use iroha_logger::{actor::LoggerHandle, InitConfig as LoggerInitConfig}; use iroha_torii::Torii; use tokio::{ signal, @@ -252,10 +253,9 @@ impl Iroha { let state = Arc::new(state); let queue = Arc::new(Queue::from_config(config.queue)); - match Self::start_telemetry(&logger, &config).await? { - TelemetryStartStatus::Started => iroha_logger::info!("Telemetry started"), - TelemetryStartStatus::NotStarted => iroha_logger::warn!("Telemetry not started"), - }; + + #[cfg(feature = "telemetry")] + Self::start_telemetry(&logger, &config).await?; let kura_thread_handler = Kura::start(Arc::clone(&kura)); @@ -382,18 +382,15 @@ impl Iroha { } #[cfg(feature = "telemetry")] - async fn start_telemetry( - logger: &LoggerHandle, - config: &Config, - ) -> Result { + async fn start_telemetry(logger: &LoggerHandle, config: &Config) -> Result<()> { #[cfg(feature = "dev-telemetry")] { - if let Some(config) = &config.dev_telemetry { + if let Some(out_file) = &config.dev_telemetry.out_file { let receiver = logger .subscribe_on_telemetry(iroha_logger::telemetry::Channel::Future) .await .wrap_err("Failed to subscribe on telemetry")?; - let _handle = iroha_telemetry::dev::start(config.clone(), receiver) + let _handle = iroha_telemetry::dev::start_file_output(out_file.clone(), receiver) .await .wrap_err("Failed to setup telemetry for futures")?; } @@ -407,21 +404,14 @@ impl Iroha { let _handle = iroha_telemetry::ws::start(config.clone(), receiver) .await .wrap_err("Failed to setup telemetry for websocket communication")?; - - Ok(TelemetryStartStatus::Started) + iroha_logger::info!("Telemetry started"); + Ok(()) } else { - Ok(TelemetryStartStatus::NotStarted) + iroha_logger::warn!("Telemetry not started - make sure you have configured the `telemetry` configuration section properly"); + Ok(()) } } - #[cfg(not(feature = "telemetry"))] - async fn start_telemetry( - _logger: &LoggerHandle, - _config: &Config, - ) -> Result { - Ok(TelemetryStartStatus::NotStarted) - } - fn start_listening_signal(notify_shutdown: Arc) -> Result> { let (mut sigint, mut sigterm) = signal::unix::signal(signal::unix::SignalKind::interrupt()) .and_then(|sigint| { @@ -481,11 +471,6 @@ impl Iroha { } } -enum TelemetryStartStatus { - Started, - NotStarted, -} - fn genesis_account(public_key: PublicKey) -> Account { Account::new(iroha_genesis::GENESIS_ACCOUNT_ID.clone(), public_key) .build(&iroha_genesis::GENESIS_ACCOUNT_ID) @@ -503,20 +488,24 @@ fn genesis_domain(public_key: PublicKey) -> Domain { domain } -/// Read configuration and then a genesis block if specified. +/// Read the configuration and then a genesis block if specified. /// /// # Errors /// - If failed to read the config /// - If failed to load the genesis block /// - If failed to build a genesis network -pub fn read_config_and_genesis>( - path: Option

, - submit_genesis: bool, -) -> Result<(Config, Option)> { +pub fn read_config_and_genesis( + args: &Args, +) -> Result<(Config, LoggerInitConfig, Option)> { use iroha_config::parameters::actual::Genesis; - let config = Config::load(path, CliContext { submit_genesis }) - .wrap_err("failed to load configuration")?; + let config = Config::load( + args.config.as_ref(), + CliContext { + submit_genesis: args.submit_genesis, + }, + ) + .wrap_err("failed to load configuration")?; let genesis = if let Genesis::Full { key_pair, file } = &config.genesis { let raw_block = RawGenesisBlock::from_path(file)?; @@ -530,7 +519,62 @@ pub fn read_config_and_genesis>( None }; - Ok((config, genesis)) + let logger_config = LoggerInitConfig::new(config.logger, args.terminal_colors); + + #[cfg(not(feature = "telemetry"))] + if config.telemetry.is_some() { + // TODO: use a centralized configuration logging + // https://github.com/hyperledger/iroha/issues/4300 + eprintln!("`telemetry` config is specified, but ignored, because Iroha is compiled without `telemetry` feature enabled"); + } + + Ok((config, logger_config, genesis)) +} + +#[allow(missing_docs)] +pub fn is_colouring_supported() -> bool { + supports_color::on(supports_color::Stream::Stdout).is_some() +} + +fn default_terminal_colors_str() -> clap::builder::OsStr { + is_colouring_supported().to_string().into() +} + +/// Iroha peer Command-Line Interface. +#[derive(Parser, Debug)] +#[command(name = "iroha", version = concat!("version=", env!("CARGO_PKG_VERSION"), " git_commit_sha=", env!("VERGEN_GIT_SHA")), author)] +pub struct Args { + /// Path to the configuration file + #[arg(long, short, value_name("PATH"), value_hint(clap::ValueHint::FilePath))] + pub config: Option, + /// Whether to enable ANSI colored output or not + /// + /// By default, Iroha determines whether the terminal supports colors or not. + /// + /// In order to disable this flag explicitly, pass `--terminal-colors=false`. + #[arg( + long, + env, + default_missing_value("true"), + default_value(default_terminal_colors_str()), + action(clap::ArgAction::Set), + require_equals(true), + num_args(0..=1), + )] + pub terminal_colors: bool, + /// Whether the current peer should submit the genesis block or not + /// + /// Only one peer in the network should submit the genesis block. + /// + /// This argument must be set alongside with `genesis.file` and `genesis.private_key` + /// configuration options. If not, Iroha will exit with an error. + /// + /// In case when the network consists only of this one peer, i.e. the amount of trusted + /// peers in the configuration (`sumeragi.trusted_peers`) is less than 2, this peer must + /// submit the genesis, since there are no other peers who can provide it. In this case, Iroha + /// will exit with an error if `--submit-genesis` is not set. + #[arg(long)] + pub submit_genesis: bool, } #[cfg(test)] @@ -624,7 +668,11 @@ mod tests { // When - let (config, genesis) = read_config_and_genesis(Some(config_path), true)?; + let (config, _logger, genesis) = read_config_and_genesis(&Args { + config: Some(config_path), + submit_genesis: true, + terminal_colors: false, + })?; // Then @@ -642,8 +690,8 @@ mod tests { assert_eq!( config .dev_telemetry - .expect("dev telemetry should be set") .out_file + .expect("dev telemetry should be set") .absolutize()?, dir.path().join("logs/telemetry") ); @@ -673,7 +721,12 @@ mod tests { // When & Then - let report = read_config_and_genesis(Some(config_path), false).unwrap_err(); + let report = read_config_and_genesis(&Args { + config: Some(config_path), + submit_genesis: false, + terminal_colors: false, + }) + .unwrap_err(); assert_contains!( format!("{report:#}"), diff --git a/cli/src/main.rs b/cli/src/main.rs index 34c7909ef9d..320f6944811 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,53 +1,9 @@ //! Iroha peer command-line interface. -use std::{env, path::PathBuf}; +use std::env; use clap::Parser; use color_eyre::eyre::Result; - -fn is_colouring_supported() -> bool { - supports_color::on(supports_color::Stream::Stdout).is_some() -} - -fn default_terminal_colors_str() -> clap::builder::OsStr { - is_colouring_supported().to_string().into() -} - -/// Iroha peer Command-Line Interface. -#[derive(Parser, Debug)] -#[command(name = "iroha", version = concat!("version=", env!("CARGO_PKG_VERSION"), " git_commit_sha=", env!("VERGEN_GIT_SHA")), author)] -struct Args { - /// Path to the configuration file - #[arg(long, short, value_name("PATH"), value_hint(clap::ValueHint::FilePath))] - config: Option, - /// Whether to enable ANSI colored output or not - /// - /// By default, Iroha determines whether the terminal supports colors or not. - /// - /// In order to disable this flag explicitly, pass `--terminal-colors=false`. - #[arg( - long, - env, - default_missing_value("true"), - default_value(default_terminal_colors_str()), - action(clap::ArgAction::Set), - require_equals(true), - num_args(0..=1), - )] - terminal_colors: bool, - /// Whether the current peer should submit the genesis block or not - /// - /// Only one peer in the network should submit the genesis block. - /// - /// This argument must be set alongside with `genesis.file` and `genesis.private_key` - /// configuration options. If not, Iroha will exit with an error. - /// - /// In case when the network consists only of this one peer, i.e. the amount of trusted - /// peers in the configuration (`sumeragi.trusted_peers`) is less than 2, this peer must - /// submit the genesis, since there are no other peers who can provide it. In this case, Iroha - /// will exit with an error if `--submit-genesis` is not set. - #[arg(long)] - submit_genesis: bool, -} +use iroha::Args; #[tokio::main] async fn main() -> Result<()> { @@ -57,8 +13,8 @@ async fn main() -> Result<()> { color_eyre::install()?; } - let (config, genesis) = iroha::read_config_and_genesis(args.config, args.submit_genesis)?; - let logger = iroha_logger::init_global(&config.logger, args.terminal_colors)?; + let (config, logger_config, genesis) = iroha::read_config_and_genesis(&args)?; + let logger = iroha_logger::init_global(logger_config)?; iroha_logger::info!( version = env!("CARGO_PKG_VERSION"), @@ -80,6 +36,8 @@ async fn main() -> Result<()> { #[cfg(test)] mod tests { + use iroha::is_colouring_supported; + use super::*; #[test] diff --git a/config/src/parameters/actual.rs b/config/src/parameters/actual.rs index df47ba9c2ee..7a34ce40c5e 100644 --- a/config/src/parameters/actual.rs +++ b/config/src/parameters/actual.rs @@ -42,7 +42,7 @@ pub struct Root { pub queue: Queue, pub snapshot: Snapshot, pub telemetry: Option, - pub dev_telemetry: Option, + pub dev_telemetry: DevTelemetry, pub chain_wide: ChainWide, } @@ -249,5 +249,5 @@ pub struct Telemetry { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct DevTelemetry { - pub out_file: PathBuf, + pub out_file: Option, } diff --git a/config/src/parameters/defaults.rs b/config/src/parameters/defaults.rs index a3893c19cdc..d81c08b4ac9 100644 --- a/config/src/parameters/defaults.rs +++ b/config/src/parameters/defaults.rs @@ -24,12 +24,6 @@ pub mod kura { pub const DEFAULT_STORE_DIR: &str = "./storage"; } -pub mod logger { - use iroha_primitives::addr::{socket_addr, SocketAddr}; - - pub const DEFAULT_TOKIO_CONSOLE_ADDR: SocketAddr = socket_addr!(127.0.0.1:5555); -} - pub mod network { use super::*; diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 7b92127c31b..eccef7a0ba6 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -461,7 +461,7 @@ pub struct Queue { pub future_threshold: Duration, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, Default)] pub struct Logger { /// Level of logging verbosity // TODO: parse user provided value in a case insensitive way, @@ -470,18 +470,6 @@ pub struct Logger { pub level: Level, /// Output format pub format: LoggerFormat, - /// Address of tokio console - pub tokio_console_address: SocketAddr, -} - -impl Default for Logger { - fn default() -> Self { - Self { - level: Level::default(), - format: LoggerFormat::default(), - tokio_console_address: super::defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR, - } - } } #[derive(Debug)] @@ -501,7 +489,7 @@ pub struct TelemetryDev { } impl Telemetry { - fn parse(self) -> Result<(Option, Option), Report> { + fn parse(self) -> Result<(Option, actual::DevTelemetry), Report> { let Self { name, url, @@ -528,9 +516,7 @@ impl Telemetry { } }; - let dev = file.map(|file| actual::DevTelemetry { - out_file: file.clone(), - }); + let dev = actual::DevTelemetry { out_file: file }; Ok((regular, dev)) } diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 84c4a12e542..40363658153 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -505,7 +505,6 @@ impl FromEnvDefaultFallback for QueuePartial {} pub struct LoggerPartial { pub level: UserField, pub format: UserField, - pub tokio_console_address: UserField, } impl UnwrapPartial for LoggerPartial { @@ -515,10 +514,6 @@ impl UnwrapPartial for LoggerPartial { Ok(Logger { level: self.level.unwrap_or_default(), format: self.format.unwrap_or_default(), - tokio_console_address: self - .tokio_console_address - .get() - .unwrap_or_else(|| defaults::logger::DEFAULT_TOKIO_CONSOLE_ADDR.clone()), }) } } @@ -560,6 +555,7 @@ pub struct TelemetryPartial { #[serde(deny_unknown_fields, default)] pub struct TelemetryDevPartial { pub out_file: UserField, + pub tokio_console_address: UserField, } impl UnwrapPartial for TelemetryDevPartial { diff --git a/config/tests/fixtures.rs b/config/tests/fixtures.rs index 1b3cadd98d2..83e109e6a36 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -525,7 +525,7 @@ fn absolute_paths_are_preserved() { assert_eq!(cfg.kura.store_dir, PathBuf::from("/kura/store")); assert_eq!(cfg.snapshot.store_dir, PathBuf::from("/snapshot/store")); assert_eq!( - cfg.dev_telemetry.unwrap().out_file, + cfg.dev_telemetry.out_file.unwrap(), PathBuf::from("/telemetry/file.json") ); if let Genesis::Full { diff --git a/core/Cargo.toml b/core/Cargo.toml index 17d88b76cd3..0519a865991 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -18,15 +18,10 @@ categories.workspace = true workspace = true [features] -default = ["cli", "telemetry"] +default = ["telemetry"] # Support lightweight telemetry, including diagnostics telemetry = [] -# Support the included CLI -cli = [] -# Support developer-specific telemetry. -# Should not be enabled on production builds. -dev-telemetry = ["telemetry", "iroha_telemetry/dev-telemetry"] # Support Prometheus metrics. See https://prometheus.io/. expensive-telemetry = ["iroha_telemetry/metric-instrumentation"] # Profiler integration for wasmtime @@ -109,8 +104,8 @@ path = "benches/blocks/validate_blocks_oneshot.rs" [package.metadata.cargo-all-features] denylist = [ -"schema-endpoint", -"telemetry", -"test-network" + "schema-endpoint", + "telemetry", + "test-network" ] skip_optional_dependencies = true diff --git a/logger/Cargo.toml b/logger/Cargo.toml index 4c3cdbfa343..fa0d977f260 100644 --- a/logger/Cargo.toml +++ b/logger/Cargo.toml @@ -21,7 +21,7 @@ tracing-core = "0.1.31" tracing-futures = { version = "0.2.5", default-features = false, features = ["std-future", "std"] } tracing-subscriber = { workspace = true, features = ["fmt", "ansi", "json"] } tokio = { workspace = true, features = ["sync", "rt", "macros"] } -console-subscriber = { version = "0.2.0", optional = true } +console-subscriber = { version = "0.2.0", optional = true } once_cell = { workspace = true } derive_more = { workspace = true } tracing-error = "0.2.0" @@ -32,6 +32,9 @@ tokio = { workspace = true, features = ["macros", "time", "rt"] } [features] +# When this feature is enabled, tokio console will be started anyway. +# Configured via ENV: +# https://docs.rs/console-subscriber/0.2.0/console_subscriber/struct.Builder.html#method.with_default_env tokio-console = ["dep:console-subscriber", "tokio/tracing"] # Workaround to avoid activating `tokio-console` with `--all-features` flag, because `tokio-console` require `tokio_unstable` rustc flag no-tokio-console = [] diff --git a/logger/src/lib.rs b/logger/src/lib.rs index d00550e7447..35fd022889d 100644 --- a/logger/src/lib.rs +++ b/logger/src/lib.rs @@ -16,7 +16,7 @@ use color_eyre::{eyre::eyre, Report, Result}; use iroha_config::logger::into_tracing_level; pub use iroha_config::{ logger::{Format, Level}, - parameters::actual::Logger as Config, + parameters::actual::{DevTelemetry as DevTelemetryConfig, Logger as Config}, }; use tracing::subscriber::set_global_default; pub use tracing::{ @@ -41,6 +41,23 @@ fn try_set_logger() -> Result<()> { Ok(()) } +/// Configuration needed for [`init_global`]. It is a little extension of [`Config`]. +#[derive(Copy, Clone, Debug)] +pub struct InitConfig { + base: Config, + terminal_colors: bool, +} + +impl InitConfig { + /// Create new config from the base logger [`Config`] + pub fn new(base: Config, terminal_colors: bool) -> Self { + Self { + base, + terminal_colors, + } + } +} + /// Initializes the logger globally with given [`Configuration`]. /// /// Returns [`LoggerHandle`] to interact with the logger instance @@ -53,18 +70,18 @@ fn try_set_logger() -> Result<()> { /// If the logger is already set, raises a generic error. // TODO: refactor configuration in a way that `terminal_colors` is part of it // https://github.com/hyperledger/iroha/issues/3500 -pub fn init_global(configuration: &Config, terminal_colors: bool) -> Result { +pub fn init_global(config: InitConfig) -> Result { try_set_logger()?; let layer = tracing_subscriber::fmt::layer() - .with_ansi(terminal_colors) + .with_ansi(config.terminal_colors) .with_test_writer(); - match configuration.format { - Format::Full => step2(configuration, layer), - Format::Compact => step2(configuration, layer.compact()), - Format::Pretty => step2(configuration, layer.pretty()), - Format::Json => step2(configuration, layer.json()), + match config.base.format { + Format::Full => step2(config, layer), + Format::Compact => step2(config, layer.compact()), + Format::Pretty => step2(config, layer.pretty()), + Format::Json => step2(config, layer.json()), } } @@ -85,10 +102,9 @@ pub fn test_logger() -> LoggerHandle { let config = Config { level: Level::DEBUG, format: Format::Pretty, - ..Config::default() }; - init_global(&config, true).expect( + init_global(InitConfig::new(config, true)).expect( "`init_global()` or `disable_global()` should not be called before `test_logger()`", ) }) @@ -105,11 +121,11 @@ pub fn disable_global() -> Result<()> { try_set_logger() } -fn step2(configuration: &Config, layer: L) -> Result +fn step2(config: InitConfig, layer: L) -> Result where L: tracing_subscriber::Layer + Debug + Send + Sync + 'static, { - let level: tracing::Level = into_tracing_level(configuration.level); + let level: tracing::Level = into_tracing_level(config.base.level); let level_filter = tracing_subscriber::filter::LevelFilter::from_level(level); let (level_filter, level_filter_handle) = reload::Layer::new(level_filter); let subscriber = Registry::default() @@ -118,18 +134,8 @@ where .with(tracing_error::ErrorLayer::default()); #[cfg(all(feature = "tokio-console", not(feature = "no-tokio-console")))] - let subscriber = { - let console_subscriber = console_subscriber::ConsoleLayer::builder() - .server_addr( - configuration - .tokio_console_addr - .into() - .expect("Invalid address for tokio console"), - ) - .spawn(); + let subscriber = subscriber.with(console_subscriber::spawn()); - subscriber.with(console_subscriber) - }; let (subscriber, receiver) = telemetry::Layer::with_capacity(subscriber, TELEMETRY_CAPACITY); set_global_default(subscriber)?; diff --git a/logger/tests/setting_logger.rs b/logger/tests/setting_logger.rs index 6f118366562..2df0de5f548 100644 --- a/logger/tests/setting_logger.rs +++ b/logger/tests/setting_logger.rs @@ -1,13 +1,13 @@ -use iroha_logger::{init_global, Config}; +use iroha_logger::{init_global, Config, InitConfig}; #[tokio::test] async fn setting_logger_twice_fails() { let cfg = Config::default(); - let first = init_global(&cfg, false); + let first = init_global(InitConfig::new(cfg, false)); assert!(first.is_ok()); - let second = init_global(&cfg, false); + let second = init_global(InitConfig::new(cfg, false)); assert!(second.is_err()); } diff --git a/telemetry/src/dev.rs b/telemetry/src/dev.rs index 257b980165d..75f7c0188d2 100644 --- a/telemetry/src/dev.rs +++ b/telemetry/src/dev.rs @@ -1,7 +1,8 @@ -//! Module with development telemetry +//! Telemetry for development rather than production purposes -use eyre::{Result, WrapErr}; -use iroha_config::parameters::actual::DevTelemetry as Config; +use std::path::PathBuf; + +use eyre::{eyre, Result, WrapErr}; use iroha_logger::telemetry::Event as Telemetry; use tokio::{ fs::OpenOptions, @@ -14,25 +15,27 @@ use tokio_stream::{wrappers::BroadcastStream, StreamExt}; /// Starts telemetry writing to a file /// # Errors /// Fails if unable to open the file -pub async fn start(config: Config, telemetry: Receiver) -> Result> { +pub async fn start_file_output( + path: PathBuf, + telemetry: Receiver, +) -> Result> { let mut stream = crate::futures::get_stream(BroadcastStream::new(telemetry).fuse()); let mut file = OpenOptions::new() - .write(true) - // Fails to write full item at exit. that is why not append - // TODO: think of workaround with dropcheck? - // - //.append(true) - .create(true) - .truncate(true) - .open(config.out_file) - .await - .wrap_err("Failed to create and open file for telemetry")?; + .write(true) + .append(true) + .create(true) + .open(&path) + .await + .wrap_err_with(|| { + eyre!( + "failed to open the target file for telemetry: {}", + path.display() + ) + })?; // Serde doesn't support async Read Write traits. // So let synchronous code be here. - // - // TODO: After migration to tokio move to https://docs.rs/tokio-serde let join_handle = task::spawn(async move { while let Some(item) = stream.next().await { let telemetry_json = match serde_json::to_string(&item) { From f5350724fa6fe4488ce48495b873dab812fa1dbd Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:52:57 +0900 Subject: [PATCH 04/19] [test]: fixes Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/main.rs | 2 ++ config/src/parameters/user/boilerplate.rs | 1 - config/tests/fixtures.rs | 7 +++---- config/tests/fixtures/full.toml | 1 - configs/peer.template.toml | 1 - 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 320f6944811..beec6d2019c 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -36,6 +36,8 @@ async fn main() -> Result<()> { #[cfg(test)] mod tests { + use std::path::PathBuf; + use iroha::is_colouring_supported; use super::*; diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 40363658153..90b9700b96c 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -555,7 +555,6 @@ pub struct TelemetryPartial { #[serde(deny_unknown_fields, default)] pub struct TelemetryDevPartial { pub out_file: UserField, - pub tokio_console_address: UserField, } impl UnwrapPartial for TelemetryDevPartial { diff --git a/config/tests/fixtures.rs b/config/tests/fixtures.rs index 83e109e6a36..97c6c7294b1 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -114,7 +114,6 @@ fn minimal_config_snapshot() -> Result<()> { logger: Logger { level: INFO, format: Full, - tokio_console_address: 127.0.0.1:5555, }, queue: Queue { capacity: 65536, @@ -128,7 +127,9 @@ fn minimal_config_snapshot() -> Result<()> { store_dir: "./storage/snapshot", }, telemetry: None, - dev_telemetry: None, + dev_telemetry: DevTelemetry { + out_file: None, + }, chain_wide: ChainWide { max_transactions_in_block: 512, block_time: 2s, @@ -372,7 +373,6 @@ fn full_envs_set_is_consumed() -> Result<()> { format: Some( Pretty, ), - tokio_console_address: None, }, queue: QueuePartial { capacity: None, @@ -494,7 +494,6 @@ fn multiple_extends_works() -> Result<()> { format: Some( Compact, ), - tokio_console_address: None, }"#]]; expected.assert_eq(&format!("{layer:#?}")); diff --git a/config/tests/fixtures/full.toml b/config/tests/fixtures/full.toml index f38ad0e38ef..4f5546332a7 100644 --- a/config/tests/fixtures/full.toml +++ b/config/tests/fixtures/full.toml @@ -38,7 +38,6 @@ force_soft_fork = true [logger] level = "TRACE" format = "compact" -tokio_console_address = "127.0.0.1:5555" [queue] capacity = 65536 diff --git a/configs/peer.template.toml b/configs/peer.template.toml index bc01942940e..53ada5f6f7c 100644 --- a/configs/peer.template.toml +++ b/configs/peer.template.toml @@ -42,7 +42,6 @@ [logger] # level = "INFO" # format = "full" -# tokio_console_address = "127.0.0.1:5555" ## Transactions Queue [queue] From c30eb973a57735e6ede1ce53e8f742e0629b1ea8 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 09:44:12 +0900 Subject: [PATCH 05/19] [chore]: repair `Cargo.toml` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- Cargo.toml | 149 ----------------------------------------------------- 1 file changed, 149 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f013909f54..91122c8b026 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,204 +131,55 @@ storage = { git = "https://github.com/Erigara/storage.git", rev = "e0afe4b42810e rustdoc.private_doc_tests = "deny" rust.anonymous_parameters = "deny" - rust.future_incompatible = "deny" - rust.missing_copy_implementations = "deny" - rust.missing_docs = "deny" - rust.nonstandard_style = "deny" - rust.rust_2018_idioms = "deny" - rust.trivial_casts = "deny" - rust.trivial_numeric_casts = "deny" - rust.unsafe_code = "deny" - rust.unused = "deny" - rust.unused_import_braces = "deny" - rust.variant_size_differences = "deny" - rust.explicit_outlives_requirements = "deny" - rust.non_ascii_idents = "deny" - rust.elided_lifetimes_in_paths = "allow" - rust.unknown_lints = "warn" - rust.single_use_lifetimes = "warn" - rust.unused_lifetimes = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.pedantic = { level = "warn", priority = -1 } -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.match_wildcard_for_single_variants = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.semicolon_if_nothing_returned = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.wildcard_imports = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.manual_let_else = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.enum_glob_use = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.module_name_repetitions = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.must_use_candidate = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.missing_panics_doc = "allow" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.dbg_macro = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.debug_assert_with_mut_call = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.derive_partial_eq_without_eq = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.empty_line_after_outer_attr = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.fallible_impl_from = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.future_not_send = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.iter_with_drain = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.mutex_integer = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.needless_collect = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.path_buf_push_overwrite = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.suboptimal_flops = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.trailing_empty_array = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.transmute_undefined_repr = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.trivial_regex = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.unused_peekable = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.unused_rounding = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.option_if_let_else = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.or_fun_call = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.redundant_pub_crate = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.string_lit_as_bytes = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.suspicious_operation_groupings = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.useless_let_if_seq = "warn" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.redundant_feature_names = "deny" -# TODO: reenable -# rust.unsafe_op_in_unsafe_fn = "deny" - -# pedantic clippy.wildcard_dependencies = "deny" [workspace] From 28ca209e0644c7ded84d9862af00a9fd2f1f6595 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:01:57 +0900 Subject: [PATCH 06/19] [chore]: repair `Cargo.toml` (how often should I?) Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- Cargo.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 91122c8b026..b06b72696c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,6 +148,10 @@ rust.elided_lifetimes_in_paths = "allow" rust.unknown_lints = "warn" rust.single_use_lifetimes = "warn" rust.unused_lifetimes = "warn" +# TODO: reenable +# rust.unsafe_op_in_unsafe_fn = "deny" + +# pedantic clippy.pedantic = { level = "warn", priority = -1 } clippy.match_wildcard_for_single_variants = "allow" clippy.semicolon_if_nothing_returned = "allow" @@ -157,7 +161,11 @@ clippy.enum_glob_use = "allow" clippy.module_name_repetitions = "allow" clippy.must_use_candidate = "allow" clippy.missing_panics_doc = "allow" + +# restriction clippy.dbg_macro = "deny" + +# nursery clippy.debug_assert_with_mut_call = "deny" clippy.derive_partial_eq_without_eq = "deny" clippy.empty_line_after_outer_attr = "deny" @@ -179,6 +187,8 @@ clippy.redundant_pub_crate = "warn" clippy.string_lit_as_bytes = "warn" clippy.suspicious_operation_groupings = "warn" clippy.useless_let_if_seq = "warn" + +#cargo clippy.redundant_feature_names = "deny" clippy.wildcard_dependencies = "deny" From f2abae2f9064593689ed286a55db7097b02c3ba6 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:11:13 +0900 Subject: [PATCH 07/19] [refactor]: `[telemetry.dev]` to `[dev_telemetry]` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 2 +- config/src/parameters/actual.rs | 9 +-------- config/src/parameters/user.rs | 20 +++++++++----------- config/src/parameters/user/boilerplate.rs | 22 +++++++++++++--------- config/tests/fixtures.rs | 6 +++--- config/tests/fixtures/absolute_paths.toml | 2 +- config/tests/fixtures/full.toml | 4 ++-- configs/peer.template.toml | 6 +++--- 8 files changed, 33 insertions(+), 38 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index dbca39e8a81..8f45fe8303a 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -650,7 +650,7 @@ mod tests { cfg.genesis.file.set("./genesis/gen.json".into()); cfg.kura.store_dir.set("../storage".into()); cfg.snapshot.store_dir.set("../snapshots".into()); - cfg.telemetry.dev.out_file.set("../logs/telemetry".into()); + cfg.dev_telemetry.out_file.set("../logs/telemetry".into()); toml::Value::try_from(cfg)? }; diff --git a/config/src/parameters/actual.rs b/config/src/parameters/actual.rs index 7a34ce40c5e..df23be982f7 100644 --- a/config/src/parameters/actual.rs +++ b/config/src/parameters/actual.rs @@ -16,7 +16,7 @@ use iroha_data_model::{ use iroha_primitives::{addr::SocketAddr, unique_vec::UniqueVec}; use serde::{Deserialize, Serialize}; use url::Url; -pub use user::{Logger, Queue, Snapshot}; +pub use user::{DevTelemetry, Logger, Queue, Snapshot}; use crate::{ kura::InitMode, @@ -244,10 +244,3 @@ pub struct Telemetry { pub min_retry_period: Duration, pub max_retry_delay_exponent: u8, } - -/// Complete configuration needed to start dev telemetry. -#[derive(Debug, Clone)] -#[allow(missing_docs)] -pub struct DevTelemetry { - pub out_file: Option, -} diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index eccef7a0ba6..82632255e52 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -52,6 +52,7 @@ pub struct Root { queue: Queue, snapshot: Snapshot, telemetry: Telemetry, + dev_telemetry: DevTelemetry, torii: Torii, chain_wide: ChainWide, } @@ -119,7 +120,7 @@ impl RootPartial { patch!(self.genesis.file); patch!(self.snapshot.store_dir); patch!(self.kura.store_dir); - patch!(self.telemetry.dev.out_file); + patch!(self.dev_telemetry.out_file); } // FIXME workaround the inconvenient way `Merge::merge` works @@ -182,10 +183,11 @@ impl Root { let logger = self.logger; let queue = self.queue; let snapshot = self.snapshot; + let dev_telemetry = self.dev_telemetry; let (torii, live_query_store) = self.torii.parse(); - let telemetries = self.telemetry.parse().map_or_else( + let telemetry = self.telemetry.parse().map_or_else( |err| { emitter.emit(err); None @@ -208,7 +210,7 @@ impl Root { key_pair: key_pair.unwrap(), p2p_address, }; - let (telemetry, dev_telemetry) = telemetries.unwrap(); + let telemetry = telemetry.unwrap(); let genesis = genesis.unwrap(); let sumeragi = { let mut x = sumeragi.unwrap(); @@ -480,22 +482,20 @@ pub struct Telemetry { pub url: Option, pub min_retry_period: Option, pub max_retry_delay_exponent: Option, - pub dev: TelemetryDev, } -#[derive(Debug)] -pub struct TelemetryDev { +#[derive(Debug, Clone)] +pub struct DevTelemetry { pub out_file: Option, } impl Telemetry { - fn parse(self) -> Result<(Option, actual::DevTelemetry), Report> { + fn parse(self) -> Result, Report> { let Self { name, url, max_retry_delay_exponent, min_retry_period, - dev: TelemetryDev { out_file: file }, } = self; let regular = match (name, url) { @@ -516,9 +516,7 @@ impl Telemetry { } }; - let dev = actual::DevTelemetry { out_file: file }; - - Ok((regular, dev)) + Ok(regular) } } diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 90b9700b96c..2e9b8695474 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -32,8 +32,8 @@ use crate::{ defaults::{self, chain_wide::*, network::*, queue::*, torii::*}, user, user::{ - ChainWide, Genesis, Kura, KuraDebug, Logger, Network, Queue, Root, Snapshot, Sumeragi, - SumeragiDebug, Telemetry, TelemetryDev, Torii, + ChainWide, DevTelemetry, Genesis, Kura, KuraDebug, Logger, Network, Queue, Root, + Snapshot, Sumeragi, SumeragiDebug, Telemetry, Torii, }, }, snapshot::Mode as SnapshotMode, @@ -54,6 +54,7 @@ pub struct RootPartial { pub queue: QueuePartial, pub snapshot: SnapshotPartial, pub telemetry: TelemetryPartial, + pub dev_telemetry: DevTelemetryPartial, pub torii: ToriiPartial, pub chain_wide: ChainWidePartial, } @@ -102,6 +103,7 @@ impl UnwrapPartial for RootPartial { let queue = nested!(self.queue); let snapshot = nested!(self.snapshot); let telemetry = nested!(self.telemetry); + let dev_telemetry = nested!(self.dev_telemetry); let torii = nested!(self.torii); let chain_wide = nested!(self.chain_wide); @@ -115,6 +117,7 @@ impl UnwrapPartial for RootPartial { kura: kura.unwrap(), sumeragi: sumeragi.unwrap(), telemetry: telemetry.unwrap(), + dev_telemetry: dev_telemetry.unwrap(), logger: logger.unwrap(), queue: queue.unwrap(), snapshot: snapshot.unwrap(), @@ -156,6 +159,7 @@ impl FromEnv for RootPartial { let queue = emitter.try_from_env(env); let snapshot = emitter.try_from_env(env); let telemetry = emitter.try_from_env(env); + let dev_telemetry = emitter.try_from_env(env); let torii = emitter.try_from_env(env); let chain_wide = emitter.try_from_env(env); @@ -174,6 +178,7 @@ impl FromEnv for RootPartial { queue: queue.unwrap(), snapshot: snapshot.unwrap(), telemetry: telemetry.unwrap(), + dev_telemetry: dev_telemetry.unwrap(), torii: torii.unwrap(), chain_wide: chain_wide.unwrap(), }) @@ -548,20 +553,19 @@ pub struct TelemetryPartial { pub url: UserField, pub min_retry_period: UserField, pub max_retry_delay_exponent: UserField, - pub dev: TelemetryDevPartial, } #[derive(Clone, Deserialize, Serialize, Debug, Default, Merge)] #[serde(deny_unknown_fields, default)] -pub struct TelemetryDevPartial { +pub struct DevTelemetryPartial { pub out_file: UserField, } -impl UnwrapPartial for TelemetryDevPartial { - type Output = TelemetryDev; +impl UnwrapPartial for DevTelemetryPartial { + type Output = DevTelemetry; fn unwrap_partial(self) -> UnwrapPartialResult { - Ok(TelemetryDev { + Ok(DevTelemetry { out_file: self.out_file.get(), }) } @@ -576,7 +580,6 @@ impl UnwrapPartial for TelemetryPartial { url, max_retry_delay_exponent, min_retry_period, - dev, } = self; Ok(Telemetry { @@ -584,13 +587,14 @@ impl UnwrapPartial for TelemetryPartial { url: url.get(), max_retry_delay_exponent: max_retry_delay_exponent.get(), min_retry_period: min_retry_period.get().map(HumanDuration::get), - dev: dev.unwrap_partial()?, }) } } impl FromEnvDefaultFallback for TelemetryPartial {} +impl FromEnvDefaultFallback for DevTelemetryPartial {} + #[derive(Debug, Clone, Deserialize, Serialize, Default, Merge)] #[serde(deny_unknown_fields, default)] pub struct SnapshotPartial { diff --git a/config/tests/fixtures.rs b/config/tests/fixtures.rs index 97c6c7294b1..0c0c5c586ca 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -394,9 +394,9 @@ fn full_envs_set_is_consumed() -> Result<()> { url: None, min_retry_period: None, max_retry_delay_exponent: None, - dev: TelemetryDevPartial { - out_file: None, - }, + }, + dev_telemetry: DevTelemetryPartial { + out_file: None, }, torii: ToriiPartial { address: Some( diff --git a/config/tests/fixtures/absolute_paths.toml b/config/tests/fixtures/absolute_paths.toml index c176502b257..7a5a043a4d0 100644 --- a/config/tests/fixtures/absolute_paths.toml +++ b/config/tests/fixtures/absolute_paths.toml @@ -6,7 +6,7 @@ store_dir = "/kura/store" [snapshot] store_dir = "/snapshot/store" -[telemetry.dev] +[dev_telemetry] out_file = "/telemetry/file.json" [genesis] diff --git a/config/tests/fixtures/full.toml b/config/tests/fixtures/full.toml index 4f5546332a7..ef611ea97cf 100644 --- a/config/tests/fixtures/full.toml +++ b/config/tests/fixtures/full.toml @@ -56,8 +56,8 @@ url = "http://test.com" min_retry_period = 5_000 max_retry_delay_exponent = 4 -[telemetry.dev] -out_file = "./dev-telemetry.json5" +[dev_telemetry] +out_file = "./dev-telemetry.json" [chain_wide] max_transactions_in_block = 512 diff --git a/configs/peer.template.toml b/configs/peer.template.toml index 53ada5f6f7c..aa8691bcf76 100644 --- a/configs/peer.template.toml +++ b/configs/peer.template.toml @@ -61,6 +61,6 @@ # min_retry_period = "1s" # max_retry_delay_exponent = 4 -[telemetry.dev] -## FIXME: is it JSON5? -# out_file = "./dev-telemetry.json5" +[dev_telemetry] +## A path to a file with JSON logs +# out_file = "./dev-telemetry.json" From d3ca01201a46d5b7685a694b4db4ba04636897e3 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:43:24 +0900 Subject: [PATCH 08/19] [build]: fix Iroha build with `--no-default-features` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 1 + torii/src/lib.rs | 7 +++++-- torii/src/routing.rs | 7 +++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 8f45fe8303a..72d75d98fd3 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -322,6 +322,7 @@ impl Iroha { Arc::clone(&queue), events_sender, Arc::clone(¬ify_shutdown), + #[cfg(feature = "telemetry")] sumeragi.clone(), live_query_store_handle, Arc::clone(&kura), diff --git a/torii/src/lib.rs b/torii/src/lib.rs index 46b37d5cfe0..ce43bbe8561 100644 --- a/torii/src/lib.rs +++ b/torii/src/lib.rs @@ -14,6 +14,8 @@ use std::{ use futures::{stream::FuturesUnordered, StreamExt}; use iroha_config::parameters::actual::Torii as Config; +#[cfg(feature = "telemetry")] +use iroha_core::sumeragi::SumeragiHandle; use iroha_core::{ kiso::{Error as KisoError, KisoHandle}, kura::Kura, @@ -21,7 +23,6 @@ use iroha_core::{ query::store::LiveQueryStoreHandle, queue::{self, Queue}, state::State, - sumeragi::SumeragiHandle, EventsSender, }; use iroha_data_model::ChainId; @@ -49,6 +50,7 @@ pub struct Torii { queue: Arc, events: EventsSender, notify_shutdown: Arc, + #[cfg(feature = "telemetry")] sumeragi: SumeragiHandle, query_service: LiveQueryStoreHandle, kura: Arc, @@ -67,7 +69,7 @@ impl Torii { queue: Arc, events: EventsSender, notify_shutdown: Arc, - sumeragi: SumeragiHandle, + #[cfg(feature = "telemetry")] sumeragi: SumeragiHandle, query_service: LiveQueryStoreHandle, kura: Arc, state: Arc, @@ -78,6 +80,7 @@ impl Torii { queue, events, notify_shutdown, + #[cfg(feature = "telemetry")] sumeragi, query_service, kura, diff --git a/torii/src/routing.rs b/torii/src/routing.rs index 89095543651..46281f62916 100644 --- a/torii/src/routing.rs +++ b/torii/src/routing.rs @@ -9,10 +9,9 @@ use eyre::{eyre, WrapErr}; use futures::TryStreamExt; use iroha_config::client_api::ConfigDTO; -use iroha_core::{ - query::store::LiveQueryStoreHandle, smartcontracts::query::ValidQueryRequest, - sumeragi::SumeragiHandle, -}; +#[cfg(feature = "telemetry")] +use iroha_core::sumeragi::SumeragiHandle; +use iroha_core::{query::store::LiveQueryStoreHandle, smartcontracts::query::ValidQueryRequest}; use iroha_data_model::{ block::{ stream::{BlockMessage, BlockSubscriptionRequest}, From 5ae01bb9b51d83b021759579be78b7ddc86c44da Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:44:38 +0900 Subject: [PATCH 09/19] [refactor]: move args tests to `lib.rs` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++++ cli/src/main.rs | 54 ------------------------------------------------- 2 files changed, 45 insertions(+), 54 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 72d75d98fd3..3a9302ddc0b 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -737,4 +737,49 @@ mod tests { Ok(()) } } + + #[test] + #[allow(clippy::bool_assert_comparison)] // for expressiveness + fn default_args() -> Result<()> { + let args = Args::try_parse_from(["test"])?; + + assert_eq!(args.terminal_colors, is_colouring_supported()); + assert_eq!(args.submit_genesis, false); + + Ok(()) + } + + #[test] + #[allow(clippy::bool_assert_comparison)] // for expressiveness + fn terminal_colors_works_as_expected() -> Result<()> { + fn try_with(arg: &str) -> Result { + Ok(Args::try_parse_from(["test", arg])?.terminal_colors) + } + + assert_eq!( + Args::try_parse_from(["test"])?.terminal_colors, + is_colouring_supported() + ); + assert_eq!(try_with("--terminal-colors")?, true); + assert_eq!(try_with("--terminal-colors=false")?, false); + assert_eq!(try_with("--terminal-colors=true")?, true); + assert!(try_with("--terminal-colors=random").is_err()); + + Ok(()) + } + + #[test] + fn user_provided_config_path_works() -> Result<()> { + let args = Args::try_parse_from(["test", "--config", "/home/custom/file.json"])?; + + assert_eq!(args.config, Some(PathBuf::from("/home/custom/file.json"))); + + Ok(()) + } + + #[test] + fn user_can_provide_any_extension() { + let _args = Args::try_parse_from(["test", "--config", "file.toml.but.not"]) + .expect("should allow doing this as well"); + } } diff --git a/cli/src/main.rs b/cli/src/main.rs index beec6d2019c..fe90dcd3a26 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -33,57 +33,3 @@ async fn main() -> Result<()> { Ok(()) } - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use iroha::is_colouring_supported; - - use super::*; - - #[test] - #[allow(clippy::bool_assert_comparison)] // for expressiveness - fn default_args() -> Result<()> { - let args = Args::try_parse_from(["test"])?; - - assert_eq!(args.terminal_colors, is_colouring_supported()); - assert_eq!(args.submit_genesis, false); - - Ok(()) - } - - #[test] - #[allow(clippy::bool_assert_comparison)] // for expressiveness - fn terminal_colors_works_as_expected() -> Result<()> { - fn try_with(arg: &str) -> Result { - Ok(Args::try_parse_from(["test", arg])?.terminal_colors) - } - - assert_eq!( - Args::try_parse_from(["test"])?.terminal_colors, - is_colouring_supported() - ); - assert_eq!(try_with("--terminal-colors")?, true); - assert_eq!(try_with("--terminal-colors=false")?, false); - assert_eq!(try_with("--terminal-colors=true")?, true); - assert!(try_with("--terminal-colors=random").is_err()); - - Ok(()) - } - - #[test] - fn user_provided_config_path_works() -> Result<()> { - let args = Args::try_parse_from(["test", "--config", "/home/custom/file.json"])?; - - assert_eq!(args.config, Some(PathBuf::from("/home/custom/file.json"))); - - Ok(()) - } - - #[test] - fn user_can_provide_any_extension() { - let _args = Args::try_parse_from(["test", "--config", "file.toml.but.not"]) - .expect("should allow doing this as well"); - } -} From 78860719413a4401bc971d466754a0c82c1dedcb Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:45:00 +0900 Subject: [PATCH 10/19] [feature]: add cargo features into `iroha --version` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 3a9302ddc0b..0caf4c022e8 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -543,7 +543,11 @@ fn default_terminal_colors_str() -> clap::builder::OsStr { /// Iroha peer Command-Line Interface. #[derive(Parser, Debug)] -#[command(name = "iroha", version = concat!("version=", env!("CARGO_PKG_VERSION"), " git_commit_sha=", env!("VERGEN_GIT_SHA")), author)] +#[command( + name = "iroha", + version = concat!("version=", env!("CARGO_PKG_VERSION"), " git_commit_sha=", env!("VERGEN_GIT_SHA"), " cargo_features=", env!("VERGEN_CARGO_FEATURES")), + author +)] pub struct Args { /// Path to the configuration file #[arg(long, short, value_name("PATH"), value_hint(clap::ValueHint::FilePath))] From 67f64328a11fe8dcb7ed92bc91da8b4c5fe0713a Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:47:40 +0900 Subject: [PATCH 11/19] [feature]: improve logging a bit Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 0caf4c022e8..766fb5e4352 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -408,7 +408,7 @@ impl Iroha { iroha_logger::info!("Telemetry started"); Ok(()) } else { - iroha_logger::warn!("Telemetry not started - make sure you have configured the `telemetry` configuration section properly"); + iroha_logger::info!("Telemetry not started due to absent configuration"); Ok(()) } } @@ -529,6 +529,13 @@ pub fn read_config_and_genesis( eprintln!("`telemetry` config is specified, but ignored, because Iroha is compiled without `telemetry` feature enabled"); } + #[cfg(not(feature = "dev-telemetry"))] + if config.dev_telemetry.out_file.is_some() { + // TODO: use a centralized configuration logging + // https://github.com/hyperledger/iroha/issues/4300 + eprintln!("`dev_telemetry.out_file` config is specified, but ignored, because Iroha is compiled without `dev-telemetry` feature enabled"); + } + Ok((config, logger_config, genesis)) } From 5ccbf745bad99d17be1948c0d86f839cf925e7fa Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:53:37 +0900 Subject: [PATCH 12/19] [feature]: `mkdir -r` for `dev_telemetry.out_file` Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- telemetry/src/dev.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/telemetry/src/dev.rs b/telemetry/src/dev.rs index 75f7c0188d2..6d38455401a 100644 --- a/telemetry/src/dev.rs +++ b/telemetry/src/dev.rs @@ -12,7 +12,8 @@ use tokio::{ }; use tokio_stream::{wrappers::BroadcastStream, StreamExt}; -/// Starts telemetry writing to a file +/// Starts telemetry writing to a file. Will create all parent directories. +/// /// # Errors /// Fails if unable to open the file pub async fn start_file_output( @@ -21,6 +22,17 @@ pub async fn start_file_output( ) -> Result> { let mut stream = crate::futures::get_stream(BroadcastStream::new(telemetry).fuse()); + std::fs::create_dir_all( + path.parent() + .ok_or_else(|| eyre!("the dev telemetry output file should have a parent directory"))?, + ) + .wrap_err_with(|| { + eyre!( + "failed to recursively create directories for the dev telemetry output file: {}", + path.display() + ) + })?; + let mut file = OpenOptions::new() .write(true) .append(true) @@ -29,7 +41,7 @@ pub async fn start_file_output( .await .wrap_err_with(|| { eyre!( - "failed to open the target file for telemetry: {}", + "failed to open the dev telemetry output file: {}", path.display() ) })?; From 44f63bf4bf147c05a66d58a41211ce32b877dd0d Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:04:05 +0900 Subject: [PATCH 13/19] [feature]: improve validation of paths in config Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- config/src/parameters/user.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 82632255e52..b279178b3e3 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -155,8 +155,14 @@ impl Root { }, Some, ); + if let Some(actual::Genesis::Full { file, .. }) = &genesis { + if !file.is_file() { + emitter.emit(eyre!("unable to access `genesis.file`: {}", file.display())) + } + } let kura = self.kura.parse(); + validate_directory_path(&mut emitter, &kura.store_dir, "kura.store_dir"); let sumeragi = self.sumeragi.parse().map_or_else( |err| { @@ -182,8 +188,19 @@ impl Root { let logger = self.logger; let queue = self.queue; + let snapshot = self.snapshot; + validate_directory_path(&mut emitter, &snapshot.store_dir, "snapshot.store_dir"); + let dev_telemetry = self.dev_telemetry; + if let Some(path) = &dev_telemetry.out_file { + if path.parent().is_none() { + emitter.emit(eyre!("`dev_telemetry.out_file` is not a valid file path")) + } + if path.is_dir() { + emitter.emit(eyre!("`dev_telemetry.out_file` is expected to be a file path, but it is a directory: {}", path.display())) + } + } let (torii, live_query_store) = self.torii.parse(); @@ -237,6 +254,20 @@ impl Root { } } +fn validate_directory_path( + emitter: &mut Emitter, + path: impl AsRef, + name: impl AsRef, +) { + if path.as_ref().is_file() { + emitter.emit(eyre!( + "`{}` is expected to be a directory path (existing or non-existing), but it points to an existing file: {}", + name.as_ref(), + path.as_ref().display() + )) + } +} + #[derive(Copy, Clone)] pub struct CliContext { pub submit_genesis: bool, From ba1a9790b550d698979aa5bf1d45be7465269fce Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:23:16 +0900 Subject: [PATCH 14/19] [fix]: add `\n` separator to file telemetry logs Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- telemetry/src/dev.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/telemetry/src/dev.rs b/telemetry/src/dev.rs index 6d38455401a..56530628768 100644 --- a/telemetry/src/dev.rs +++ b/telemetry/src/dev.rs @@ -3,9 +3,10 @@ use std::path::PathBuf; use eyre::{eyre, Result, WrapErr}; +use iroha_futures::FuturePollTelemetry; use iroha_logger::telemetry::Event as Telemetry; use tokio::{ - fs::OpenOptions, + fs::{File, OpenOptions}, io::AsyncWriteExt, sync::broadcast::Receiver, task::{self, JoinHandle}, @@ -50,18 +51,22 @@ pub async fn start_file_output( // So let synchronous code be here. let join_handle = task::spawn(async move { while let Some(item) = stream.next().await { - let telemetry_json = match serde_json::to_string(&item) { - Ok(json) => json, - Err(error) => { - iroha_logger::error!(%error, "Failed to serialize telemetry to json"); - continue; - } - }; - if let Err(error) = file.write_all(telemetry_json.as_bytes()).await { - iroha_logger::error!(%error, "Failed to write telemetry to file"); + if let Err(error) = write_telemetry(&mut file, &item).await { + iroha_logger::error!(%error, "failed to write telemetry") } } }); Ok(join_handle) } + +async fn write_telemetry(file: &mut File, item: &FuturePollTelemetry) -> Result<()> { + let json = serde_json::to_string(&item).wrap_err("failed to serialize telemetry to JSON")?; + file.write_vectored(&[ + std::io::IoSlice::new(json.as_bytes()), + std::io::IoSlice::new(b"\n"), + ]) + .await + .wrap_err("failed to write data to the file")?; + Ok(()) +} From 6b76f941bd88b6f46f103d5b7a68c86318061857 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:23:27 +0900 Subject: [PATCH 15/19] [chore]: update snapshot logs Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 766fb5e4352..a99f3580123 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -230,16 +230,16 @@ impl Iroha { Ok(state) => { iroha_logger::info!( at_height = state.view().height(), - "Successfully loaded state from a snapshot" + "Successfully loaded WSV from a snapshot" ); Some(state) } Err(TryReadSnapshotError::NotFound) => { - iroha_logger::info!("Didn't find a snapshot of state, creating an empty one"); + iroha_logger::info!("Didn't find a WSV snapshot; creating empty WSV"); None } Err(error) => { - iroha_logger::warn!(%error, "Failed to load state from a snapshot, creating an empty one"); + iroha_logger::warn!(%error, "Failed to load WSV from a snapshot; creating empty WSV"); None } }.unwrap_or_else(|| { From 48c73c679e865044f31d529387d257087ea646b0 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:37:02 +0900 Subject: [PATCH 16/19] [fix]: use `write_all` again Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- telemetry/src/dev.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/telemetry/src/dev.rs b/telemetry/src/dev.rs index 56530628768..43055a72339 100644 --- a/telemetry/src/dev.rs +++ b/telemetry/src/dev.rs @@ -61,12 +61,11 @@ pub async fn start_file_output( } async fn write_telemetry(file: &mut File, item: &FuturePollTelemetry) -> Result<()> { - let json = serde_json::to_string(&item).wrap_err("failed to serialize telemetry to JSON")?; - file.write_vectored(&[ - std::io::IoSlice::new(json.as_bytes()), - std::io::IoSlice::new(b"\n"), - ]) - .await - .wrap_err("failed to write data to the file")?; + let mut json = + serde_json::to_string(&item).wrap_err("failed to serialize telemetry to JSON")?; + json.push_str("\n"); + file.write_all(json.as_bytes()) + .await + .wrap_err("failed to write data to the file")?; Ok(()) } From 4a6f17ddd66581493d815f340593514dd3ab054b Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Mon, 25 Mar 2024 13:20:19 +0900 Subject: [PATCH 17/19] [fix]: disable `genesis.file` validation (#4383) Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- config/src/parameters/user.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index b279178b3e3..1a0d7a5ced1 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -155,11 +155,13 @@ impl Root { }, Some, ); - if let Some(actual::Genesis::Full { file, .. }) = &genesis { - if !file.is_file() { - emitter.emit(eyre!("unable to access `genesis.file`: {}", file.display())) - } - } + + // TODO: enable this check after fix of https://github.com/hyperledger/iroha/issues/4383 + // if let Some(actual::Genesis::Full { file, .. }) = &genesis { + // if !file.is_file() { + // emitter.emit(eyre!("unable to access `genesis.file`: {}", file.display())) + // } + // } let kura = self.kura.parse(); validate_directory_path(&mut emitter, &kura.store_dir, "kura.store_dir"); From 1c8c5e802534dd135b9f1f9de0f3d650240ca574 Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Mon, 25 Mar 2024 13:20:33 +0900 Subject: [PATCH 18/19] [test]: remove telemetry features from integration tests Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- client/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Cargo.toml b/client/Cargo.toml index 1d38df505b9..a31dbab37d3 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -83,7 +83,7 @@ iroha_wasm_builder = { workspace = true } # TODO: These three activate `transparent_api` but client should never activate this feature. # Additionally there is a dependency on iroha_core in dev-dependencies in telemetry/derive # Hopefully, once the integration tests migration is finished these can be removed -iroha = { workspace = true, features = ["dev-telemetry", "telemetry"] } +iroha = { workspace = true } iroha_genesis = { workspace = true } test_network = { workspace = true } From 95983d46cd099d269284f527519e00399c7e77dd Mon Sep 17 00:00:00 2001 From: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:31:23 +0900 Subject: [PATCH 19/19] [chore]: revert "WSV" logs Signed-off-by: Dmitry Balashov <43530070+0x009922@users.noreply.github.com> --- cli/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index a99f3580123..1c3b107bcc6 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -230,16 +230,16 @@ impl Iroha { Ok(state) => { iroha_logger::info!( at_height = state.view().height(), - "Successfully loaded WSV from a snapshot" + "Successfully loaded the state from a snapshot" ); Some(state) } Err(TryReadSnapshotError::NotFound) => { - iroha_logger::info!("Didn't find a WSV snapshot; creating empty WSV"); + iroha_logger::info!("Didn't find a state snapshot; creating an empty state"); None } Err(error) => { - iroha_logger::warn!(%error, "Failed to load WSV from a snapshot; creating empty WSV"); + iroha_logger::warn!(%error, "Failed to load the state from a snapshot; creating an empty state"); None } }.unwrap_or_else(|| {