diff --git a/Cargo.toml b/Cargo.toml index 9d82e9a11eb..eaa1f4c38d8 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" @@ -138,117 +129,256 @@ toml = "0.8.8" 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 9ebcce6f929..4685dc9b380 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, @@ -250,10 +251,9 @@ impl Iroha { }); 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)); @@ -377,18 +377,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")?; } @@ -402,21 +399,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| { @@ -476,11 +466,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) @@ -498,33 +483,92 @@ 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)?; Some( GenesisNetwork::new(raw_block, &config.common.chain_id, key_pair) - .wrap_err("Failed to construct the genesis")?, + .wrap_err("failed to construct the genesis")?, ) } else { 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)] @@ -617,7 +661,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 @@ -635,8 +683,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") ); @@ -666,7 +714,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 9c97fc37e9c..8c5674f3b75 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -495,7 +495,6 @@ impl FromEnvDefaultFallback for QueuePartial {} pub struct LoggerPartial { pub level: UserField, pub format: UserField, - pub tokio_console_address: UserField, } impl UnwrapPartial for LoggerPartial { @@ -505,10 +504,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()), }) } } @@ -550,6 +545,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 318d46c37dd..8824baf2138 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -511,7 +511,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 e2f86e46f47..0e4eec9e220 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 @@ -108,8 +103,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) {