From a9ea25181199f05938205c85e9d7bff7db6e57c1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 22 Oct 2020 15:26:43 +0200 Subject: [PATCH 001/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- .../basic-authorship/src/basic_authorship.rs | 10 +- client/consensus/aura/src/lib.rs | 18 +- client/consensus/babe/src/lib.rs | 18 +- client/consensus/slots/src/lib.rs | 43 ++- client/finality-grandpa/src/authorities.rs | 8 +- .../src/communication/gossip.rs | 18 +- .../finality-grandpa/src/communication/mod.rs | 307 ++++++++++-------- client/finality-grandpa/src/environment.rs | 14 +- client/finality-grandpa/src/finality_proof.rs | 5 +- client/finality-grandpa/src/import.rs | 8 +- client/finality-grandpa/src/lib.rs | 29 +- client/finality-grandpa/src/light_import.rs | 10 +- client/finality-grandpa/src/observer.rs | 10 + client/service/src/client/client.rs | 13 +- client/service/src/client/light.rs | 4 +- client/service/src/metrics.rs | 11 +- client/telemetry/src/lib.rs | 6 +- client/tracing/src/lib.rs | 15 +- 18 files changed, 344 insertions(+), 203 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 89edfac0d4e98..d5d8657bd7754 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -32,7 +32,7 @@ use sp_runtime::{ traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256}, }; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; -use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; use sp_api::{ProvideRuntimeApi, ApiExt}; use futures::{future, future::{Future, FutureExt}, channel::oneshot, select}; @@ -51,6 +51,8 @@ pub struct ProposerFactory { transaction_pool: Arc, /// Prometheus Link, metrics: PrometheusMetrics, + /// Logger instance used for metrics. + logger: Logger, /// phantom member to pin the `Backend` type. _phantom: PhantomData, } @@ -61,12 +63,14 @@ impl ProposerFactory { client: Arc, transaction_pool: Arc, prometheus: Option<&PrometheusRegistry>, + logger: Logger, ) -> Self { ProposerFactory { spawn_handle: Box::new(spawn_handle), client, transaction_pool, metrics: PrometheusMetrics::new(prometheus), + logger, _phantom: PhantomData, } } @@ -102,6 +106,7 @@ impl ProposerFactory transaction_pool: self.transaction_pool.clone(), now, metrics: self.metrics.clone(), + logger: self.logger.clone(), _phantom: PhantomData, }; @@ -142,6 +147,7 @@ pub struct Proposer { transaction_pool: Arc, now: Box time::Instant + Send + Sync>, metrics: PrometheusMetrics, + logger: Logger, _phantom: PhantomData, } @@ -325,7 +331,7 @@ impl Proposer .collect::>() .join(", ") ); - telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing"; + telemetry!(self.logger; CONSENSUS_INFO; "prepared_block_for_proposing"; "number" => ?block.header().number(), "hash" => ?::Hash::from(block.header().hash()), ); diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 426a0e873f2e9..fe8a9631f2ce0 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -69,7 +69,7 @@ use sp_inherents::{InherentDataProviders, InherentData}; use sp_timestamp::{ TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError }; -use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; use sc_consensus_slots::{ CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, StorageChanges, check_equivocation, @@ -149,6 +149,7 @@ pub fn start_aura( force_authoring: bool, keystore: SyncCryptoStorePtr, can_author_with: CAW, + logger: Logger, ) -> Result, sp_consensus::Error> where B: BlockT, C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, @@ -171,6 +172,7 @@ pub fn start_aura( keystore, sync_oracle: sync_oracle.clone(), force_authoring, + logger, _key_type: PhantomData::

, }; register_aura_inherent_data_provider( @@ -195,6 +197,7 @@ struct AuraWorker { keystore: SyncCryptoStorePtr, sync_oracle: SO, force_authoring: bool, + logger: Logger, _key_type: PhantomData

, } @@ -351,6 +354,10 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW Some(slot_remaining) } } + + fn logger(&self) -> Logger { + self.logger.clone() + } } impl SlotWorker for AuraWorker where @@ -500,6 +507,7 @@ pub struct AuraVerifier { phantom: PhantomData

, inherent_data_providers: sp_inherents::InherentDataProviders, can_author_with: CAW, + logger: Logger, } impl AuraVerifier where @@ -551,7 +559,7 @@ impl AuraVerifier where "halting for block {} seconds in the future", diff ); - telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block"; + telemetry!(self.logger; CONSENSUS_INFO; "aura.halting_for_future_block"; "diff" => ?diff ); thread::sleep(Duration::from_secs(diff)); @@ -641,7 +649,7 @@ impl Verifier for AuraVerifier where } trace!(target: "aura", "Checked {:?}; importing.", pre_header); - telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); + telemetry!(self.logger; CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); // Look for an authorities-change log. let maybe_keys = pre_header.digest() @@ -668,7 +676,7 @@ impl Verifier for AuraVerifier where } CheckedHeader::Deferred(a, b) => { debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); - telemetry!(CONSENSUS_DEBUG; "aura.header_too_far_in_future"; + telemetry!(self.logger; CONSENSUS_DEBUG; "aura.header_too_far_in_future"; "hash" => ?hash, "a" => ?a, "b" => ?b ); Err(format!("Header {:?} rejected: too far in the future", hash)) @@ -839,6 +847,7 @@ pub fn import_queue( spawner: &S, registry: Option<&Registry>, can_author_with: CAW, + logger: Logger, ) -> Result, sp_consensus::Error> where B: BlockT, C::Api: BlockBuilderApi + AuraApi> + ApiExt, @@ -859,6 +868,7 @@ pub fn import_queue( inherent_data_providers, phantom: PhantomData, can_author_with, + logger, }; Ok(BasicQueue::new( diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 6105e9876bb5e..6a55649337b2d 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -92,7 +92,7 @@ use sp_runtime::{ use sp_api::{ProvideRuntimeApi, NumberFor}; use parking_lot::Mutex; use sp_inherents::{InherentDataProviders, InherentData}; -use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; use sp_consensus::{ self, BlockImport, Environment, Proposer, BlockCheckParams, ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, @@ -358,6 +358,9 @@ pub struct BabeParams { /// Checks if the current native implementation can author with a runtime at a given block. pub can_author_with: CAW, + + /// Logger instant use for metrics. + pub logger: Logger, } /// Start the babe worker. @@ -372,6 +375,7 @@ pub fn start_babe(BabeParams { force_authoring, babe_link, can_author_with, + logger, }: BabeParams) -> Result< BabeWorker, sp_consensus::Error, @@ -402,6 +406,7 @@ pub fn start_babe(BabeParams { epoch_changes: babe_link.epoch_changes.clone(), slot_notification_sinks: slot_notification_sinks.clone(), config: config.clone(), + logger, }; register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; @@ -472,6 +477,7 @@ struct BabeSlotWorker { epoch_changes: SharedEpochChanges, slot_notification_sinks: SlotNotificationSinks, config: Config, + logger: Logger, } impl sc_consensus_slots::SimpleSlotWorker for BabeSlotWorker where @@ -665,6 +671,10 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeSlot Some(slot_remaining) } } + + fn logger(&self) -> Logger { + self.logger.clone() + } } impl SlotWorker for BabeSlotWorker where @@ -796,6 +806,7 @@ pub struct BabeVerifier { epoch_changes: SharedEpochChanges, time_source: TimeSource, can_author_with: CAW, + logger: Logger, } impl BabeVerifier @@ -1024,6 +1035,7 @@ where trace!(target: "babe", "Checked {:?}; importing.", pre_header); telemetry!( + self.logger; CONSENSUS_TRACE; "babe.checked_and_importing"; "pre_header" => ?pre_header); @@ -1042,7 +1054,7 @@ where } CheckedHeader::Deferred(a, b) => { debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); - telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future"; + telemetry!(self.logger; CONSENSUS_DEBUG; "babe.header_too_far_in_future"; "hash" => ?hash, "a" => ?a, "b" => ?b ); Err(Error::::TooFarInFuture(hash).into()) @@ -1450,6 +1462,7 @@ pub fn import_queue( spawner: &impl sp_core::traits::SpawnNamed, registry: Option<&Registry>, can_author_with: CAW, + logger: Logger, ) -> ClientResult> where Inner: BlockImport> + Send + Sync + 'static, @@ -1469,6 +1482,7 @@ pub fn import_queue( epoch_changes: babe_link.epoch_changes, time_source: babe_link.time_source, can_author_with, + logger, }; Ok(BasicQueue::new( diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 7d346ffe3954d..c98419d806712 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -39,7 +39,7 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header, HashFor, NumberFor}; use sp_api::{ProvideRuntimeApi, ApiRef}; use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc, time::{Instant, Duration}}; -use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; use parking_lot::Mutex; /// The changes that need to applied to the storage to create the state for a block. @@ -144,6 +144,9 @@ pub trait SimpleSlotWorker { /// Returns a `Proposer` to author on top of the given block. fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer; + /// Returns the `Logger` instance used for metrics. + fn logger(&self) -> Logger; + /// Remaining duration of the slot. fn slot_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { let now = Instant::now(); @@ -169,6 +172,8 @@ pub trait SimpleSlotWorker { Self: Send + Sync, >::Proposal: Unpin + Send + 'static, { + let logger = self.logger(); + let (timestamp, slot_number, slot_duration) = (slot_info.timestamp, slot_info.number, slot_info.duration); @@ -191,7 +196,7 @@ pub trait SimpleSlotWorker { warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err); telemetry!( - CONSENSUS_WARN; "slots.unable_fetching_authorities"; + logger; CONSENSUS_WARN; "slots.unable_fetching_authorities"; "slot" => ?chain_head.hash(), "err" => ?err, ); @@ -210,7 +215,7 @@ pub trait SimpleSlotWorker { { debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network."); telemetry!( - CONSENSUS_DEBUG; + logger; CONSENSUS_DEBUG; "slots.skipping_proposal_slot"; "authorities_len" => authorities_len, ); @@ -229,20 +234,23 @@ pub trait SimpleSlotWorker { timestamp, ); - telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship"; + telemetry!(logger; CONSENSUS_DEBUG; "slots.starting_authorship"; "slot_num" => slot_number, "timestamp" => timestamp, ); - let awaiting_proposer = self.proposer(&chain_head).map_err(move |err| { - warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); + let awaiting_proposer = { + let logger = logger.clone(); + self.proposer(&chain_head).map_err(move |err| { + warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); - telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block"; - "slot" => slot_number, "err" => ?err - ); + telemetry!(logger; CONSENSUS_WARN; "slots.unable_authoring_block"; + "slot" => slot_number, "err" => ?err + ); - err - }); + err + }) + }; let slot_remaining_duration = self.slot_remaining_duration(&slot_info); let proposing_remaining_duration = self.proposing_remaining_duration(&chain_head, &slot_info); @@ -263,7 +271,8 @@ pub trait SimpleSlotWorker { None => Box::new(future::pending()), }; - let proposal_work = + let proposal_work = { + let logger = logger.clone(); Box::new(futures::future::select(proposing, delay).map(move |v| match v { futures::future::Either::Left((b, _)) => b.map(|b| (b, claim)), futures::future::Either::Right(_) => { @@ -271,16 +280,18 @@ pub trait SimpleSlotWorker { // If the node was compiled with debug, tell the user to use release optimizations. #[cfg(build_type="debug")] info!("👉 Recompile your node in `--release` mode to mitigate this problem."); - telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; + telemetry!(logger; CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; "slot" => slot_number, ); Err(sp_consensus::Error::ClientImport("Timeout in the Slots proposer".into())) }, - })); + })) + }; let block_import_params_maker = self.block_import_params(); let block_import = self.block_import(); let logging_target = self.logging_target(); + let logger = logger.clone(); Box::pin(proposal_work.and_then(move |(proposal, claim)| { let (header, body) = proposal.block.deconstruct(); @@ -309,7 +320,7 @@ pub trait SimpleSlotWorker { header_hash, ); - telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block"; + telemetry!(logger; CONSENSUS_INFO; "slots.pre_sealed_block"; "header_num" => ?header_num, "hash_now" => ?block_import_params.post_hash(), "hash_previously" => ?header_hash, @@ -322,7 +333,7 @@ pub trait SimpleSlotWorker { err, ); - telemetry!(CONSENSUS_WARN; "slots.err_with_block_built_on"; + telemetry!(logger; CONSENSUS_WARN; "slots.err_with_block_built_on"; "hash" => ?parent_hash, "err" => ?err, ); } diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 57c30bc3b25c9..f100695318d2c 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -23,7 +23,7 @@ use parking_lot::RwLock; use finality_grandpa::voter_set::VoterSet; use parity_scale_codec::{Encode, Decode}; use log::debug; -use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList}; use std::cmp::Ord; @@ -352,6 +352,7 @@ where best_number: N, is_descendent_of: &F, initial_sync: bool, + logger: &Logger, ) -> Result, E> where F: Fn(&H, &H) -> Result, { @@ -369,7 +370,7 @@ where "👴 Applying authority set change forced at block #{:?}", change.canon_height, ); - telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; + telemetry!(logger; CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; "block" => ?change.canon_height ); @@ -411,6 +412,7 @@ where finalized_number: N, is_descendent_of: &F, initial_sync: bool, + logger: &Logger, ) -> Result, Error> where F: Fn(&H, &H) -> Result, E: std::error::Error, @@ -450,7 +452,7 @@ where "👴 Applying authority set change scheduled at block #{:?}", change.canon_height, ); - telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; + telemetry!(logger; CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; "block" => ?change.canon_height ); diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 276529d555ffe..e6cabc5fe062f 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -85,6 +85,7 @@ use sp_runtime::traits::{NumberFor, Block as BlockT, Zero}; use sc_network_gossip::{MessageIntent, ValidatorContext}; use sc_network::{ObservedRole, PeerId, ReputationChange}; +use sc_telemetry::slog::Logger; use parity_scale_codec::{Encode, Decode}; use sp_finality_grandpa::AuthorityId; @@ -680,12 +681,13 @@ struct Inner { next_rebroadcast: Instant, pending_catch_up: PendingCatchUp, catch_up_config: CatchUpConfig, + logger: Logger, } type MaybeMessage = Option<(Vec, NeighborPacket>)>; impl Inner { - fn new(config: crate::Config) -> Self { + fn new(config: crate::Config, logger: Logger) -> Self { let catch_up_config = if config.observer_enabled { if config.is_authority { // since the observer protocol is enabled, we will only issue @@ -712,6 +714,7 @@ impl Inner { pending_catch_up: PendingCatchUp::None, catch_up_config, config, + logger, } } @@ -829,7 +832,7 @@ impl Inner { // ensure authority is part of the set. if !self.authorities.contains(&full.message.id) { debug!(target: "afg", "Message from unknown voter: {}", full.message.id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); return Action::Discard(cost::UNKNOWN_VOTER); } @@ -841,7 +844,7 @@ impl Inner { full.set_id.0, ) { debug!(target: "afg", "Bad message signature {}", full.message.id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); return Action::Discard(cost::BAD_SIGNATURE); } @@ -867,7 +870,7 @@ impl Inner { if full.message.precommits.len() != full.message.auth_data.len() || full.message.precommits.is_empty() { debug!(target: "afg", "Malformed compact commit"); - telemetry!(CONSENSUS_DEBUG; "afg.malformed_compact_commit"; + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.malformed_compact_commit"; "precommits_len" => ?full.message.precommits.len(), "auth_data_len" => ?full.message.auth_data.len(), "precommits_is_empty" => ?full.message.precommits.is_empty(), @@ -1280,6 +1283,7 @@ pub(super) struct GossipValidator { set_state: environment::SharedVoterSetState, report_sender: TracingUnboundedSender, metrics: Option, + logger: Logger, } impl GossipValidator { @@ -1290,6 +1294,7 @@ impl GossipValidator { config: crate::Config, set_state: environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, + logger: Logger, ) -> (GossipValidator, TracingUnboundedReceiver) { let metrics = match prometheus_registry.map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), @@ -1302,10 +1307,11 @@ impl GossipValidator { let (tx, rx) = tracing_unbounded("mpsc_grandpa_gossip_validator"); let val = GossipValidator { - inner: parking_lot::RwLock::new(Inner::new(config)), + inner: parking_lot::RwLock::new(Inner::new(config, logger.clone())), set_state, report_sender: tx, metrics, + logger, }; (val, rx) @@ -1414,7 +1420,7 @@ impl GossipValidator { Err(e) => { message_name = None; debug!(target: "afg", "Error decoding message: {}", e.what()); - telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); let len = std::cmp::min(i32::max_value() as usize, data.len()) as i32; Action::Discard(Misbehavior::UndecodablePacket(len).cost()) diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 3daffcb9f2522..440eff5ef3cd9 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -42,7 +42,7 @@ use sc_network::{NetworkService, ReputationChange}; use sc_network_gossip::{GossipEngine, Network as GossipNetwork}; use parity_scale_codec::{Encode, Decode}; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; -use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; use crate::{ CatchUp, Commit, CommunicationIn, CommunicationOutH, @@ -170,6 +170,7 @@ pub(crate) struct NetworkBridge> { service: N, gossip_engine: Arc>>, validator: Arc>, + logger: Logger, /// Sender side of the neighbor packet channel. /// @@ -205,11 +206,13 @@ impl> NetworkBridge { config: crate::Config, set_state: crate::environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, + logger: Logger, ) -> Self { let (validator, report_stream) = GossipValidator::new( config, set_state.clone(), prometheus_registry, + logger.clone(), ); let validator = Arc::new(validator); @@ -267,6 +270,7 @@ impl> NetworkBridge { neighbor_sender: neighbor_packet_sender, neighbor_packet_worker: Arc::new(Mutex::new(neighbor_packet_worker)), gossip_validator_report_stream: Arc::new(Mutex::new(report_stream)), + logger, } } @@ -319,56 +323,59 @@ impl> NetworkBridge { }); let topic = round_topic::(round.0, set_id.0); - let incoming = self.gossip_engine.lock().messages_for(topic) - .filter_map(move |notification| { - let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); - - match decoded { - Err(ref e) => { - debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); - future::ready(None) - } - Ok(GossipMessage::Vote(msg)) => { - // check signature. - if !voters.contains(&msg.message.id) { - debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); - return future::ready(None); + let incoming = { + let logger = self.logger.clone(); + self.gossip_engine.lock().messages_for(topic) + .filter_map(move |notification| { + let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); + + match decoded { + Err(ref e) => { + debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); + future::ready(None) } - - if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { - match &msg.message.message { - PrimaryPropose(propose) => { - telemetry!(CONSENSUS_INFO; "afg.received_propose"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?propose.target_number, - "target_hash" => ?propose.target_hash, - ); - }, - Prevote(prevote) => { - telemetry!(CONSENSUS_INFO; "afg.received_prevote"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?prevote.target_number, - "target_hash" => ?prevote.target_hash, - ); - }, - Precommit(precommit) => { - telemetry!(CONSENSUS_INFO; "afg.received_precommit"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?precommit.target_number, - "target_hash" => ?precommit.target_hash, - ); - }, - }; + Ok(GossipMessage::Vote(msg)) => { + // check signature. + if !voters.contains(&msg.message.id) { + debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); + return future::ready(None); + } + + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { + match &msg.message.message { + PrimaryPropose(propose) => { + telemetry!(logger; CONSENSUS_INFO; "afg.received_propose"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?propose.target_number, + "target_hash" => ?propose.target_hash, + ); + }, + Prevote(prevote) => { + telemetry!(logger; CONSENSUS_INFO; "afg.received_prevote"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?prevote.target_number, + "target_hash" => ?prevote.target_hash, + ); + }, + Precommit(precommit) => { + telemetry!(logger; CONSENSUS_INFO; "afg.received_precommit"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?precommit.target_number, + "target_hash" => ?precommit.target_hash, + ); + }, + }; + } + + future::ready(Some(msg.message)) + } + _ => { + debug!(target: "afg", "Skipping unknown message type"); + future::ready(None) } - - future::ready(Some(msg.message)) - } - _ => { - debug!(target: "afg", "Skipping unknown message type"); - future::ready(None) } - } - }); + }) + }; let (tx, out_rx) = mpsc::channel(0); let outgoing = OutgoingMessages:: { @@ -378,6 +385,7 @@ impl> NetworkBridge { network: self.gossip_engine.clone(), sender: tx, has_voted, + logger: self.logger.clone(), }; // Combine incoming votes from external GRANDPA nodes with outgoing @@ -411,6 +419,7 @@ impl> NetworkBridge { voters, self.validator.clone(), self.neighbor_sender.clone(), + self.logger.clone(), ); let outgoing = CommitsOut::::new( @@ -419,6 +428,7 @@ impl> NetworkBridge { is_voter, self.validator.clone(), self.neighbor_sender.clone(), + self.logger.clone(), ); let outgoing = outgoing.with(|out| { @@ -490,110 +500,119 @@ fn incoming_global( voters: Arc>, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, + logger: Logger, ) -> impl Stream> { - let process_commit = move | - msg: FullCommitMessage, - mut notification: sc_network_gossip::TopicNotification, - gossip_engine: &Arc>>, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { - let precommits_signed_by: Vec = - msg.message.auth_data.iter().map(move |(_, a)| { - format!("{}", a) - }).collect(); - - telemetry!(CONSENSUS_INFO; "afg.received_commit"; - "contains_precommits_signed_by" => ?precommits_signed_by, - "target_number" => ?msg.message.target_number.clone(), - "target_hash" => ?msg.message.target_hash.clone(), - ); - } - - if let Err(cost) = check_compact_commit::( - &msg.message, - voters, - msg.round, - msg.set_id, - ) { - if let Some(who) = notification.sender { - gossip_engine.lock().report(who, cost); + let process_commit = { + let logger = logger.clone(); + move | + msg: FullCommitMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &Arc>>, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { + let precommits_signed_by: Vec = + msg.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + + telemetry!(logger; CONSENSUS_INFO; "afg.received_commit"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "target_number" => ?msg.message.target_number.clone(), + "target_hash" => ?msg.message.target_hash.clone(), + ); } - return None; - } - - let round = msg.round; - let set_id = msg.set_id; - let commit = msg.message; - let finalized_number = commit.target_number; - let gossip_validator = gossip_validator.clone(); - let gossip_engine = gossip_engine.clone(); - let neighbor_sender = neighbor_sender.clone(); - let cb = move |outcome| match outcome { - voter::CommitProcessingOutcome::Good(_) => { - // if it checks out, gossip it. not accounting for - // any discrepancy between the actual ghost and the claimed - // finalized number. - gossip_validator.note_commit_finalized( - round, - set_id, - finalized_number, - |to, neighbor| neighbor_sender.send(to, neighbor), - ); + if let Err(cost) = check_compact_commit::( + &msg.message, + voters, + msg.round, + msg.set_id, + &logger, + ) { + if let Some(who) = notification.sender { + gossip_engine.lock().report(who, cost); + } - gossip_engine.lock().gossip_message(topic, notification.message.clone(), false); + return None; } - voter::CommitProcessingOutcome::Bad(_) => { - // report peer and do not gossip. - if let Some(who) = notification.sender.take() { - gossip_engine.lock().report(who, cost::INVALID_COMMIT); + + let round = msg.round; + let set_id = msg.set_id; + let commit = msg.message; + let finalized_number = commit.target_number; + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); + let neighbor_sender = neighbor_sender.clone(); + let cb = move |outcome| match outcome { + voter::CommitProcessingOutcome::Good(_) => { + // if it checks out, gossip it. not accounting for + // any discrepancy between the actual ghost and the claimed + // finalized number. + gossip_validator.note_commit_finalized( + round, + set_id, + finalized_number, + |to, neighbor| neighbor_sender.send(to, neighbor), + ); + + gossip_engine.lock().gossip_message(topic, notification.message.clone(), false); } - } - }; + voter::CommitProcessingOutcome::Bad(_) => { + // report peer and do not gossip. + if let Some(who) = notification.sender.take() { + gossip_engine.lock().report(who, cost::INVALID_COMMIT); + } + } + }; - let cb = voter::Callback::Work(Box::new(cb)); + let cb = voter::Callback::Work(Box::new(cb)); - Some(voter::CommunicationIn::Commit(round.0, commit, cb)) + Some(voter::CommunicationIn::Commit(round.0, commit, cb)) + } }; - let process_catch_up = move | - msg: FullCatchUpMessage, - mut notification: sc_network_gossip::TopicNotification, - gossip_engine: &Arc>>, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - let gossip_validator = gossip_validator.clone(); - let gossip_engine = gossip_engine.clone(); + let process_catch_up = { + let logger = logger.clone(); + move | + msg: FullCatchUpMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &Arc>>, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); + + if let Err(cost) = check_catch_up::( + &msg.message, + voters, + msg.set_id, + &logger, + ) { + if let Some(who) = notification.sender { + gossip_engine.lock().report(who, cost); + } - if let Err(cost) = check_catch_up::( - &msg.message, - voters, - msg.set_id, - ) { - if let Some(who) = notification.sender { - gossip_engine.lock().report(who, cost); + return None; } - return None; - } - - let cb = move |outcome| { - if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { - // report peer - if let Some(who) = notification.sender.take() { - gossip_engine.lock().report(who, cost::INVALID_CATCH_UP); + let cb = move |outcome| { + if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { + // report peer + if let Some(who) = notification.sender.take() { + gossip_engine.lock().report(who, cost::INVALID_CATCH_UP); + } } - } - gossip_validator.note_catch_up_message_processed(); - }; + gossip_validator.note_catch_up_message_processed(); + }; - let cb = voter::Callback::Work(Box::new(cb)); + let cb = voter::Callback::Work(Box::new(cb)); - Some(voter::CommunicationIn::CatchUp(msg.message, cb)) + Some(voter::CommunicationIn::CatchUp(msg.message, cb)) + } }; gossip_engine.clone().lock().messages_for(topic) @@ -628,6 +647,7 @@ impl> Clone for NetworkBridge { neighbor_sender: self.neighbor_sender.clone(), neighbor_packet_worker: self.neighbor_packet_worker.clone(), gossip_validator_report_stream: self.gossip_validator_report_stream.clone(), + logger: self.logger.clone(), } } } @@ -654,6 +674,7 @@ pub(crate) struct OutgoingMessages { sender: mpsc::Sender>, network: Arc>>, has_voted: HasVoted, + logger: Logger, } impl Unpin for OutgoingMessages {} @@ -716,7 +737,7 @@ impl Sink> for OutgoingMessages ); telemetry!( - CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; + self.logger; CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; "block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id, ); @@ -755,6 +776,7 @@ fn check_compact_commit( voters: &VoterSet, round: Round, set_id: SetId, + logger: &Logger, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -796,7 +818,7 @@ fn check_compact_commit( &mut buf, ) { debug!(target: "afg", "Bad commit message signature {}", id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); + telemetry!(logger; CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); let cost = Misbehavior::BadCommitMessage { signatures_checked: i as i32, blocks_loaded: 0, @@ -816,6 +838,7 @@ fn check_catch_up( msg: &CatchUp, voters: &VoterSet, set_id: SetId, + logger: &Logger, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -866,6 +889,7 @@ fn check_catch_up( set_id: SetIdNumber, mut signatures_checked: usize, buf: &mut Vec, + logger: &Logger, ) -> Result where B: BlockT, I: Iterator, &'a AuthorityId, &'a AuthoritySignature)>, @@ -884,7 +908,7 @@ fn check_catch_up( buf, ) { debug!(target: "afg", "Bad catch up message signature {}", id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); + telemetry!(logger; CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); let cost = Misbehavior::BadCatchUpMessage { signatures_checked: signatures_checked as i32, @@ -908,6 +932,7 @@ fn check_catch_up( set_id.0, 0, &mut buf, + &logger, )?; // check signatures on all contained precommits. @@ -919,6 +944,7 @@ fn check_catch_up( set_id.0, signatures_checked, &mut buf, + &logger, )?; Ok(()) @@ -931,6 +957,7 @@ struct CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, + logger: Logger, } impl CommitsOut { @@ -941,6 +968,7 @@ impl CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, + logger: Logger, ) -> Self { CommitsOut { network, @@ -948,6 +976,7 @@ impl CommitsOut { is_voter, gossip_validator, neighbor_sender, + logger, } } } @@ -967,7 +996,7 @@ impl Sink<(RoundNumber, Commit)> for CommitsOut { let (round, commit) = input; let round = Round(round); - telemetry!(CONSENSUS_DEBUG; "afg.commit_issued"; + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.commit_issued"; "target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash, ); let (precommits, auth_data) = commit.precommits.into_iter() diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 95d7adb9578c5..6e25b4a038abc 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -39,7 +39,7 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, }; -use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; use crate::{ CommandOrError, Commit, Config, Error, Precommit, Prevote, @@ -423,6 +423,7 @@ pub(crate) struct Environment, SC, pub(crate) voting_rule: VR, pub(crate) metrics: Option, pub(crate) justification_sender: Option>, + pub(crate) logger: Logger, pub(crate) _phantom: PhantomData, } @@ -823,7 +824,7 @@ where }; let report_prevote_metrics = |prevote: &Prevote| { - telemetry!(CONSENSUS_DEBUG; "afg.prevote_issued"; + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.prevote_issued"; "round" => round, "target_number" => ?prevote.target_number, "target_hash" => ?prevote.target_hash, @@ -884,7 +885,7 @@ where }; let report_precommit_metrics = |precommit: &Precommit| { - telemetry!(CONSENSUS_DEBUG; "afg.precommit_issued"; + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.precommit_issued"; "round" => round, "target_number" => ?precommit.target_number, "target_hash" => ?precommit.target_hash, @@ -1078,6 +1079,7 @@ where (round, commit).into(), false, self.justification_sender.as_ref(), + self.logger.clone(), ) } @@ -1143,6 +1145,7 @@ pub(crate) fn finalize_block( justification_or_commit: JustificationOrCommit, initial_sync: bool, justification_sender: Option<&GrandpaJustificationSender>, + logger: Logger, ) -> Result<(), CommandOrError>> where Block: BlockT, @@ -1187,6 +1190,7 @@ where number, &is_descendent_of::(&*client, None), initial_sync, + &logger, ).map_err(|e| Error::Safety(e.to_string()))?; // check if this is this is the first finalization of some consensus changes @@ -1284,7 +1288,7 @@ where warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); e })?; - telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to"; + telemetry!(logger; CONSENSUS_INFO; "afg.finalized_blocks_up_to"; "number" => ?number, "hash" => ?hash, ); @@ -1304,7 +1308,7 @@ where ); } - telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set"; + telemetry!(logger; CONSENSUS_INFO; "afg.generating_new_authority_set"; "number" => ?canon_number, "hash" => ?canon_hash, "authorities" => ?set_ref.to_vec(), "set_id" => ?new_id, diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 33dd69cc11d6e..4ec690282611e 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -52,7 +52,7 @@ use sp_runtime::{ traits::{NumberFor, Block as BlockT, Header as HeaderT, One}, }; use sp_core::storage::StorageKey; -use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; use crate::justification::GrandpaJustification; @@ -468,6 +468,7 @@ pub(crate) fn check_finality_proof( current_authorities: AuthorityList, authorities_provider: &dyn AuthoritySetForFinalityChecker, remote_proof: Vec, + logger: &Logger, ) -> ClientResult> where NumberFor: BlockNumberOps, @@ -510,7 +511,7 @@ pub(crate) fn check_finality_proof( check_finality_proof_fragment always returns FinalityEffects;\ qed"); - telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok"; + telemetry!(logger; CONSENSUS_INFO; "afg.finality_proof_ok"; "set_id" => ?effects.new_set_id, "finalized_header_hash" => ?effects.block); Ok(effects) diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 04df95a3187e1..5522511af03fb 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -24,6 +24,7 @@ use parking_lot::RwLockWriteGuard; use sp_blockchain::{BlockStatus, well_known_cache_keys}; use sc_client_api::{backend::Backend, utils::is_descendent_of}; +use sc_telemetry::slog::Logger; use sp_utils::mpsc::TracingUnboundedSender; use sp_api::{TransactionFor}; @@ -64,6 +65,7 @@ pub struct GrandpaBlockImport { consensus_changes: SharedConsensusChanges>, authority_set_hard_forks: HashMap>>, justification_sender: GrandpaJustificationSender, + logger: Logger, _phantom: PhantomData, } @@ -79,6 +81,7 @@ impl Clone for consensus_changes: self.consensus_changes.clone(), authority_set_hard_forks: self.authority_set_hard_forks.clone(), justification_sender: self.justification_sender.clone(), + logger: self.logger.clone(), _phantom: PhantomData, } } @@ -337,7 +340,7 @@ where let applied_changes = { let forced_change_set = guard .as_mut() - .apply_forced_changes(hash, number, &is_descendent_of, initial_sync) + .apply_forced_changes(hash, number, &is_descendent_of, initial_sync, &self.logger) .map_err(|e| ConsensusError::ClientImport(e.to_string())) .map_err(ConsensusError::from)?; @@ -564,6 +567,7 @@ impl GrandpaBlockImport>, authority_set_hard_forks: Vec<(SetId, PendingChange>)>, justification_sender: GrandpaJustificationSender, + logger: Logger, ) -> GrandpaBlockImport { // check for and apply any forced authority set hard fork that applies // to the *current* authority set. @@ -608,6 +612,7 @@ impl GrandpaBlockImport( client: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, + logger: Logger, ) -> Result< ( GrandpaBlockImport, @@ -518,6 +519,7 @@ where genesis_authorities_provider, select_chain, Default::default(), + logger, ) } @@ -531,6 +533,7 @@ pub fn block_import_with_authority_set_hard_forks genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, + logger: Logger, ) -> Result< ( GrandpaBlockImport, @@ -552,11 +555,11 @@ where >::zero(), || { let authorities = genesis_authorities_provider.get()?; - telemetry!(CONSENSUS_DEBUG; "afg.loading_authorities"; + telemetry!(logger; CONSENSUS_DEBUG; "afg.loading_authorities"; "authorities_len" => ?authorities.len() ); Ok(authorities) - } + }, )?; let (voter_commands_tx, voter_commands_rx) = tracing_unbounded("mpsc_grandpa_voter_command"); @@ -591,6 +594,7 @@ where persistent_data.consensus_changes.clone(), authority_set_hard_forks, justification_sender.clone(), + logger, ), LinkHalf { client, @@ -665,6 +669,8 @@ pub struct GrandpaParams { pub prometheus_registry: Option, /// The voter state is exposed at an RPC endpoint. pub shared_voter_state: SharedVoterState, + /// Logger used by telemtry. + pub logger: Logger, } /// Run a GRANDPA voter as a task. Provide configuration and a link to a @@ -691,6 +697,7 @@ where voting_rule, prometheus_registry, shared_voter_state, + logger, } = grandpa_params; // NOTE: we have recently removed `run_grandpa_observer` from the public @@ -713,10 +720,12 @@ where config.clone(), persistent_data.set_state.clone(), prometheus_registry.as_ref(), + logger.clone(), ); let conf = config.clone(); let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect { + let logger = logger.clone(); let authorities = persistent_data.authority_set.clone(); let events = telemetry_on_connect .for_each(move |_| { @@ -735,7 +744,7 @@ where elements are always of type string", ); - telemetry!(CONSENSUS_INFO; "afg.authority_set"; + telemetry!(logger; CONSENSUS_INFO; "afg.authority_set"; "authority_id" => authority_id.to_string(), "authority_set_id" => ?set_id, "authorities" => authorities, @@ -759,6 +768,7 @@ where prometheus_registry, shared_voter_state, justification_sender, + logger, ); let voter_work = voter_work.map(|res| match res { @@ -797,6 +807,7 @@ struct VoterWork, SC, VR> { env: Arc>, voter_commands_rx: TracingUnboundedReceiver>>, network: NetworkBridge, + logger: Logger, /// Prometheus metrics. metrics: Option, @@ -824,6 +835,7 @@ where prometheus_registry: Option, shared_voter_state: SharedVoterState, justification_sender: GrandpaJustificationSender, + logger: Logger, ) -> Self { let metrics = match prometheus_registry.as_ref().map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), @@ -848,6 +860,7 @@ where voter_set_state: persistent_data.set_state, metrics: metrics.as_ref().map(|m| m.environment.clone()), justification_sender: Some(justification_sender), + logger: logger.clone(), _phantom: PhantomData, }); @@ -859,6 +872,7 @@ where env, voter_commands_rx, network, + logger, metrics, }; work.rebuild_voter(); @@ -874,7 +888,7 @@ where let authority_id = local_authority_id(&self.env.voters, self.env.config.keystore.as_ref()) .unwrap_or_default(); - telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; + telemetry!(self.logger; CONSENSUS_DEBUG; "afg.starting_new_voter"; "name" => ?self.env.config.name(), "set_id" => ?self.env.set_id, "authority_id" => authority_id.to_string(), @@ -893,7 +907,7 @@ where "authorities is always at least an empty vector; elements are always of type string", ); - telemetry!(CONSENSUS_INFO; "afg.authority_set"; + telemetry!(self.logger; CONSENSUS_INFO; "afg.authority_set"; "number" => ?chain_info.finalized_number, "hash" => ?chain_info.finalized_hash, "authority_id" => authority_id.to_string(), @@ -953,7 +967,7 @@ where let voters: Vec = new.authorities.iter().map(move |(a, _)| { format!("{}", a) }).collect(); - telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; + telemetry!(self.logger; CONSENSUS_INFO; "afg.voter_command_change_authorities"; "number" => ?new.canon_number, "hash" => ?new.canon_hash, "voters" => ?voters, @@ -994,6 +1008,7 @@ where voting_rule: self.env.voting_rule.clone(), metrics: self.env.metrics.clone(), justification_sender: self.env.justification_sender.clone(), + logger: self.logger.clone(), _phantom: PhantomData, }); diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs index a7c9a655467c7..054d34b39cdad 100644 --- a/client/finality-grandpa/src/light_import.rs +++ b/client/finality-grandpa/src/light_import.rs @@ -27,6 +27,7 @@ use sp_consensus::{ BlockCheckParams, Error as ConsensusError, }; use sc_network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; +use sc_telemetry::slog::Logger; use sp_runtime::Justification; use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor}; use sp_finality_grandpa::{self, AuthorityList}; @@ -52,6 +53,7 @@ pub fn light_block_import( backend: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, authority_set_provider: Arc>, + logger: Logger, ) -> Result, ClientError> where BE: Backend, @@ -68,6 +70,7 @@ pub fn light_block_import( backend, authority_set_provider, data: Arc::new(RwLock::new(import_data)), + logger, }) } @@ -81,6 +84,7 @@ pub struct GrandpaLightBlockImport { backend: Arc, authority_set_provider: Arc>, data: Arc>>, + logger: Logger, } impl Clone for GrandpaLightBlockImport { @@ -90,6 +94,7 @@ impl Clone for GrandpaLightBlockImport FinalityProofImport number, finality_proof, verifier, + &self.logger, ) } } @@ -303,6 +309,7 @@ fn do_import_finality_proof( _number: NumberFor, finality_proof: Vec, verifier: &mut dyn Verifier, + logger: &Logger, ) -> Result<(Block::Hash, NumberFor), ConsensusError> where C: HeaderBackend @@ -323,6 +330,7 @@ fn do_import_finality_proof( authorities, authority_set_provider, finality_proof, + logger, ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; // try to import all new headers @@ -834,7 +842,7 @@ pub mod tests { let initial_set = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; let updated_set = vec![(AuthorityId::from_slice(&[2; 32]), 2)]; let babe_set_signal = vec![AuthorityId::from_slice(&[42; 32])].encode(); - + // import block #1 without justification let mut cache = HashMap::new(); cache.insert(well_known_cache_keys::AUTHORITIES, babe_set_signal); diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index fd00b35c40a73..121710112f258 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -29,6 +29,7 @@ use log::{debug, info, warn}; use sp_keystore::SyncCryptoStorePtr; use sp_consensus::SelectChain; use sc_client_api::backend::Backend; +use sc_telemetry::slog::Logger; use sp_utils::mpsc::TracingUnboundedReceiver; use sp_runtime::traits::{NumberFor, Block as BlockT}; use sp_blockchain::HeaderMetadata; @@ -74,6 +75,7 @@ fn grandpa_observer( last_finalized_number: NumberFor, commits: S, note_round: F, + logger: Logger, ) -> impl Future>>> where NumberFor: BlockNumberOps, @@ -130,6 +132,7 @@ where (round, commit).into(), false, justification_sender.as_ref(), + logger.clone(), ) { Ok(_) => {}, Err(e) => return future::err(e), @@ -167,6 +170,7 @@ pub fn run_grandpa_observer( config: Config, link: LinkHalf, network: N, + logger: Logger, ) -> sp_blockchain::Result + Unpin + Send + 'static> where BE: Backend + Unpin + 'static, @@ -189,6 +193,7 @@ where config.clone(), persistent_data.set_state.clone(), None, + logger.clone(), ); let observer_work = ObserverWork::new( @@ -198,6 +203,7 @@ where config.keystore, voter_commands_rx, Some(justification_sender), + logger, ); let observer_work = observer_work @@ -219,6 +225,7 @@ struct ObserverWork> { keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, + logger: Logger, _phantom: PhantomData, } @@ -237,6 +244,7 @@ where keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, + logger: Logger, ) -> Self { let mut work = ObserverWork { @@ -249,6 +257,7 @@ where keystore: keystore.clone(), voter_commands_rx, justification_sender, + logger, _phantom: PhantomData, }; work.rebuild_observer(); @@ -299,6 +308,7 @@ where last_finalized_number, global_in, note_round, + self.logger.clone(), ); self.observer = Box::pin(observer); diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 64b00f81905dc..513aeda49de76 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -34,7 +34,7 @@ use sp_core::{ }; #[cfg(feature="test-helpers")] use sp_keystore::SyncCryptoStorePtr; -use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; use sp_runtime::{ Justification, BuildStorage, generic::{BlockId, SignedBlock, DigestItem}, @@ -114,6 +114,7 @@ pub struct Client where Block: BlockT { block_rules: BlockRules, execution_extensions: ExecutionExtensions, config: ClientConfig, + logger: Logger, _phantom: PhantomData, } @@ -153,6 +154,7 @@ pub fn new_in_mem( prometheus_registry: Option, spawn_handle: Box, config: ClientConfig, + logger: Logger, ) -> sp_blockchain::Result, LocalCallExecutor, E>, @@ -171,6 +173,7 @@ pub fn new_in_mem( spawn_handle, prometheus_registry, config, + logger, ) } @@ -194,6 +197,7 @@ pub fn new_with_backend( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, + logger: Logger, ) -> sp_blockchain::Result, Block, RA>> where E: CodeExecutor + RuntimeInfo, @@ -212,6 +216,7 @@ pub fn new_with_backend( extensions, prometheus_registry, config, + logger, ) } @@ -292,6 +297,7 @@ impl Client where execution_extensions: ExecutionExtensions, prometheus_registry: Option, config: ClientConfig, + logger: Logger, ) -> sp_blockchain::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { let genesis_storage = build_genesis_storage.build_storage()?; @@ -322,6 +328,7 @@ impl Client where block_rules: BlockRules::new(fork_blocks, bad_blocks), execution_extensions, config, + logger, _phantom: Default::default(), }) } @@ -664,7 +671,7 @@ impl Client where if origin != BlockOrigin::NetworkInitialSync || rand::thread_rng().gen_bool(0.1) { - telemetry!(SUBSTRATE_INFO; "block.import"; + telemetry!(self.logger; SUBSTRATE_INFO; "block.import"; "height" => height, "best" => ?hash, "origin" => ?origin @@ -984,7 +991,7 @@ impl Client where indicated in the tree route; qed" ); - telemetry!(SUBSTRATE_INFO; "notify.finalized"; + telemetry!(self.logger; SUBSTRATE_INFO; "notify.finalized"; "height" => format!("{}", header.number()), "best" => ?last, ); diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs index e8e1286eccdb0..e925dad494e43 100644 --- a/client/service/src/client/light.rs +++ b/client/service/src/client/light.rs @@ -30,7 +30,7 @@ use prometheus_endpoint::Registry; use super::{call_executor::LocalCallExecutor, client::{Client, ClientConfig}}; use sc_client_api::light::Storage as BlockchainStorage; use sc_light::{Backend, GenesisCallExecutor}; - +use sc_telemetry::slog::Logger; /// Create an instance of light client. pub fn new_light( @@ -39,6 +39,7 @@ pub fn new_light( code_executor: E, spawn_handle: Box, prometheus_registry: Option, + logger: Logger, ) -> ClientResult< Client< Backend>, @@ -71,5 +72,6 @@ pub fn new_light( Default::default(), prometheus_registry, ClientConfig::default(), + logger, ) } diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 0af393b53f517..d7d412beb9f0f 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -21,7 +21,7 @@ use std::{convert::TryFrom, time::SystemTime}; use crate::{NetworkStatus, NetworkState, NetworkStatusSinks, config::Configuration}; use futures_timer::Delay; use prometheus_endpoint::{register, Gauge, U64, Registry, PrometheusError, Opts, GaugeVec}; -use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; use sp_api::ProvideRuntimeApi; use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto}; use sp_transaction_pool::{PoolStatus, MaintainedTransactionPool}; @@ -112,17 +112,19 @@ pub struct MetricsService { last_update: Instant, last_total_bytes_inbound: u64, last_total_bytes_outbound: u64, + logger: Logger, } impl MetricsService { /// Creates a `MetricsService` that only sends information /// to the telemetry. - pub fn new() -> Self { + pub fn new(logger: Logger) -> Self { MetricsService { metrics: None, last_total_bytes_inbound: 0, last_total_bytes_outbound: 0, last_update: Instant::now(), + logger, } } @@ -131,6 +133,7 @@ impl MetricsService { pub fn with_prometheus( registry: &Registry, config: &Configuration, + logger: Logger, ) -> Result { let role_bits = match config.role { Role::Full => 1u64, @@ -150,6 +153,7 @@ impl MetricsService { last_total_bytes_inbound: 0, last_total_bytes_outbound: 0, last_update: Instant::now(), + logger, }) } @@ -246,6 +250,7 @@ impl MetricsService { // Update/send metrics that are always available. telemetry!( + self.logger; SUBSTRATE_INFO; "system.interval"; "height" => best_number, @@ -308,6 +313,7 @@ impl MetricsService { }; telemetry!( + self.logger; SUBSTRATE_INFO; "system.interval"; "peers" => num_peers, @@ -329,6 +335,7 @@ impl MetricsService { // Send network state information, if any. if let Some(net_state) = net_state { telemetry!( + self.logger; SUBSTRATE_INFO; "system.network_state"; "state" => net_state, diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6a5ac0e0cb312..f259ac30ad1c0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -314,10 +314,8 @@ impl slog::Drain for TelemetryDrain { /// parameter is added to the record as a key-value pair. #[macro_export] macro_rules! telemetry { - ( $a:expr; $b:expr; $( $t:tt )* ) => { - $crate::with_logger(|l| { - $crate::slog::slog_info!(l, #$a, $b; $($t)* ) - }) + ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => { + $crate::slog::slog_info!($l, #$a, $b; $($t)* ) } } diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 6690f283464ea..60197446b4570 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -38,6 +38,7 @@ use tracing::{ subscriber::Subscriber, }; use tracing_subscriber::{CurrentSpan, layer::{Layer, Context}}; +use slog::Logger; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; @@ -216,11 +217,13 @@ impl ProfilingLayer { /// either with a level: "pallet=trace,frame=debug" /// or without: "pallet,frame" in which case the level defaults to `trace`. /// wasm_tracing indicates whether to enable wasm traces - pub fn new(receiver: TracingReceiver, targets: &str) -> Self { + pub fn new(receiver: TracingReceiver, targets: &str, logger: Logger) -> Self { match receiver { TracingReceiver::Log => Self::new_with_handler(Box::new(LogTraceHandler), targets), TracingReceiver::Telemetry => Self::new_with_handler( - Box::new(TelemetryTraceHandler), + Box::new(TelemetryTraceHandler { + logger, + }), targets, ), } @@ -402,11 +405,13 @@ impl TraceHandler for LogTraceHandler { /// TraceHandler for sending span data to telemetry, /// Please see telemetry documentation for details on how to specify endpoints and /// set the required telemetry level to activate tracing messages -pub struct TelemetryTraceHandler; +pub struct TelemetryTraceHandler { + logger: Logger, +} impl TraceHandler for TelemetryTraceHandler { fn handle_span(&self, span_datum: SpanDatum) { - telemetry!(SUBSTRATE_INFO; "tracing.profiling"; + telemetry!(self.logger; SUBSTRATE_INFO; "tracing.profiling"; "name" => span_datum.name, "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), @@ -417,7 +422,7 @@ impl TraceHandler for TelemetryTraceHandler { } fn handle_event(&self, event: TraceEvent) { - telemetry!(SUBSTRATE_INFO; "tracing.event"; + telemetry!(self.logger; SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, "parent_id" => event.parent_id.map(|i| i.into_u64()), From 9e2801a55eb6ee508e69ed8c0a734b759bed1166 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 22 Oct 2020 15:51:48 +0200 Subject: [PATCH 002/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- Cargo.lock | 12 ------------ client/telemetry/Cargo.toml | 1 - client/telemetry/src/lib.rs | 12 +++++------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f43bc9e7ec839..bc1f0def07ecb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7409,7 +7409,6 @@ dependencies = [ "serde", "slog", "slog-json", - "slog-scope", "take_mut", "void", "wasm-timer", @@ -7799,17 +7798,6 @@ dependencies = [ "slog", ] -[[package]] -name = "slog-scope" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" -dependencies = [ - "arc-swap", - "lazy_static", - "slog", -] - [[package]] name = "slog_derive" version = "0.2.0" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index be7c88f68ae79..d593471696ab1 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -26,6 +26,5 @@ rand = "0.7.2" serde = { version = "1.0.101", features = ["derive"] } slog = { version = "2.5.2", features = ["nested-values"] } slog-json = { version = "2.3.0", features = ["nested-values"] } -slog-scope = "4.1.2" take_mut = "0.2.2" void = "1.0.2" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f259ac30ad1c0..ff385435ea4e9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -67,9 +67,9 @@ use parking_lot::Mutex; use serde::{Serialize, Deserialize, Deserializer}; use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::Duration}; use wasm_timer::Instant; +use slog::Logger; pub use libp2p::wasm_ext::ExtTransport; -pub use slog_scope::with_logger; pub use slog; mod async_record; @@ -164,8 +164,7 @@ pub const CONSENSUS_INFO: &str = "1"; #[derive(Clone)] pub struct Telemetry { inner: Arc>, - /// Slog guard so that we don't get deregistered. - _guard: Arc, + logger: Logger, } /// Behind the `Mutex` in `Telemetry`. @@ -196,10 +195,9 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { let (endpoints, wasm_external_transport) = (config.endpoints.0, config.wasm_external_transport); let (sender, receiver) = mpsc::channel(16); - let guard = { + let logger = { let logger = TelemetryDrain { sender: std::panic::AssertUnwindSafe(sender) }; - let root = slog::Logger::root(slog::Drain::fuse(logger), slog::o!()); - slog_scope::set_global_logger(root) + slog::Logger::root(slog::Drain::fuse(logger), slog::o!()) }; let worker = match worker::TelemetryWorker::new(endpoints, wasm_external_transport) { @@ -215,7 +213,7 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { worker, receiver, })), - _guard: Arc::new(guard), + logger, } } From c7934bb9115991a56381650826871190585d4d50 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 22 Oct 2020 16:04:02 +0200 Subject: [PATCH 003/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- client/service/src/builder.rs | 68 +++++++++++++++++++++-------------- client/telemetry/src/lib.rs | 3 +- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 3b60db7ec5854..95d74fb448f5a 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -51,7 +51,7 @@ use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; @@ -243,16 +243,18 @@ impl KeystoreContainer { /// Creates a new full client for the given config. pub fn new_full_client( config: &Configuration, + logger: Logger, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - new_full_parts(config).map(|parts| parts.0) + new_full_parts(config, logger).map(|parts| parts.0) } /// Create the initial parts of a full node. pub fn new_full_parts( config: &Configuration, + logger: Logger, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -306,6 +308,8 @@ pub fn new_full_parts( offchain_worker_enabled : config.offchain_worker.enabled , offchain_indexing_api: config.offchain_worker.indexing_enabled, }, + // TODO: maybe pass by ref + logger, )? }; @@ -319,7 +323,8 @@ pub fn new_full_parts( /// Create the initial parts of a light node. pub fn new_light_parts( - config: &Configuration + config: &Configuration, + logger: Logger, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -362,6 +367,8 @@ pub fn new_light_parts( executor, Box::new(task_manager.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), + // TODO: maybe pass by ref? + logger, )?); Ok((client, backend, keystore_container, task_manager, on_demand)) @@ -378,6 +385,7 @@ pub fn new_client( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, + logger: Logger, ) -> Result<( crate::client::Client< Backend, @@ -407,6 +415,7 @@ pub fn new_client( execution_extensions, prometheus_registry, config, + logger, )?, backend, )) @@ -531,8 +540,28 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; + // Telemetry + let telemetry = config.telemetry_endpoints.clone().and_then(|endpoints| { + if endpoints.is_empty() { + // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) + return None; + } + + let genesis_hash = match client.block_hash(Zero::zero()) { + Ok(Some(hash)) => hash, + _ => Default::default(), + }; + + Some(build_telemetry( + &mut config, endpoints, telemetry_connection_sinks.clone(), network.clone(), + task_manager.spawn_handle(), genesis_hash, + )) + }); + let logger = telemetry.as_ref().map(|x| x.logger.clone()).expect("TODO"); + info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( + logger; SUBSTRATE_INFO; "node.start"; "height" => chain_info.best_number.saturated_into::(), @@ -549,7 +578,7 @@ pub fn spawn_tasks( spawn_handle.spawn( "on-transaction-imported", - transaction_notifications(transaction_pool.clone(), network.clone()), + transaction_notifications(transaction_pool.clone(), network.clone(), logger.clone()), ); // Prometheus metrics. @@ -557,7 +586,7 @@ pub fn spawn_tasks( config.prometheus_config.clone() { // Set static metrics. - let metrics = MetricsService::with_prometheus(®istry, &config)?; + let metrics = MetricsService::with_prometheus(®istry, &config, logger)?; spawn_handle.spawn( "prometheus-endpoint", prometheus_endpoint::init_prometheus(port, registry).map(drop) @@ -565,7 +594,7 @@ pub fn spawn_tasks( metrics } else { - MetricsService::new() + MetricsService::new(logger) }; // Periodically updated metrics and telemetry updates. @@ -595,24 +624,6 @@ pub fn spawn_tasks( sc_rpc_server::RpcMiddleware::new(rpc_metrics.as_ref().cloned(), "inbrowser") ).into())); - // Telemetry - let telemetry = config.telemetry_endpoints.clone().and_then(|endpoints| { - if endpoints.is_empty() { - // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) - return None; - } - - let genesis_hash = match client.block_hash(Zero::zero()) { - Ok(Some(hash)) => hash, - _ => Default::default(), - }; - - Some(build_telemetry( - &mut config, endpoints, telemetry_connection_sinks.clone(), network.clone(), - task_manager.spawn_handle(), genesis_hash, - )) - }); - // Spawn informant task spawn_handle.spawn("informant", sc_informant::build( client.clone(), @@ -621,6 +632,7 @@ pub fn spawn_tasks( config.informant_output_format, )); + // TODO: probably dont need this anymore task_manager.keep_alive((telemetry, config.base_path, rpc, rpc_handlers.clone())); Ok(rpc_handlers) @@ -628,7 +640,8 @@ pub fn spawn_tasks( async fn transaction_notifications( transaction_pool: Arc, - network: Arc::Hash>> + network: Arc::Hash>>, + logger: Logger, ) where TBl: BlockT, @@ -639,7 +652,7 @@ async fn transaction_notifications( .for_each(move |hash| { network.propagate_transaction(hash); let status = transaction_pool.status(); - telemetry!(SUBSTRATE_INFO; "txpool.import"; + telemetry!(logger; SUBSTRATE_INFO; "txpool.import"; "ready" => status.ready, "future" => status.future ); @@ -669,6 +682,7 @@ fn build_telemetry( let startup_time = SystemTime::UNIX_EPOCH.elapsed() .map(|dur| dur.as_millis()) .unwrap_or(0); + let logger = telemetry.logger.clone(); spawn_handle.spawn( "telemetry-worker", @@ -677,7 +691,7 @@ fn build_telemetry( // Safe-guard in case we add more events in the future. let sc_telemetry::TelemetryEvent::Connected = event; - telemetry!(SUBSTRATE_INFO; "system.connected"; + telemetry!(logger; SUBSTRATE_INFO; "system.connected"; "name" => name.clone(), "implementation" => impl_name.clone(), "version" => impl_version.clone(), diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ff385435ea4e9..6c04728946032 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -164,7 +164,8 @@ pub const CONSENSUS_INFO: &str = "1"; #[derive(Clone)] pub struct Telemetry { inner: Arc>, - logger: Logger, + /// Logger used to report telemetry. + pub logger: Logger, } /// Behind the `Mutex` in `Telemetry`. From 67b1083837727c8354472d16b4923bbba6aa1b2b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 22 Oct 2020 17:15:28 +0200 Subject: [PATCH 004/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- .../basic-authorship/src/basic_authorship.rs | 6 ++--- client/consensus/aura/src/lib.rs | 10 +++---- client/consensus/babe/src/lib.rs | 10 +++---- client/consensus/slots/src/lib.rs | 2 +- client/finality-grandpa/src/authorities.rs | 4 +-- .../src/communication/gossip.rs | 8 +++--- .../finality-grandpa/src/communication/mod.rs | 26 +++++++++---------- client/finality-grandpa/src/environment.rs | 6 ++--- client/finality-grandpa/src/finality_proof.rs | 2 +- client/finality-grandpa/src/import.rs | 12 ++++++--- client/finality-grandpa/src/lib.rs | 10 +++---- client/finality-grandpa/src/light_import.rs | 8 +++--- client/finality-grandpa/src/observer.rs | 8 +++--- client/service/src/builder.rs | 14 +++++----- client/service/src/client/client.rs | 8 +++--- client/service/src/client/light.rs | 2 +- client/service/src/metrics.rs | 6 ++--- client/telemetry/src/lib.rs | 6 +++-- client/tracing/src/lib.rs | 4 +-- 19 files changed, 80 insertions(+), 72 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index d5d8657bd7754..6d170abc502d4 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -52,7 +52,7 @@ pub struct ProposerFactory { /// Prometheus Link, metrics: PrometheusMetrics, /// Logger instance used for metrics. - logger: Logger, + logger: Option, /// phantom member to pin the `Backend` type. _phantom: PhantomData, } @@ -63,7 +63,7 @@ impl ProposerFactory { client: Arc, transaction_pool: Arc, prometheus: Option<&PrometheusRegistry>, - logger: Logger, + logger: Option, ) -> Self { ProposerFactory { spawn_handle: Box::new(spawn_handle), @@ -147,7 +147,7 @@ pub struct Proposer { transaction_pool: Arc, now: Box time::Instant + Send + Sync>, metrics: PrometheusMetrics, - logger: Logger, + logger: Option, _phantom: PhantomData, } diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index fe8a9631f2ce0..183b8f236c58d 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -149,7 +149,7 @@ pub fn start_aura( force_authoring: bool, keystore: SyncCryptoStorePtr, can_author_with: CAW, - logger: Logger, + logger: Option, ) -> Result, sp_consensus::Error> where B: BlockT, C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, @@ -197,7 +197,7 @@ struct AuraWorker { keystore: SyncCryptoStorePtr, sync_oracle: SO, force_authoring: bool, - logger: Logger, + logger: Option, _key_type: PhantomData

, } @@ -355,7 +355,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW } } - fn logger(&self) -> Logger { + fn logger(&self) -> Option { self.logger.clone() } } @@ -507,7 +507,7 @@ pub struct AuraVerifier { phantom: PhantomData

, inherent_data_providers: sp_inherents::InherentDataProviders, can_author_with: CAW, - logger: Logger, + logger: Option, } impl AuraVerifier where @@ -847,7 +847,7 @@ pub fn import_queue( spawner: &S, registry: Option<&Registry>, can_author_with: CAW, - logger: Logger, + logger: Option, ) -> Result, sp_consensus::Error> where B: BlockT, C::Api: BlockBuilderApi + AuraApi> + ApiExt, diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 6a55649337b2d..c397fde753a6e 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -360,7 +360,7 @@ pub struct BabeParams { pub can_author_with: CAW, /// Logger instant use for metrics. - pub logger: Logger, + pub logger: Option, } /// Start the babe worker. @@ -477,7 +477,7 @@ struct BabeSlotWorker { epoch_changes: SharedEpochChanges, slot_notification_sinks: SlotNotificationSinks, config: Config, - logger: Logger, + logger: Option, } impl sc_consensus_slots::SimpleSlotWorker for BabeSlotWorker where @@ -672,7 +672,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeSlot } } - fn logger(&self) -> Logger { + fn logger(&self) -> Option { self.logger.clone() } } @@ -806,7 +806,7 @@ pub struct BabeVerifier { epoch_changes: SharedEpochChanges, time_source: TimeSource, can_author_with: CAW, - logger: Logger, + logger: Option, } impl BabeVerifier @@ -1462,7 +1462,7 @@ pub fn import_queue( spawner: &impl sp_core::traits::SpawnNamed, registry: Option<&Registry>, can_author_with: CAW, - logger: Logger, + logger: Option, ) -> ClientResult> where Inner: BlockImport> + Send + Sync + 'static, diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index c98419d806712..3335122273622 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -145,7 +145,7 @@ pub trait SimpleSlotWorker { fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer; /// Returns the `Logger` instance used for metrics. - fn logger(&self) -> Logger; + fn logger(&self) -> Option; /// Remaining duration of the slot. fn slot_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index f100695318d2c..eae6c91b8ac42 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -352,7 +352,7 @@ where best_number: N, is_descendent_of: &F, initial_sync: bool, - logger: &Logger, + logger: Option<&Logger>, ) -> Result, E> where F: Fn(&H, &H) -> Result, { @@ -412,7 +412,7 @@ where finalized_number: N, is_descendent_of: &F, initial_sync: bool, - logger: &Logger, + logger: Option<&Logger>, ) -> Result, Error> where F: Fn(&H, &H) -> Result, E: std::error::Error, diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index e6cabc5fe062f..98c8e5cd18343 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -681,13 +681,13 @@ struct Inner { next_rebroadcast: Instant, pending_catch_up: PendingCatchUp, catch_up_config: CatchUpConfig, - logger: Logger, + logger: Option, } type MaybeMessage = Option<(Vec, NeighborPacket>)>; impl Inner { - fn new(config: crate::Config, logger: Logger) -> Self { + fn new(config: crate::Config, logger: Option) -> Self { let catch_up_config = if config.observer_enabled { if config.is_authority { // since the observer protocol is enabled, we will only issue @@ -1283,7 +1283,7 @@ pub(super) struct GossipValidator { set_state: environment::SharedVoterSetState, report_sender: TracingUnboundedSender, metrics: Option, - logger: Logger, + logger: Option, } impl GossipValidator { @@ -1294,7 +1294,7 @@ impl GossipValidator { config: crate::Config, set_state: environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, - logger: Logger, + logger: Option, ) -> (GossipValidator, TracingUnboundedReceiver) { let metrics = match prometheus_registry.map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 440eff5ef3cd9..edd2c85f5ad69 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -170,7 +170,7 @@ pub(crate) struct NetworkBridge> { service: N, gossip_engine: Arc>>, validator: Arc>, - logger: Logger, + logger: Option, /// Sender side of the neighbor packet channel. /// @@ -206,7 +206,7 @@ impl> NetworkBridge { config: crate::Config, set_state: crate::environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, - logger: Logger, + logger: Option, ) -> Self { let (validator, report_stream) = GossipValidator::new( config, @@ -500,7 +500,7 @@ fn incoming_global( voters: Arc>, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Logger, + logger: Option, ) -> impl Stream> { let process_commit = { let logger = logger.clone(); @@ -529,7 +529,7 @@ fn incoming_global( voters, msg.round, msg.set_id, - &logger, + logger.as_ref(), ) { if let Some(who) = notification.sender { gossip_engine.lock().report(who, cost); @@ -589,7 +589,7 @@ fn incoming_global( &msg.message, voters, msg.set_id, - &logger, + logger.as_ref(), ) { if let Some(who) = notification.sender { gossip_engine.lock().report(who, cost); @@ -674,7 +674,7 @@ pub(crate) struct OutgoingMessages { sender: mpsc::Sender>, network: Arc>>, has_voted: HasVoted, - logger: Logger, + logger: Option, } impl Unpin for OutgoingMessages {} @@ -776,7 +776,7 @@ fn check_compact_commit( voters: &VoterSet, round: Round, set_id: SetId, - logger: &Logger, + logger: Option<&Logger>, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -838,7 +838,7 @@ fn check_catch_up( msg: &CatchUp, voters: &VoterSet, set_id: SetId, - logger: &Logger, + logger: Option<&Logger>, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -889,7 +889,7 @@ fn check_catch_up( set_id: SetIdNumber, mut signatures_checked: usize, buf: &mut Vec, - logger: &Logger, + logger: Option<&Logger>, ) -> Result where B: BlockT, I: Iterator, &'a AuthorityId, &'a AuthoritySignature)>, @@ -932,7 +932,7 @@ fn check_catch_up( set_id.0, 0, &mut buf, - &logger, + logger, )?; // check signatures on all contained precommits. @@ -944,7 +944,7 @@ fn check_catch_up( set_id.0, signatures_checked, &mut buf, - &logger, + logger, )?; Ok(()) @@ -957,7 +957,7 @@ struct CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Logger, + logger: Option, } impl CommitsOut { @@ -968,7 +968,7 @@ impl CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Logger, + logger: Option, ) -> Self { CommitsOut { network, diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 6e25b4a038abc..1ea2555fdfb70 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -423,7 +423,7 @@ pub(crate) struct Environment, SC, pub(crate) voting_rule: VR, pub(crate) metrics: Option, pub(crate) justification_sender: Option>, - pub(crate) logger: Logger, + pub(crate) logger: Option, pub(crate) _phantom: PhantomData, } @@ -1145,7 +1145,7 @@ pub(crate) fn finalize_block( justification_or_commit: JustificationOrCommit, initial_sync: bool, justification_sender: Option<&GrandpaJustificationSender>, - logger: Logger, + logger: Option, ) -> Result<(), CommandOrError>> where Block: BlockT, @@ -1190,7 +1190,7 @@ where number, &is_descendent_of::(&*client, None), initial_sync, - &logger, + logger.as_ref(), ).map_err(|e| Error::Safety(e.to_string()))?; // check if this is this is the first finalization of some consensus changes diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 4ec690282611e..56d3c939d3c2f 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -468,7 +468,7 @@ pub(crate) fn check_finality_proof( current_authorities: AuthorityList, authorities_provider: &dyn AuthoritySetForFinalityChecker, remote_proof: Vec, - logger: &Logger, + logger: Option<&Logger>, ) -> ClientResult> where NumberFor: BlockNumberOps, diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 5522511af03fb..fc7b396b24cd7 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -65,7 +65,7 @@ pub struct GrandpaBlockImport { consensus_changes: SharedConsensusChanges>, authority_set_hard_forks: HashMap>>, justification_sender: GrandpaJustificationSender, - logger: Logger, + logger: Option, _phantom: PhantomData, } @@ -340,7 +340,13 @@ where let applied_changes = { let forced_change_set = guard .as_mut() - .apply_forced_changes(hash, number, &is_descendent_of, initial_sync, &self.logger) + .apply_forced_changes( + hash, + number, + &is_descendent_of, + initial_sync, + self.logger.as_ref(), + ) .map_err(|e| ConsensusError::ClientImport(e.to_string())) .map_err(ConsensusError::from)?; @@ -567,7 +573,7 @@ impl GrandpaBlockImport>, authority_set_hard_forks: Vec<(SetId, PendingChange>)>, justification_sender: GrandpaJustificationSender, - logger: Logger, + logger: Option, ) -> GrandpaBlockImport { // check for and apply any forced authority set hard fork that applies // to the *current* authority set. diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index 9195589e7dbcf..05298cacdb6d1 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -501,7 +501,7 @@ pub fn block_import( client: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, - logger: Logger, + logger: Option, ) -> Result< ( GrandpaBlockImport, @@ -533,7 +533,7 @@ pub fn block_import_with_authority_set_hard_forks genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, - logger: Logger, + logger: Option, ) -> Result< ( GrandpaBlockImport, @@ -670,7 +670,7 @@ pub struct GrandpaParams { /// The voter state is exposed at an RPC endpoint. pub shared_voter_state: SharedVoterState, /// Logger used by telemtry. - pub logger: Logger, + pub logger: Option, } /// Run a GRANDPA voter as a task. Provide configuration and a link to a @@ -807,7 +807,7 @@ struct VoterWork, SC, VR> { env: Arc>, voter_commands_rx: TracingUnboundedReceiver>>, network: NetworkBridge, - logger: Logger, + logger: Option, /// Prometheus metrics. metrics: Option, @@ -835,7 +835,7 @@ where prometheus_registry: Option, shared_voter_state: SharedVoterState, justification_sender: GrandpaJustificationSender, - logger: Logger, + logger: Option, ) -> Self { let metrics = match prometheus_registry.as_ref().map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs index 054d34b39cdad..df4dfe00c6b8a 100644 --- a/client/finality-grandpa/src/light_import.rs +++ b/client/finality-grandpa/src/light_import.rs @@ -53,7 +53,7 @@ pub fn light_block_import( backend: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, authority_set_provider: Arc>, - logger: Logger, + logger: Option, ) -> Result, ClientError> where BE: Backend, @@ -84,7 +84,7 @@ pub struct GrandpaLightBlockImport { backend: Arc, authority_set_provider: Arc>, data: Arc>>, - logger: Logger, + logger: Option, } impl Clone for GrandpaLightBlockImport { @@ -197,7 +197,7 @@ impl FinalityProofImport number, finality_proof, verifier, - &self.logger, + self.logger.as_ref(), ) } } @@ -309,7 +309,7 @@ fn do_import_finality_proof( _number: NumberFor, finality_proof: Vec, verifier: &mut dyn Verifier, - logger: &Logger, + logger: Option<&Logger>, ) -> Result<(Block::Hash, NumberFor), ConsensusError> where C: HeaderBackend diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index 121710112f258..3806fd268e68a 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -75,7 +75,7 @@ fn grandpa_observer( last_finalized_number: NumberFor, commits: S, note_round: F, - logger: Logger, + logger: Option, ) -> impl Future>>> where NumberFor: BlockNumberOps, @@ -170,7 +170,7 @@ pub fn run_grandpa_observer( config: Config, link: LinkHalf, network: N, - logger: Logger, + logger: Option, ) -> sp_blockchain::Result + Unpin + Send + 'static> where BE: Backend + Unpin + 'static, @@ -225,7 +225,7 @@ struct ObserverWork> { keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, - logger: Logger, + logger: Option, _phantom: PhantomData, } @@ -244,7 +244,7 @@ where keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, - logger: Logger, + logger: Option, ) -> Self { let mut work = ObserverWork { diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 95d74fb448f5a..d6fd69f4d036a 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -243,7 +243,7 @@ impl KeystoreContainer { /// Creates a new full client for the given config. pub fn new_full_client( config: &Configuration, - logger: Logger, + logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -254,7 +254,7 @@ pub fn new_full_client( /// Create the initial parts of a full node. pub fn new_full_parts( config: &Configuration, - logger: Logger, + logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -324,7 +324,7 @@ pub fn new_full_parts( /// Create the initial parts of a light node. pub fn new_light_parts( config: &Configuration, - logger: Logger, + logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -385,7 +385,7 @@ pub fn new_client( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, - logger: Logger, + logger: Option, ) -> Result<( crate::client::Client< Backend, @@ -557,7 +557,7 @@ pub fn spawn_tasks( task_manager.spawn_handle(), genesis_hash, )) }); - let logger = telemetry.as_ref().map(|x| x.logger.clone()).expect("TODO"); + let logger = telemetry.as_ref().map(|x| x.logger.clone()); info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( @@ -641,7 +641,7 @@ pub fn spawn_tasks( async fn transaction_notifications( transaction_pool: Arc, network: Arc::Hash>>, - logger: Logger, + logger: Option, ) where TBl: BlockT, @@ -682,7 +682,7 @@ fn build_telemetry( let startup_time = SystemTime::UNIX_EPOCH.elapsed() .map(|dur| dur.as_millis()) .unwrap_or(0); - let logger = telemetry.logger.clone(); + let logger = Some(telemetry.logger.clone()); spawn_handle.spawn( "telemetry-worker", diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 513aeda49de76..f905870db133e 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -114,7 +114,7 @@ pub struct Client where Block: BlockT { block_rules: BlockRules, execution_extensions: ExecutionExtensions, config: ClientConfig, - logger: Logger, + logger: Option, _phantom: PhantomData, } @@ -154,7 +154,7 @@ pub fn new_in_mem( prometheus_registry: Option, spawn_handle: Box, config: ClientConfig, - logger: Logger, + logger: Option, ) -> sp_blockchain::Result, LocalCallExecutor, E>, @@ -197,7 +197,7 @@ pub fn new_with_backend( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, - logger: Logger, + logger: Option, ) -> sp_blockchain::Result, Block, RA>> where E: CodeExecutor + RuntimeInfo, @@ -297,7 +297,7 @@ impl Client where execution_extensions: ExecutionExtensions, prometheus_registry: Option, config: ClientConfig, - logger: Logger, + logger: Option, ) -> sp_blockchain::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { let genesis_storage = build_genesis_storage.build_storage()?; diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs index e925dad494e43..7252885f25a7d 100644 --- a/client/service/src/client/light.rs +++ b/client/service/src/client/light.rs @@ -39,7 +39,7 @@ pub fn new_light( code_executor: E, spawn_handle: Box, prometheus_registry: Option, - logger: Logger, + logger: Option, ) -> ClientResult< Client< Backend>, diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index d7d412beb9f0f..e948972d3fd5f 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -112,13 +112,13 @@ pub struct MetricsService { last_update: Instant, last_total_bytes_inbound: u64, last_total_bytes_outbound: u64, - logger: Logger, + logger: Option, } impl MetricsService { /// Creates a `MetricsService` that only sends information /// to the telemetry. - pub fn new(logger: Logger) -> Self { + pub fn new(logger: Option) -> Self { MetricsService { metrics: None, last_total_bytes_inbound: 0, @@ -133,7 +133,7 @@ impl MetricsService { pub fn with_prometheus( registry: &Registry, config: &Configuration, - logger: Logger, + logger: Option, ) -> Result { let role_bits = match config.role { Role::Full => 1u64, diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6c04728946032..c5e41bb16a1bc 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -313,8 +313,10 @@ impl slog::Drain for TelemetryDrain { /// parameter is added to the record as a key-value pair. #[macro_export] macro_rules! telemetry { - ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => { - $crate::slog::slog_info!($l, #$a, $b; $($t)* ) + ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => { + if let Some(ref l) = $l { + $crate::slog::slog_info!(l, #$a, $b; $($t)* ) + } } } diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 60197446b4570..f92e64585e135 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -217,7 +217,7 @@ impl ProfilingLayer { /// either with a level: "pallet=trace,frame=debug" /// or without: "pallet,frame" in which case the level defaults to `trace`. /// wasm_tracing indicates whether to enable wasm traces - pub fn new(receiver: TracingReceiver, targets: &str, logger: Logger) -> Self { + pub fn new(receiver: TracingReceiver, targets: &str, logger: Option) -> Self { match receiver { TracingReceiver::Log => Self::new_with_handler(Box::new(LogTraceHandler), targets), TracingReceiver::Telemetry => Self::new_with_handler( @@ -406,7 +406,7 @@ impl TraceHandler for LogTraceHandler { /// Please see telemetry documentation for details on how to specify endpoints and /// set the required telemetry level to activate tracing messages pub struct TelemetryTraceHandler { - logger: Logger, + logger: Option, } impl TraceHandler for TelemetryTraceHandler { From cabeeb4e171d7b3d3b8882d9dabfac2382e57481 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 23 Oct 2020 12:24:58 +0200 Subject: [PATCH 005/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- bin/node/testing/src/bench.rs | 1 + test-utils/client/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 153a52375c2a9..3374d889efe0d 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -425,6 +425,7 @@ impl BenchDb { Box::new(task_executor.clone()), None, Default::default(), + None, ).expect("Should not fail"); (client, backend, task_executor) diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 35d6e78ccd41e..501f37b2158f6 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -220,6 +220,7 @@ impl TestClientBuilder Date: Fri, 23 Oct 2020 12:58:55 +0200 Subject: [PATCH 006/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- bin/node/bench/src/construct.rs | 1 + bin/node/inspect/src/command.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index 5506dc426de0b..425f32fc55ceb 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -151,6 +151,7 @@ impl core::Benchmark for ConstructionBenchmark { context.client.clone(), self.transactions.clone().into(), None, + None, ); let inherent_data_providers = sp_inherents::InherentDataProviders::new(); inherent_data_providers diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index fae6c10c7fe78..b69d3a002fec2 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -34,7 +34,7 @@ impl InspectCmd { RA: Send + Sync + 'static, EX: NativeExecutionDispatch + 'static, { - let client = new_full_client::(&config)?; + let client = new_full_client::(&config, None)?; let inspect = Inspector::::new(client); match &self.command { From 26524068012b07a1a52034bbc95b786e02582832 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 23 Oct 2020 12:59:12 +0200 Subject: [PATCH 007/222] Refactor build_telemetry --- client/service/src/builder.rs | 47 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index d6fd69f4d036a..bba9ff9ce5d49 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -541,23 +541,13 @@ pub fn spawn_tasks( )?; // Telemetry - let telemetry = config.telemetry_endpoints.clone().and_then(|endpoints| { - if endpoints.is_empty() { - // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) - return None; - } - - let genesis_hash = match client.block_hash(Zero::zero()) { - Ok(Some(hash)) => hash, - _ => Default::default(), - }; - - Some(build_telemetry( - &mut config, endpoints, telemetry_connection_sinks.clone(), network.clone(), - task_manager.spawn_handle(), genesis_hash, - )) - }); - let logger = telemetry.as_ref().map(|x| x.logger.clone()); + let (telemetry, logger) = build_telemetry( + &mut config, + telemetry_connection_sinks.clone(), + network.clone(), + task_manager.spawn_handle(), + client.clone(), + ); info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( @@ -661,14 +651,24 @@ async fn transaction_notifications( .await; } -fn build_telemetry( +fn build_telemetry>( config: &mut Configuration, - endpoints: sc_telemetry::TelemetryEndpoints, telemetry_connection_sinks: TelemetryConnectionSinks, network: Arc::Hash>>, spawn_handle: SpawnTaskHandle, - genesis_hash: ::Hash, -) -> sc_telemetry::Telemetry { + client: Arc, +) -> (Option, Option) { + let endpoints = match config.telemetry_endpoints.clone() { + Some(endpoints) if !endpoints.is_empty() => endpoints, + // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) + _ => return (None, None), + }; + + let genesis_hash = match client.block_hash(Zero::zero()) { + Ok(Some(hash)) => hash, + _ => Default::default(), + }; + let is_authority = config.role.is_authority(); let network_id = network.local_peer_id().to_base58(); let name = config.network.node_name.clone(); @@ -710,7 +710,10 @@ fn build_telemetry( }) ); - telemetry + let logger = telemetry.logger.clone(); + + // TODO probably don't need the telemetry object anymore + (Some(telemetry), Some(logger)) } fn gen_handler( From 6b463a0148bc844196841102c2d8439ea0994f0b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 23 Oct 2020 13:34:17 +0200 Subject: [PATCH 008/222] Refactor init_telemetry more --- bin/node-template/node/src/service.rs | 4 +- bin/node/cli/src/service.rs | 3 +- client/service/src/builder.rs | 71 +++++++++++++++------------ 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 90187061c9cf7..6efb6d5b8904f 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -224,7 +224,7 @@ pub fn new_full(config: Configuration) -> Result { /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry) = sc_service::new_light_parts::(&config)?; let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( @@ -253,6 +253,7 @@ pub fn new_light(config: Configuration) -> Result { &task_manager.spawn_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, + telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_provider = @@ -291,6 +292,7 @@ pub fn new_light(config: Configuration) -> Result { network, network_status_sinks, system_rpc_tx, + telemetry, })?; network_starter.start_network(); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 3d5bb8a329af4..e07a6b2b69554 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -359,7 +359,7 @@ pub fn new_light_base(config: Configuration) -> Result<( Arc::Hash>>, Arc>> ), ServiceError> { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry) = sc_service::new_light_parts::(&config)?; let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -446,6 +446,7 @@ pub fn new_light_base(config: Configuration) -> Result<( network: network.clone(), telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), task_manager: &mut task_manager, + telemetry, })?; Ok((task_manager, rpc_handlers, client, network, transaction_pool)) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index bba9ff9ce5d49..4015cc60ebf16 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -178,6 +178,7 @@ type TFullParts = ( Arc>, KeystoreContainer, TaskManager, + Option, ); type TLightParts = ( @@ -186,6 +187,7 @@ type TLightParts = ( KeystoreContainer, TaskManager, Arc>, + Option, ); /// Light client backend type with a specific hash type. @@ -243,22 +245,21 @@ impl KeystoreContainer { /// Creates a new full client for the given config. pub fn new_full_client( config: &Configuration, - logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - new_full_parts(config, logger).map(|parts| parts.0) + new_full_parts(config).map(|parts| parts.0) } /// Create the initial parts of a full node. pub fn new_full_parts( config: &Configuration, - logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { + let (telemetry, logger) = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { @@ -308,7 +309,6 @@ pub fn new_full_parts( offchain_worker_enabled : config.offchain_worker.enabled , offchain_indexing_api: config.offchain_worker.indexing_enabled, }, - // TODO: maybe pass by ref logger, )? }; @@ -318,17 +318,18 @@ pub fn new_full_parts( backend, keystore_container, task_manager, + telemetry, )) } /// Create the initial parts of a light node. pub fn new_light_parts( config: &Configuration, - logger: Option, ) -> Result, Error> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { + let (telemetry, logger) = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); @@ -367,11 +368,10 @@ pub fn new_light_parts( executor, Box::new(task_manager.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), - // TODO: maybe pass by ref? logger, )?); - Ok((client, backend, keystore_container, task_manager, on_demand)) + Ok((client, backend, keystore_container, task_manager, on_demand, telemetry)) } /// Create an instance of db-backed client. @@ -450,6 +450,8 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { pub system_rpc_tx: TracingUnboundedSender>, /// Shared Telemetry connection sinks, pub telemetry_connection_sinks: TelemetryConnectionSinks, + /// Telemetry object. + pub telemetry: Option, } /// Build a shared offchain workers instance. @@ -530,6 +532,7 @@ pub fn spawn_tasks( network_status_sinks, system_rpc_tx, telemetry_connection_sinks, + telemetry, } = params; let chain_info = client.usage_info().chain; @@ -540,14 +543,17 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - // Telemetry - let (telemetry, logger) = build_telemetry( - &mut config, - telemetry_connection_sinks.clone(), - network.clone(), - task_manager.spawn_handle(), - client.clone(), - ); + let logger = telemetry.as_ref().map(|x| x.logger.clone()); + if let Some(telemetry) = telemetry.clone() { + spawn_telemetry_worker( + telemetry, + &mut config, + telemetry_connection_sinks.clone(), + network.clone(), + task_manager.spawn_handle(), + client.clone(), + ); + } info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( @@ -651,19 +657,29 @@ async fn transaction_notifications( .await; } -fn build_telemetry>( - config: &mut Configuration, - telemetry_connection_sinks: TelemetryConnectionSinks, - network: Arc::Hash>>, - spawn_handle: SpawnTaskHandle, - client: Arc, -) -> (Option, Option) { +fn init_telemetry(config: &Configuration) -> (Option, Option) { let endpoints = match config.telemetry_endpoints.clone() { Some(endpoints) if !endpoints.is_empty() => endpoints, // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) _ => return (None, None), }; + let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { + endpoints, + wasm_external_transport: config.telemetry_external_transport.clone(), + }); + let logger = telemetry.logger.clone(); + + (Some(telemetry), Some(logger)) +} +fn spawn_telemetry_worker>( + telemetry: sc_telemetry::Telemetry, + config: &mut Configuration, + telemetry_connection_sinks: TelemetryConnectionSinks, + network: Arc::Hash>>, + spawn_handle: SpawnTaskHandle, + client: Arc, +) { let genesis_hash = match client.block_hash(Zero::zero()) { Ok(Some(hash)) => hash, _ => Default::default(), @@ -675,10 +691,6 @@ fn build_telemetry>( let impl_name = config.impl_name.clone(); let impl_version = config.impl_version.clone(); let chain_name = config.chain_spec.name().to_owned(); - let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { - endpoints, - wasm_external_transport: config.telemetry_external_transport.take(), - }); let startup_time = SystemTime::UNIX_EPOCH.elapsed() .map(|dur| dur.as_millis()) .unwrap_or(0); @@ -686,7 +698,7 @@ fn build_telemetry>( spawn_handle.spawn( "telemetry-worker", - telemetry.clone() + telemetry .for_each(move |event| { // Safe-guard in case we add more events in the future. let sc_telemetry::TelemetryEvent::Connected = event; @@ -709,11 +721,6 @@ fn build_telemetry>( ready(()) }) ); - - let logger = telemetry.logger.clone(); - - // TODO probably don't need the telemetry object anymore - (Some(telemetry), Some(logger)) } fn gen_handler( From c2ac19a3430f71d3c897a8cc627877ff455f488b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 23 Oct 2020 13:45:24 +0200 Subject: [PATCH 009/222] Revert "WIP" This reverts commit 6ad79c8348be4b449e4d2cdae114b35345d98026. --- bin/node/bench/src/construct.rs | 1 - bin/node/inspect/src/command.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index 425f32fc55ceb..5506dc426de0b 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -151,7 +151,6 @@ impl core::Benchmark for ConstructionBenchmark { context.client.clone(), self.transactions.clone().into(), None, - None, ); let inherent_data_providers = sp_inherents::InherentDataProviders::new(); inherent_data_providers diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index b69d3a002fec2..fae6c10c7fe78 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -34,7 +34,7 @@ impl InspectCmd { RA: Send + Sync + 'static, EX: NativeExecutionDispatch + 'static, { - let client = new_full_client::(&config, None)?; + let client = new_full_client::(&config)?; let inspect = Inspector::::new(client); match &self.command { From 6f5edfc56b6ef1e7e0633af26061a1221f93a5c5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 23 Oct 2020 14:28:00 +0200 Subject: [PATCH 010/222] WIP Forked at: d67fc4c2cb6db6fdd2af92909bd13467c20029e5 Parent branch: origin/master --- bin/node-template/node/src/service.rs | 44 ++++++++++++++++++++++----- bin/node/bench/src/construct.rs | 1 + bin/node/cli/src/service.rs | 42 ++++++++++++++++++++----- client/service/src/lib.rs | 2 ++ 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 6efb6d5b8904f..4456ee9d62258 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -39,7 +39,7 @@ pub fn new_partial(config: &Configuration) -> Result, ServiceError> { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager) = + let (client, backend, keystore_container, task_manager, telemetry) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -53,7 +53,10 @@ pub fn new_partial(config: &Configuration) -> Result), select_chain.clone(), + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + telemetry.as_ref().map(|x| x.logger.clone()), )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( @@ -70,11 +73,19 @@ pub fn new_partial(config: &Configuration) -> Result Result Result { let sc_service::PartialComponents { - client, backend, mut task_manager, import_queue, keystore_container, - select_chain, transaction_pool, inherent_data_providers, + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + inherent_data_providers, + telemetry, other: (block_import, grandpa_link), } = new_partial(&config)?; @@ -141,7 +159,11 @@ pub fn new_full(config: Configuration) -> Result { rpc_extensions_builder, on_demand: None, remote_blockchain: None, - backend, network_status_sinks, system_rpc_tx, config, + backend, + network_status_sinks, + system_rpc_tx, + config, + telemetry: telemetry.clone(), })?; if role.is_authority() { @@ -150,6 +172,7 @@ pub fn new_full(config: Configuration) -> Result { client.clone(), transaction_pool, prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.logger.clone()), ); let can_author_with = @@ -166,6 +189,7 @@ pub fn new_full(config: Configuration) -> Result { force_authoring, keystore_container.sync_keystore(), can_author_with, + telemetry.as_ref().map(|x| x.logger.clone()), )?; // the AURA authoring task is considered essential, i.e. if it @@ -206,6 +230,7 @@ pub fn new_full(config: Configuration) -> Result { voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), + logger: telemetry.as_ref().map(|x| x.logger.clone()), }; // the GRANDPA voter task is considered infallible, i.e. @@ -236,8 +261,11 @@ pub fn new_light(config: Configuration) -> Result { )); let grandpa_block_import = sc_finality_grandpa::light_block_import( - client.clone(), backend.clone(), &(client.clone() as Arc<_>), + client.clone(), + backend.clone(), + &(client.clone() as Arc<_>), Arc::new(on_demand.checker().clone()) as Arc<_>, + telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_import = grandpa_block_import.clone(); let finality_proof_request_builder = diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index 5506dc426de0b..425f32fc55ceb 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -151,6 +151,7 @@ impl core::Benchmark for ConstructionBenchmark { context.client.clone(), self.transactions.clone().into(), None, + None, ); let inherent_data_providers = sp_inherents::InherentDataProviders::new(); inherent_data_providers diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index e07a6b2b69554..ed04fcef4a26b 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -63,7 +63,7 @@ pub fn new_partial(config: &Configuration) -> Result, ServiceError> { - let (client, backend, keystore_container, task_manager) = + let (client, backend, keystore_container, task_manager, telemetry) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -77,7 +77,10 @@ pub fn new_partial(config: &Configuration) -> Result), select_chain.clone(), + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + telemetry.as_ref().map(|x| x.logger.clone()), )?; let justification_import = grandpa_block_import.clone(); @@ -100,6 +103,7 @@ pub fn new_partial(config: &Configuration) -> Result Result Result { let sc_service::PartialComponents { - client, backend, mut task_manager, import_queue, keystore_container, - select_chain, transaction_pool, inherent_data_providers, + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + inherent_data_providers, + telemetry, other: (rpc_extensions_builder, import_setup, rpc_setup), } = new_partial(&config)?; @@ -223,6 +241,7 @@ pub fn new_full_base( telemetry_connection_sinks: telemetry_connection_sinks.clone(), network_status_sinks: network_status_sinks.clone(), system_rpc_tx, + telemetry: telemetry.clone(), })?; let (block_import, grandpa_link, babe_link) = import_setup; @@ -235,6 +254,7 @@ pub fn new_full_base( client.clone(), transaction_pool.clone(), prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.logger.clone()), ); let can_author_with = @@ -251,6 +271,7 @@ pub fn new_full_base( force_authoring, babe_link, can_author_with, + logger: telemetry.as_ref().map(|x| x.logger.clone()), }; let babe = sc_consensus_babe::start_babe(babe_config)?; @@ -323,6 +344,7 @@ pub fn new_full_base( voting_rule: grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state, + logger: telemetry.as_ref().map(|x| x.logger.clone()), }; // the GRANDPA voter task is considered infallible, i.e. @@ -373,8 +395,11 @@ pub fn new_light_base(config: Configuration) -> Result<( )); let grandpa_block_import = grandpa::light_block_import( - client.clone(), backend.clone(), &(client.clone() as Arc<_>), + client.clone(), + backend.clone(), + &(client.clone() as Arc<_>), Arc::new(on_demand.checker().clone()), + telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_import = grandpa_block_import.clone(); @@ -400,6 +425,7 @@ pub fn new_light_base(config: Configuration) -> Result<( &task_manager.spawn_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, + telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_provider = diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index cb741c2920b06..5183af9ccd889 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -190,6 +190,8 @@ pub struct PartialComponents, /// A registry of all providers of `InherentData`. pub inherent_data_providers: sp_inherents::InherentDataProviders, + /// Telemetry object. + pub telemetry: Option, /// Everything else that needs to be passed into the main build function. pub other: Other, } From 4998cfb057db8de84a6d8a0544a32b343d4501d6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 28 Oct 2020 16:10:49 +0100 Subject: [PATCH 011/222] WIP --- Cargo.lock | 2 ++ client/consensus/slots/src/lib.rs | 2 +- client/service/src/metrics.rs | 3 +- client/telemetry/Cargo.toml | 2 ++ client/telemetry/src/lib.rs | 59 +++++++++++++++++++++++++++++-- client/tracing/src/lib.rs | 6 ++-- 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc1f0def07ecb..57a9c813c7245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7407,9 +7407,11 @@ dependencies = [ "pin-project", "rand 0.7.3", "serde", + "serde_json", "slog", "slog-json", "take_mut", + "tracing", "void", "wasm-timer", ] diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 3335122273622..09aba10c66b64 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -217,7 +217,7 @@ pub trait SimpleSlotWorker { telemetry!( logger; CONSENSUS_DEBUG; "slots.skipping_proposal_slot"; - "authorities_len" => authorities_len, + "authorities_len" => : authorities_len, ); return Box::pin(future::ready(Ok(()))); diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index e948972d3fd5f..03ae78b0ce695 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -338,7 +338,8 @@ impl MetricsService { self.logger; SUBSTRATE_INFO; "system.network_state"; - "state" => net_state, + // TODO: not sure why I need `?` all of a sudden? + "state" => ? net_state, ); } } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index d593471696ab1..0388d8a3d2237 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -28,3 +28,5 @@ slog = { version = "2.5.2", features = ["nested-values"] } slog-json = { version = "2.3.0", features = ["nested-values"] } take_mut = "0.2.2" void = "1.0.2" +tracing = "0.1.10" +serde_json = "1.0.41" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index c5e41bb16a1bc..d30e0d7051f14 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -71,6 +71,8 @@ use slog::Logger; pub use libp2p::wasm_ext::ExtTransport; pub use slog; +pub use slog_json; +pub use tracing; mod async_record; mod worker; @@ -166,6 +168,7 @@ pub struct Telemetry { inner: Arc>, /// Logger used to report telemetry. pub logger: Logger, + span: tracing::Span, } /// Behind the `Mutex` in `Telemetry`. @@ -209,12 +212,15 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { } }; + let span = tracing::info_span!("telemetry-logger"); + Telemetry { inner: Arc::new(Mutex::new(TelemetryInner { worker, receiver, })), logger, + span, } } @@ -313,11 +319,60 @@ impl slog::Drain for TelemetryDrain { /// parameter is added to the record as a key-value pair. #[macro_export] macro_rules! telemetry { - ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => { + ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => {{ + // TODO: drop $l + /* + // NOTE: didn't work + let record_static = $crate::slog::record_static!($crate::slog::Level::Info, $a); + let format_args = format_args!(""); + let record = $crate::slog::Record::new(&record_static, &format_args, $crate::slog::b!()); + + let mut v = vec![]; + let mut cur = std::io::Cursor::new(&mut v); + let json = $crate::slog_json::Json::default(&mut cur); + use $crate::slog::Drain; + let kv = $crate::slog::o!($($t)*); + let kvl = $crate::slog::OwnedKVList::from(kv); + json.log(&record, &kvl).unwrap(); + let s = String::from_utf8(v).unwrap(); + */ + /* + // NOTE: old code if let Some(ref l) = $l { $crate::slog::slog_info!(l, #$a, $b; $($t)* ) } - } + */ + $crate::tracing::info!(target: "telemetry-logger", + message_verbosity = $a, + message = $b, + //json = s.as_str() + json = $crate::format_fields_to_json!($($t)*).as_str() + ); + }}; +} + +#[macro_export] +macro_rules! format_fields_to_json { + ( $k:literal => $v:expr $(,)? ) => { + format!("{} = {}", $k, $v) + }; + ( $k:literal => ? $v:expr $(,)? ) => { + format!("{} = {:?}", $k, $v) + }; + ( $k:literal => : $v:expr $(,)? ) => { + $v + .map(|x| $crate::format_fields_to_json!($k => x)) + .unwrap_or_else(|| "null".to_string()) + }; + ( $k:literal => $v:expr, $($t:tt)* ) => { + format!("{}, {}", $crate::format_fields_to_json!($k => $v), $crate::format_fields_to_json!($($t)*)) + }; + ( $k:literal => ? $v:expr, $($t:tt)* ) => { + format!("{}, {}", $crate::format_fields_to_json!($k => ? $v), $crate::format_fields_to_json!($($t)*)) + }; + ( $k:literal => : $v:expr, $($t:tt)* ) => { + format!("{}, {}", $crate::format_fields_to_json!($k => : $v), $crate::format_fields_to_json!($($t)*)) + }; } #[cfg(test)] diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index f92e64585e135..5c598c6bf2c87 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -24,6 +24,8 @@ //! //! Currently we provide `Log` (default), `Telemetry` variants for `Receiver` +#![recursion_limit="256"] + use rustc_hash::FxHashMap; use std::fmt; use std::time::{Duration, Instant}; @@ -416,7 +418,7 @@ impl TraceHandler for TelemetryTraceHandler { "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), "id" => span_datum.id.into_u64(), - "parent_id" => span_datum.parent_id.map(|i| i.into_u64()), + "parent_id" => : span_datum.parent_id.as_ref().map(|i| i.into_u64()), "values" => span_datum.values ); } @@ -425,7 +427,7 @@ impl TraceHandler for TelemetryTraceHandler { telemetry!(self.logger; SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, - "parent_id" => event.parent_id.map(|i| i.into_u64()), + "parent_id" => : event.parent_id.as_ref().map(|i| i.into_u64()), "values" => event.values ); } From 613e335a20885b4e6710fb2e17bb781aa782a7b4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 08:04:31 +0100 Subject: [PATCH 012/222] WIP --- Cargo.lock | 1 + client/telemetry/Cargo.toml | 1 + client/telemetry/src/lib.rs | 67 +++++++++++++++++++++++++------------ 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57a9c813c7245..07c225c7ad90d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7399,6 +7399,7 @@ dependencies = [ name = "sc-telemetry" version = "2.0.0" dependencies = [ + "chrono", "futures 0.3.5", "futures-timer 3.0.2", "libp2p", diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 0388d8a3d2237..664991944f594 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -30,3 +30,4 @@ take_mut = "0.2.2" void = "1.0.2" tracing = "0.1.10" serde_json = "1.0.41" +chrono = "0.4.13" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d30e0d7051f14..27443e37e09b3 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -73,6 +73,8 @@ pub use libp2p::wasm_ext::ExtTransport; pub use slog; pub use slog_json; pub use tracing; +pub use serde_json; +pub use chrono; mod async_record; mod worker; @@ -314,10 +316,11 @@ impl slog::Drain for TelemetryDrain { } } +/// TODO doc /// Translates to `slog_scope::info`, but contains an additional verbosity /// parameter which the log record is tagged with. Additionally the verbosity /// parameter is added to the record as a key-value pair. -#[macro_export] +#[macro_export(local_inner_macros)] macro_rules! telemetry { ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => {{ // TODO: drop $l @@ -342,37 +345,57 @@ macro_rules! telemetry { $crate::slog::slog_info!(l, #$a, $b; $($t)* ) } */ + let mut json = format_fields_to_json!($($t)*); + json.insert("level".into(), "INFO".into()); + json.insert("msg".into(), $b.into()); + json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); $crate::tracing::info!(target: "telemetry-logger", message_verbosity = $a, message = $b, //json = s.as_str() - json = $crate::format_fields_to_json!($($t)*).as_str() + json = $crate::serde_json::to_string(&json) + .expect("contains only string keys; qed").as_str() ); }}; } -#[macro_export] +#[macro_export(local_inner_macros)] +#[doc(hidden)] macro_rules! format_fields_to_json { - ( $k:literal => $v:expr $(,)? ) => { - format!("{} = {}", $k, $v) - }; - ( $k:literal => ? $v:expr $(,)? ) => { - format!("{} = {:?}", $k, $v) - }; - ( $k:literal => : $v:expr $(,)? ) => { + ( $k:literal => $v:expr $(,)? ) => {{ + let mut map = $crate::serde_json::Map::new(); + map.insert($k.into(), $crate::serde_json::Value::from(std::format!("{}", $v))); + map + }}; + ( $k:literal => ? $v:expr $(,)? ) => {{ + let mut map = $crate::serde_json::Map::new(); + map.insert($k.into(), $crate::serde_json::Value::from(std::format!("{:?}", $v))); + map + }}; + ( $k:literal => : $v:expr $(,)? ) => {{ $v - .map(|x| $crate::format_fields_to_json!($k => x)) - .unwrap_or_else(|| "null".to_string()) - }; - ( $k:literal => $v:expr, $($t:tt)* ) => { - format!("{}, {}", $crate::format_fields_to_json!($k => $v), $crate::format_fields_to_json!($($t)*)) - }; - ( $k:literal => ? $v:expr, $($t:tt)* ) => { - format!("{}, {}", $crate::format_fields_to_json!($k => ? $v), $crate::format_fields_to_json!($($t)*)) - }; - ( $k:literal => : $v:expr, $($t:tt)* ) => { - format!("{}, {}", $crate::format_fields_to_json!($k => : $v), $crate::format_fields_to_json!($($t)*)) - }; + .map(|x| format_fields_to_json!($k => x)) + .unwrap_or_else(|| { + let mut map = $crate::serde_json::Map::new(); + map.insert($k.into(), $crate::serde_json::Value::Null); + map + }) + }}; + ( $k:literal => $v:expr, $($t:tt)* ) => {{ + let mut map = format_fields_to_json!($($t)*); + map.append(&mut format_fields_to_json!($k => $v)); + map + }}; + ( $k:literal => ? $v:expr, $($t:tt)* ) => {{ + let mut map = format_fields_to_json!($($t)*); + map.append(&mut format_fields_to_json!($k => ? $v)); + map + }}; + ( $k:literal => : $v:expr, $($t:tt)* ) => {{ + let mut map = format_fields_to_json!($($t)*); + map.append(&mut format_fields_to_json!($k => : $v)); + map + }}; } #[cfg(test)] From b962032e206ee3a155bbf1969612e51b96243893 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 08:34:11 +0100 Subject: [PATCH 013/222] WIP --- Cargo.lock | 1 + client/cli/src/lib.rs | 4 +++- client/telemetry/Cargo.toml | 1 + client/telemetry/src/layer.rs | 39 +++++++++++++++++++++++++++++++++++ client/telemetry/src/lib.rs | 4 +++- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 client/telemetry/src/layer.rs diff --git a/Cargo.lock b/Cargo.lock index 07c225c7ad90d..1b97afc39b325 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7413,6 +7413,7 @@ dependencies = [ "slog-json", "take_mut", "tracing", + "tracing-subscriber", "void", "wasm-timer", ] diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index e63e379533a62..2c303088acb69 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -324,7 +324,9 @@ pub fn init_logger( display_level: !simple, display_thread_name: !simple, }) - .finish().with(logging::NodeNameLayer); + .finish() + .with(logging::NodeNameLayer) + .with(sc_telemetry::TelemetryLayer::new()); if let Some(profiling_targets) = profiling_targets { let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets); diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 664991944f594..0027ec6985a9c 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -29,5 +29,6 @@ slog-json = { version = "2.3.0", features = ["nested-values"] } take_mut = "0.2.2" void = "1.0.2" tracing = "0.1.10" +tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs new file mode 100644 index 0000000000000..97e7deaccf436 --- /dev/null +++ b/client/telemetry/src/layer.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use futures::channel::mpsc; +use std::sync::{Arc, Mutex}; +use tracing::Subscriber; +use tracing_subscriber::{registry::LookupSpan, Layer}; + +pub struct TelemetryLayer(Senders); + +impl TelemetryLayer { + pub fn new() -> Self { + Self(Default::default()) + } + + pub fn senders(&self) -> Senders { + self.0.clone() + } +} + +impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> {} + +#[derive(Default, Debug, Clone)] +pub struct Senders(Arc>>>>); diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 27443e37e09b3..fdbf0871bb3b5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -77,8 +77,11 @@ pub use serde_json; pub use chrono; mod async_record; +mod layer; mod worker; +pub use layer::*; + /// Configuration for telemetry. pub struct TelemetryConfig { /// Collection of telemetry WebSocket servers with a corresponding verbosity level. @@ -351,7 +354,6 @@ macro_rules! telemetry { json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); $crate::tracing::info!(target: "telemetry-logger", message_verbosity = $a, - message = $b, //json = s.as_str() json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed").as_str() From ca0ab5ab52f3e4a4edb79727cefa1565478af61f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 10:18:37 +0100 Subject: [PATCH 014/222] WIP --- Cargo.lock | 2 +- client/cli/src/lib.rs | 8 +++-- client/telemetry/Cargo.toml | 2 +- client/telemetry/src/layer.rs | 68 +++++++++++++++++++++++++++++++---- client/telemetry/src/lib.rs | 45 ++++++++++++++++------- 5 files changed, 101 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 151cc1c76ed94..c0a3a3930fc77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7466,7 +7466,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log", - "parking_lot 0.10.2", + "parking_lot 0.11.0", "pin-project", "rand 0.7.3", "serde", diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 716411c9376a9..2ecb5d41ad68c 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -243,7 +243,7 @@ pub fn init_logger( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option, -) -> std::result::Result<(), String> { +) -> std::result::Result { fn parse_directives(dirs: impl AsRef) -> Vec { dirs.as_ref() .split(',') @@ -316,6 +316,8 @@ pub fn init_logger( "%Y-%m-%d %H:%M:%S%.3f".to_string() }); + let telemetry_layer = sc_telemetry::TelemetryLayer::new(); + let senders = telemetry_layer.senders(); let subscriber = FmtSubscriber::builder() .with_env_filter(env_filter) .with_writer(std::io::stderr) @@ -328,7 +330,7 @@ pub fn init_logger( }) .finish() .with(logging::NodeNameLayer) - .with(sc_telemetry::TelemetryLayer::new()); + .with(telemetry_layer); if let Some(profiling_targets) = profiling_targets { let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets); @@ -345,7 +347,7 @@ pub fn init_logger( )) } } - Ok(()) + Ok(senders) } #[cfg(test)] diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 0027ec6985a9c..be03bf64cc62a 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.10.0" +parking_lot = "0.11.0" futures = "0.3.4" futures-timer = "3.0.1" wasm-timer = "0.2.0" diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 97e7deaccf436..140c373953714 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,10 +16,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use futures::channel::mpsc; -use std::sync::{Arc, Mutex}; -use tracing::Subscriber; -use tracing_subscriber::{registry::LookupSpan, Layer}; +use futures::{channel::mpsc, prelude::*}; +use std::sync::{Arc}; +use tracing::{Subscriber, Event, Id, span::Attributes}; +use tracing_subscriber::{registry::LookupSpan, Layer, layer::Context}; +use parking_lot::Mutex; +use std::collections::HashMap; +use std::convert::TryInto; + +pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; pub struct TelemetryLayer(Senders); @@ -33,7 +38,58 @@ impl TelemetryLayer { } } -impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> {} +impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> { + fn on_event(&self, event: &Event<'_>, ctx: Context) { + for span in ctx.scope() { + if span.name() == TELEMETRY_LOG_SPAN { + let mut attrs = (None, None); + let mut vis = TelemetryAttrsVisitor(&mut attrs); + event.record(&mut vis); + + match attrs { + (Some(message_verbosity), Some(json)) => { + let id = span.id().into_u64(); + self.0.0.lock().get_mut(&id) + .expect("a telemetry span has not been registered to the TelemetryLayer") + .send(( + message_verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )); + }, + _ => panic!("missing fields in telemetry log"), + } + } + } + } +} + +struct TelemetryAttrsVisitor<'a>(&'a mut (Option, Option)); + +impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { + fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) { + // noop + } + + fn record_u64(&mut self, field: &tracing::field::Field, value: u64) { + if field.name() == "message_verbosity" { + (*self.0).0 = Some(value) + } + } + + fn record_str(&mut self, field: &tracing::field::Field, value: &str) { + if field.name() == "json" { + (*self.0).1 = Some(value.to_string()) + } + } +} #[derive(Default, Debug, Clone)] -pub struct Senders(Arc>>>>); +pub struct Senders(Arc>>>>); + +impl Senders { + pub fn insert(&mut self, id: u64, sender: mpsc::Sender<(u8, String)>) { + self.0.lock().insert(id, std::panic::AssertUnwindSafe(sender)); + } +} diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index fdbf0871bb3b5..5ad74e70823df 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -156,13 +156,13 @@ fn url_to_multiaddr(url: &str) -> Result { } /// Log levels. -pub const SUBSTRATE_DEBUG: &str = "9"; -pub const SUBSTRATE_INFO: &str = "0"; +pub const SUBSTRATE_DEBUG: u8 = 9; +pub const SUBSTRATE_INFO: u8 = 0; -pub const CONSENSUS_TRACE: &str = "9"; -pub const CONSENSUS_DEBUG: &str = "5"; -pub const CONSENSUS_WARN: &str = "4"; -pub const CONSENSUS_INFO: &str = "1"; +pub const CONSENSUS_TRACE: u8 = 9; +pub const CONSENSUS_DEBUG: u8 = 5; +pub const CONSENSUS_WARN: u8 = 4; +pub const CONSENSUS_INFO: u8 = 1; /// Telemetry object. Implements `Future` and must be polled regularly. /// Contains an `Arc` and can be cloned and pass around. Only one clone needs to be polled @@ -171,9 +171,23 @@ pub const CONSENSUS_INFO: &str = "1"; #[derive(Clone)] pub struct Telemetry { inner: Arc>, - /// Logger used to report telemetry. - pub logger: Logger, span: tracing::Span, + sender: mpsc::Sender<(u8, String)>, +} + +impl Telemetry { + /// TODO + pub fn push_sender(&self, mut senders: Senders) { + senders.insert( + self.span.id().expect("the span is enabled; qed").into_u64(), + self.sender.clone(), + ) + } + + /// TODO + pub fn enter(&self) -> tracing::span::Entered { + self.span.enter() + } } /// Behind the `Mutex` in `Telemetry`. @@ -186,7 +200,7 @@ struct TelemetryInner { /// Worker for the telemetry. `None` if it failed to initialize. worker: Option, /// Receives log entries for them to be dispatched to the worker. - receiver: mpsc::Receiver, + receiver: mpsc::Receiver<(u8, String)>, } /// Implements `slog::Drain`. @@ -204,10 +218,12 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { let (endpoints, wasm_external_transport) = (config.endpoints.0, config.wasm_external_transport); let (sender, receiver) = mpsc::channel(16); + /* let logger = { let logger = TelemetryDrain { sender: std::panic::AssertUnwindSafe(sender) }; slog::Logger::root(slog::Drain::fuse(logger), slog::o!()) }; + */ let worker = match worker::TelemetryWorker::new(endpoints, wasm_external_transport) { Ok(w) => Some(w), @@ -217,15 +233,16 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { } }; - let span = tracing::info_span!("telemetry-logger"); + let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let id = span.id(); Telemetry { inner: Arc::new(Mutex::new(TelemetryInner { worker, receiver, })), - logger, span, + sender, } } @@ -278,7 +295,8 @@ impl Stream for Telemetry { if let Poll::Ready(Some(log_entry)) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) { if let Some(worker) = inner.worker.as_mut() { - log_entry.as_record_values(|rec, val| { let _ = worker.log(rec, val); }); + todo!(); + //log_entry.as_record_values(|rec, val| { let _ = worker.log(rec, val); }); } } else { break; @@ -348,12 +366,13 @@ macro_rules! telemetry { $crate::slog::slog_info!(l, #$a, $b; $($t)* ) } */ + let message_verbosity: u8 = $a; let mut json = format_fields_to_json!($($t)*); json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); $crate::tracing::info!(target: "telemetry-logger", - message_verbosity = $a, + message_verbosity, //json = s.as_str() json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed").as_str() From 8037027a7d9648a53ab8f01275961b21d979a374 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 10:23:46 +0100 Subject: [PATCH 015/222] WIP --- client/telemetry/src/lib.rs | 9 ++++++--- client/telemetry/src/worker.rs | 20 ++------------------ 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5ad74e70823df..f4e2f6b509694 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -293,10 +293,13 @@ impl Stream for Telemetry { } } - if let Poll::Ready(Some(log_entry)) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) { + if let Poll::Ready(Some(( + message_verbosity, + json, + ))) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) + { if let Some(worker) = inner.worker.as_mut() { - todo!(); - //log_entry.as_record_values(|rec, val| { let _ = worker.log(rec, val); }); + worker.log(message_verbosity, json.as_str()); } } else { break; diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index e01ac62d12dc3..f67ed525f209c 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -140,16 +140,7 @@ impl TelemetryWorker { /// /// Keep in mind that you should call `TelemetryWorker::poll` in order to process the messages. /// You should call this function right after calling `slog::Drain::log`. - pub fn log(&mut self, record: &slog::Record, values: &slog::OwnedKVList) -> Result<(), ()> { - let msg_verbosity = match record.tag().parse::() { - Ok(v) => v, - Err(err) => { - warn!(target: "telemetry", "Failed to parse telemetry tag {:?}: {:?}", - record.tag(), err); - return Err(()) - } - }; - + pub fn log(&mut self, msg_verbosity: u8, json: &str) -> Result<(), ()> { // None of the nodes want that verbosity, so just return without doing any serialization. if self.nodes.iter().all(|(_, node_max_verbosity)| msg_verbosity > *node_max_verbosity) { trace!( @@ -160,13 +151,6 @@ impl TelemetryWorker { return Ok(()) } - // Turn the message into JSON. - let serialized = { - let mut out = Vec::new(); - slog_json::Json::default(&mut out).log(record, values).map_err(|_| ())?; - out - }; - for (node, node_max_verbosity) in &mut self.nodes { if msg_verbosity > *node_max_verbosity { trace!(target: "telemetry", "Skipping {:?} for log entry with verbosity {:?}", @@ -175,7 +159,7 @@ impl TelemetryWorker { } // `send_message` returns an error if we're not connected, which we silently ignore. - let _ = node.send_message(&serialized.clone()[..]); + let _ = node.send_message(json); } Ok(()) From 536bb7bfd72a73fd74098bfb3cc89e09b393c5a4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 10:41:32 +0100 Subject: [PATCH 016/222] Revert passing object logger everywhere --- bin/node-template/node/src/service.rs | 15 +- bin/node/bench/src/construct.rs | 1 - bin/node/cli/src/service.rs | 15 +- bin/node/testing/src/bench.rs | 1 - .../basic-authorship/src/basic_authorship.rs | 10 +- client/consensus/aura/src/lib.rs | 18 +- client/consensus/babe/src/lib.rs | 18 +- client/consensus/slots/src/lib.rs | 43 +-- client/finality-grandpa/src/authorities.rs | 7 +- .../src/communication/gossip.rs | 18 +- .../finality-grandpa/src/communication/mod.rs | 307 ++++++++---------- client/finality-grandpa/src/environment.rs | 14 +- client/finality-grandpa/src/finality_proof.rs | 5 +- client/finality-grandpa/src/import.rs | 14 +- client/finality-grandpa/src/lib.rs | 29 +- client/finality-grandpa/src/light_import.rs | 10 +- client/finality-grandpa/src/observer.rs | 10 - client/service/src/builder.rs | 29 +- client/service/src/client/client.rs | 13 +- client/service/src/client/light.rs | 4 +- client/service/src/metrics.rs | 11 +- client/telemetry/src/lib.rs | 3 +- client/tracing/src/lib.rs | 14 +- test-utils/client/src/lib.rs | 1 - 24 files changed, 213 insertions(+), 397 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 4456ee9d62258..a8d335cc49382 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -53,10 +53,7 @@ pub fn new_partial(config: &Configuration) -> Result), - select_chain.clone(), - telemetry.as_ref().map(|x| x.logger.clone()), + client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( @@ -73,7 +70,6 @@ pub fn new_partial(config: &Configuration) -> Result Result { client.clone(), transaction_pool, prometheus_registry.as_ref(), - telemetry.as_ref().map(|x| x.logger.clone()), ); let can_author_with = @@ -189,7 +184,6 @@ pub fn new_full(config: Configuration) -> Result { force_authoring, keystore_container.sync_keystore(), can_author_with, - telemetry.as_ref().map(|x| x.logger.clone()), )?; // the AURA authoring task is considered essential, i.e. if it @@ -230,7 +224,6 @@ pub fn new_full(config: Configuration) -> Result { voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), - logger: telemetry.as_ref().map(|x| x.logger.clone()), }; // the GRANDPA voter task is considered infallible, i.e. @@ -261,11 +254,8 @@ pub fn new_light(config: Configuration) -> Result { )); let grandpa_block_import = sc_finality_grandpa::light_block_import( - client.clone(), - backend.clone(), - &(client.clone() as Arc<_>), + client.clone(), backend.clone(), &(client.clone() as Arc<_>), Arc::new(on_demand.checker().clone()) as Arc<_>, - telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_import = grandpa_block_import.clone(); let finality_proof_request_builder = @@ -281,7 +271,6 @@ pub fn new_light(config: Configuration) -> Result { &task_manager.spawn_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, - telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_provider = diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index 425f32fc55ceb..5506dc426de0b 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -151,7 +151,6 @@ impl core::Benchmark for ConstructionBenchmark { context.client.clone(), self.transactions.clone().into(), None, - None, ); let inherent_data_providers = sp_inherents::InherentDataProviders::new(); inherent_data_providers diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 006ed2077084a..627c10c2f8d5d 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -77,10 +77,7 @@ pub fn new_partial(config: &Configuration) -> Result), - select_chain.clone(), - telemetry.as_ref().map(|x| x.logger.clone()), + client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), )?; let justification_import = grandpa_block_import.clone(); @@ -103,7 +100,6 @@ pub fn new_partial(config: &Configuration) -> Result Result<( )); let grandpa_block_import = grandpa::light_block_import( - client.clone(), - backend.clone(), - &(client.clone() as Arc<_>), + client.clone(), backend.clone(), &(client.clone() as Arc<_>), Arc::new(on_demand.checker().clone()), - telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_import = grandpa_block_import.clone(); @@ -413,7 +403,6 @@ pub fn new_light_base(config: Configuration) -> Result<( &task_manager.spawn_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, - telemetry.as_ref().map(|x| x.logger.clone()), )?; let finality_proof_provider = diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 3374d889efe0d..153a52375c2a9 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -425,7 +425,6 @@ impl BenchDb { Box::new(task_executor.clone()), None, Default::default(), - None, ).expect("Should not fail"); (client, backend, task_executor) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 6d170abc502d4..89edfac0d4e98 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -32,7 +32,7 @@ use sp_runtime::{ traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256}, }; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; use sp_api::{ProvideRuntimeApi, ApiExt}; use futures::{future, future::{Future, FutureExt}, channel::oneshot, select}; @@ -51,8 +51,6 @@ pub struct ProposerFactory { transaction_pool: Arc, /// Prometheus Link, metrics: PrometheusMetrics, - /// Logger instance used for metrics. - logger: Option, /// phantom member to pin the `Backend` type. _phantom: PhantomData, } @@ -63,14 +61,12 @@ impl ProposerFactory { client: Arc, transaction_pool: Arc, prometheus: Option<&PrometheusRegistry>, - logger: Option, ) -> Self { ProposerFactory { spawn_handle: Box::new(spawn_handle), client, transaction_pool, metrics: PrometheusMetrics::new(prometheus), - logger, _phantom: PhantomData, } } @@ -106,7 +102,6 @@ impl ProposerFactory transaction_pool: self.transaction_pool.clone(), now, metrics: self.metrics.clone(), - logger: self.logger.clone(), _phantom: PhantomData, }; @@ -147,7 +142,6 @@ pub struct Proposer { transaction_pool: Arc, now: Box time::Instant + Send + Sync>, metrics: PrometheusMetrics, - logger: Option, _phantom: PhantomData, } @@ -331,7 +325,7 @@ impl Proposer .collect::>() .join(", ") ); - telemetry!(self.logger; CONSENSUS_INFO; "prepared_block_for_proposing"; + telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing"; "number" => ?block.header().number(), "hash" => ?::Hash::from(block.header().hash()), ); diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 37175ff709ef8..5013c1813b685 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -69,7 +69,7 @@ use sp_inherents::{InherentDataProviders, InherentData}; use sp_timestamp::{ TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError }; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; use sc_consensus_slots::{ CheckedHeader, SlotInfo, SlotCompatible, StorageChanges, check_equivocation, @@ -149,7 +149,6 @@ pub fn start_aura( force_authoring: bool, keystore: SyncCryptoStorePtr, can_author_with: CAW, - logger: Option, ) -> Result, sp_consensus::Error> where B: BlockT, C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, @@ -172,7 +171,6 @@ pub fn start_aura( keystore, sync_oracle: sync_oracle.clone(), force_authoring, - logger, _key_type: PhantomData::

, }; register_aura_inherent_data_provider( @@ -197,7 +195,6 @@ struct AuraWorker { keystore: SyncCryptoStorePtr, sync_oracle: SO, force_authoring: bool, - logger: Option, _key_type: PhantomData

, } @@ -355,10 +352,6 @@ where Some(slot_remaining) } } - - fn logger(&self) -> Option { - self.logger.clone() - } } fn aura_err(error: Error) -> Error { @@ -488,7 +481,6 @@ pub struct AuraVerifier { phantom: PhantomData

, inherent_data_providers: sp_inherents::InherentDataProviders, can_author_with: CAW, - logger: Option, } impl AuraVerifier where @@ -540,7 +532,7 @@ impl AuraVerifier where "halting for block {} seconds in the future", diff ); - telemetry!(self.logger; CONSENSUS_INFO; "aura.halting_for_future_block"; + telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block"; "diff" => ?diff ); thread::sleep(Duration::from_secs(diff)); @@ -630,7 +622,7 @@ impl Verifier for AuraVerifier where } trace!(target: "aura", "Checked {:?}; importing.", pre_header); - telemetry!(self.logger; CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); + telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); // Look for an authorities-change log. let maybe_keys = pre_header.digest() @@ -657,7 +649,7 @@ impl Verifier for AuraVerifier where } CheckedHeader::Deferred(a, b) => { debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); - telemetry!(self.logger; CONSENSUS_DEBUG; "aura.header_too_far_in_future"; + telemetry!(CONSENSUS_DEBUG; "aura.header_too_far_in_future"; "hash" => ?hash, "a" => ?a, "b" => ?b ); Err(format!("Header {:?} rejected: too far in the future", hash)) @@ -828,7 +820,6 @@ pub fn import_queue( spawner: &S, registry: Option<&Registry>, can_author_with: CAW, - logger: Option, ) -> Result, sp_consensus::Error> where B: BlockT, C::Api: BlockBuilderApi + AuraApi> + ApiExt, @@ -849,7 +840,6 @@ pub fn import_queue( inherent_data_providers, phantom: PhantomData, can_author_with, - logger, }; Ok(BasicQueue::new( diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index e9e0977e1fc5b..4705381c2b918 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -92,7 +92,7 @@ use sp_runtime::{ use sp_api::{ProvideRuntimeApi, NumberFor}; use parking_lot::Mutex; use sp_inherents::{InherentDataProviders, InherentData}; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; +use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; use sp_consensus::{ self, BlockImport, Environment, Proposer, BlockCheckParams, ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, @@ -358,9 +358,6 @@ pub struct BabeParams { /// Checks if the current native implementation can author with a runtime at a given block. pub can_author_with: CAW, - - /// Logger instant use for metrics. - pub logger: Option, } /// Start the babe worker. @@ -375,7 +372,6 @@ pub fn start_babe(BabeParams { force_authoring, babe_link, can_author_with, - logger, }: BabeParams) -> Result< BabeWorker, sp_consensus::Error, @@ -406,7 +402,6 @@ pub fn start_babe(BabeParams { epoch_changes: babe_link.epoch_changes.clone(), slot_notification_sinks: slot_notification_sinks.clone(), config: config.clone(), - logger, }; register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; @@ -477,7 +472,6 @@ struct BabeSlotWorker { epoch_changes: SharedEpochChanges, slot_notification_sinks: SlotNotificationSinks, config: Config, - logger: Option, } impl sc_consensus_slots::SimpleSlotWorker for BabeSlotWorker where @@ -671,10 +665,6 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeSlot Some(slot_remaining) } } - - fn logger(&self) -> Option { - self.logger.clone() - } } /// Extract the BABE pre digest from the given header. Pre-runtime digests are @@ -786,7 +776,6 @@ pub struct BabeVerifier { epoch_changes: SharedEpochChanges, time_source: TimeSource, can_author_with: CAW, - logger: Option, } impl BabeVerifier @@ -1015,7 +1004,6 @@ where trace!(target: "babe", "Checked {:?}; importing.", pre_header); telemetry!( - self.logger; CONSENSUS_TRACE; "babe.checked_and_importing"; "pre_header" => ?pre_header); @@ -1034,7 +1022,7 @@ where } CheckedHeader::Deferred(a, b) => { debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); - telemetry!(self.logger; CONSENSUS_DEBUG; "babe.header_too_far_in_future"; + telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future"; "hash" => ?hash, "a" => ?a, "b" => ?b ); Err(Error::::TooFarInFuture(hash).into()) @@ -1442,7 +1430,6 @@ pub fn import_queue( spawner: &impl sp_core::traits::SpawnNamed, registry: Option<&Registry>, can_author_with: CAW, - logger: Option, ) -> ClientResult> where Inner: BlockImport> + Send + Sync + 'static, @@ -1462,7 +1449,6 @@ pub fn import_queue( epoch_changes: babe_link.epoch_changes, time_source: babe_link.time_source, can_author_with, - logger, }; Ok(BasicQueue::new( diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 4127b28fd9f0f..ad4e4924bc850 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -39,7 +39,7 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header, HashFor, NumberFor}; use sp_api::{ProvideRuntimeApi, ApiRef}; use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc, time::{Instant, Duration}}; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; use parking_lot::Mutex; /// The changes that need to applied to the storage to create the state for a block. @@ -164,9 +164,6 @@ pub trait SimpleSlotWorker { /// Returns a `Proposer` to author on top of the given block. fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer; - /// Returns the `Logger` instance used for metrics. - fn logger(&self) -> Option; - /// Remaining duration of the slot. fn slot_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { let now = Instant::now(); @@ -195,8 +192,6 @@ pub trait SimpleSlotWorker { where >::Proposal: Unpin + Send + 'static, { - let logger = self.logger(); - let (timestamp, slot_number) = (slot_info.timestamp, slot_info.number); let slot_remaining_duration = self.slot_remaining_duration(&slot_info); @@ -222,7 +217,7 @@ pub trait SimpleSlotWorker { warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err); telemetry!( - logger; CONSENSUS_WARN; "slots.unable_fetching_authorities"; + CONSENSUS_WARN; "slots.unable_fetching_authorities"; "slot" => ?chain_head.hash(), "err" => ?err, ); @@ -241,7 +236,7 @@ pub trait SimpleSlotWorker { { debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network."); telemetry!( - logger; CONSENSUS_DEBUG; + CONSENSUS_DEBUG; "slots.skipping_proposal_slot"; "authorities_len" => : authorities_len, ); @@ -261,23 +256,20 @@ pub trait SimpleSlotWorker { timestamp, ); - telemetry!(logger; CONSENSUS_DEBUG; "slots.starting_authorship"; + telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship"; "slot_num" => slot_number, "timestamp" => timestamp, ); - let awaiting_proposer = { - let logger = logger.clone(); - self.proposer(&chain_head).map_err(move |err| { - warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); + let awaiting_proposer = self.proposer(&chain_head).map_err(move |err| { + warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); - telemetry!(logger; CONSENSUS_WARN; "slots.unable_authoring_block"; - "slot" => slot_number, "err" => ?err - ); + telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block"; + "slot" => slot_number, "err" => ?err + ); - err - }) - }; + err + }); let logs = self.pre_digest_data(slot_number, &claim); @@ -291,8 +283,7 @@ pub trait SimpleSlotWorker { RecordProof::No, ).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e)))); - let proposal_work = { - let logger = logger.clone(); + let proposal_work = futures::future::select(proposing, proposing_remaining).map(move |v| match v { Either::Left((b, _)) => b.map(|b| (b, claim)), Either::Right(_) => { @@ -300,19 +291,17 @@ pub trait SimpleSlotWorker { // If the node was compiled with debug, tell the user to use release optimizations. #[cfg(build_type="debug")] info!("👉 Recompile your node in `--release` mode to mitigate this problem."); - telemetry!(logger; CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; + telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; "slot" => slot_number, ); Err(sp_consensus::Error::ClientImport("Timeout in the Slots proposer".into())) }, - }) - }; + }); let block_import_params_maker = self.block_import_params(); let block_import = self.block_import(); let logging_target = self.logging_target(); - let logger = logger.clone(); proposal_work.and_then(move |(proposal, claim)| async move { let (block, storage_proof) = (proposal.block, proposal.proof); @@ -337,7 +326,7 @@ pub trait SimpleSlotWorker { header_hash, ); - telemetry!(logger; CONSENSUS_INFO; "slots.pre_sealed_block"; + telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block"; "header_num" => ?header_num, "hash_now" => ?block_import_params.post_hash(), "hash_previously" => ?header_hash, @@ -352,7 +341,7 @@ pub trait SimpleSlotWorker { ); telemetry!( - logger; CONSENSUS_WARN; "slots.err_with_block_built_on"; + CONSENSUS_WARN; "slots.err_with_block_built_on"; "hash" => ?parent_hash, "err" => ?err, ); diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 03fc4814605d5..2de169fc8285a 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -23,7 +23,7 @@ use parking_lot::RwLock; use finality_grandpa::voter_set::VoterSet; use parity_scale_codec::{Encode, Decode}; use log::debug; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList}; use std::cmp::Ord; @@ -397,7 +397,6 @@ where best_number: N, is_descendent_of: &F, initial_sync: bool, - logger: Option<&Logger>, ) -> Result, Error> where F: Fn(&H, &H) -> Result, @@ -450,7 +449,6 @@ where ); telemetry!( - logger; CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; "block" => ?change.canon_height @@ -491,7 +489,6 @@ where finalized_number: N, is_descendent_of: &F, initial_sync: bool, - logger: Option<&Logger>, ) -> Result, Error> where F: Fn(&H, &H) -> Result, @@ -531,7 +528,7 @@ where "👴 Applying authority set change scheduled at block #{:?}", change.canon_height, ); - telemetry!(logger; CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; + telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; "block" => ?change.canon_height ); diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 98c8e5cd18343..276529d555ffe 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -85,7 +85,6 @@ use sp_runtime::traits::{NumberFor, Block as BlockT, Zero}; use sc_network_gossip::{MessageIntent, ValidatorContext}; use sc_network::{ObservedRole, PeerId, ReputationChange}; -use sc_telemetry::slog::Logger; use parity_scale_codec::{Encode, Decode}; use sp_finality_grandpa::AuthorityId; @@ -681,13 +680,12 @@ struct Inner { next_rebroadcast: Instant, pending_catch_up: PendingCatchUp, catch_up_config: CatchUpConfig, - logger: Option, } type MaybeMessage = Option<(Vec, NeighborPacket>)>; impl Inner { - fn new(config: crate::Config, logger: Option) -> Self { + fn new(config: crate::Config) -> Self { let catch_up_config = if config.observer_enabled { if config.is_authority { // since the observer protocol is enabled, we will only issue @@ -714,7 +712,6 @@ impl Inner { pending_catch_up: PendingCatchUp::None, catch_up_config, config, - logger, } } @@ -832,7 +829,7 @@ impl Inner { // ensure authority is part of the set. if !self.authorities.contains(&full.message.id) { debug!(target: "afg", "Message from unknown voter: {}", full.message.id); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); return Action::Discard(cost::UNKNOWN_VOTER); } @@ -844,7 +841,7 @@ impl Inner { full.set_id.0, ) { debug!(target: "afg", "Bad message signature {}", full.message.id); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); return Action::Discard(cost::BAD_SIGNATURE); } @@ -870,7 +867,7 @@ impl Inner { if full.message.precommits.len() != full.message.auth_data.len() || full.message.precommits.is_empty() { debug!(target: "afg", "Malformed compact commit"); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.malformed_compact_commit"; + telemetry!(CONSENSUS_DEBUG; "afg.malformed_compact_commit"; "precommits_len" => ?full.message.precommits.len(), "auth_data_len" => ?full.message.auth_data.len(), "precommits_is_empty" => ?full.message.precommits.is_empty(), @@ -1283,7 +1280,6 @@ pub(super) struct GossipValidator { set_state: environment::SharedVoterSetState, report_sender: TracingUnboundedSender, metrics: Option, - logger: Option, } impl GossipValidator { @@ -1294,7 +1290,6 @@ impl GossipValidator { config: crate::Config, set_state: environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, - logger: Option, ) -> (GossipValidator, TracingUnboundedReceiver) { let metrics = match prometheus_registry.map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), @@ -1307,11 +1302,10 @@ impl GossipValidator { let (tx, rx) = tracing_unbounded("mpsc_grandpa_gossip_validator"); let val = GossipValidator { - inner: parking_lot::RwLock::new(Inner::new(config, logger.clone())), + inner: parking_lot::RwLock::new(Inner::new(config)), set_state, report_sender: tx, metrics, - logger, }; (val, rx) @@ -1420,7 +1414,7 @@ impl GossipValidator { Err(e) => { message_name = None; debug!(target: "afg", "Error decoding message: {}", e.what()); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); + telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); let len = std::cmp::min(i32::max_value() as usize, data.len()) as i32; Action::Discard(Misbehavior::UndecodablePacket(len).cost()) diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index edd2c85f5ad69..3daffcb9f2522 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -42,7 +42,7 @@ use sc_network::{NetworkService, ReputationChange}; use sc_network_gossip::{GossipEngine, Network as GossipNetwork}; use parity_scale_codec::{Encode, Decode}; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; use crate::{ CatchUp, Commit, CommunicationIn, CommunicationOutH, @@ -170,7 +170,6 @@ pub(crate) struct NetworkBridge> { service: N, gossip_engine: Arc>>, validator: Arc>, - logger: Option, /// Sender side of the neighbor packet channel. /// @@ -206,13 +205,11 @@ impl> NetworkBridge { config: crate::Config, set_state: crate::environment::SharedVoterSetState, prometheus_registry: Option<&Registry>, - logger: Option, ) -> Self { let (validator, report_stream) = GossipValidator::new( config, set_state.clone(), prometheus_registry, - logger.clone(), ); let validator = Arc::new(validator); @@ -270,7 +267,6 @@ impl> NetworkBridge { neighbor_sender: neighbor_packet_sender, neighbor_packet_worker: Arc::new(Mutex::new(neighbor_packet_worker)), gossip_validator_report_stream: Arc::new(Mutex::new(report_stream)), - logger, } } @@ -323,59 +319,56 @@ impl> NetworkBridge { }); let topic = round_topic::(round.0, set_id.0); - let incoming = { - let logger = self.logger.clone(); - self.gossip_engine.lock().messages_for(topic) - .filter_map(move |notification| { - let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); - - match decoded { - Err(ref e) => { - debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); - future::ready(None) - } - Ok(GossipMessage::Vote(msg)) => { - // check signature. - if !voters.contains(&msg.message.id) { - debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); - return future::ready(None); - } - - if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { - match &msg.message.message { - PrimaryPropose(propose) => { - telemetry!(logger; CONSENSUS_INFO; "afg.received_propose"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?propose.target_number, - "target_hash" => ?propose.target_hash, - ); - }, - Prevote(prevote) => { - telemetry!(logger; CONSENSUS_INFO; "afg.received_prevote"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?prevote.target_number, - "target_hash" => ?prevote.target_hash, - ); - }, - Precommit(precommit) => { - telemetry!(logger; CONSENSUS_INFO; "afg.received_precommit"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?precommit.target_number, - "target_hash" => ?precommit.target_hash, - ); - }, - }; - } - - future::ready(Some(msg.message)) + let incoming = self.gossip_engine.lock().messages_for(topic) + .filter_map(move |notification| { + let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); + + match decoded { + Err(ref e) => { + debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); + future::ready(None) + } + Ok(GossipMessage::Vote(msg)) => { + // check signature. + if !voters.contains(&msg.message.id) { + debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); + return future::ready(None); } - _ => { - debug!(target: "afg", "Skipping unknown message type"); - future::ready(None) + + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { + match &msg.message.message { + PrimaryPropose(propose) => { + telemetry!(CONSENSUS_INFO; "afg.received_propose"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?propose.target_number, + "target_hash" => ?propose.target_hash, + ); + }, + Prevote(prevote) => { + telemetry!(CONSENSUS_INFO; "afg.received_prevote"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?prevote.target_number, + "target_hash" => ?prevote.target_hash, + ); + }, + Precommit(precommit) => { + telemetry!(CONSENSUS_INFO; "afg.received_precommit"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?precommit.target_number, + "target_hash" => ?precommit.target_hash, + ); + }, + }; } + + future::ready(Some(msg.message)) } - }) - }; + _ => { + debug!(target: "afg", "Skipping unknown message type"); + future::ready(None) + } + } + }); let (tx, out_rx) = mpsc::channel(0); let outgoing = OutgoingMessages:: { @@ -385,7 +378,6 @@ impl> NetworkBridge { network: self.gossip_engine.clone(), sender: tx, has_voted, - logger: self.logger.clone(), }; // Combine incoming votes from external GRANDPA nodes with outgoing @@ -419,7 +411,6 @@ impl> NetworkBridge { voters, self.validator.clone(), self.neighbor_sender.clone(), - self.logger.clone(), ); let outgoing = CommitsOut::::new( @@ -428,7 +419,6 @@ impl> NetworkBridge { is_voter, self.validator.clone(), self.neighbor_sender.clone(), - self.logger.clone(), ); let outgoing = outgoing.with(|out| { @@ -500,119 +490,110 @@ fn incoming_global( voters: Arc>, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Option, ) -> impl Stream> { - let process_commit = { - let logger = logger.clone(); - move | - msg: FullCommitMessage, - mut notification: sc_network_gossip::TopicNotification, - gossip_engine: &Arc>>, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { - let precommits_signed_by: Vec = - msg.message.auth_data.iter().map(move |(_, a)| { - format!("{}", a) - }).collect(); - - telemetry!(logger; CONSENSUS_INFO; "afg.received_commit"; - "contains_precommits_signed_by" => ?precommits_signed_by, - "target_number" => ?msg.message.target_number.clone(), - "target_hash" => ?msg.message.target_hash.clone(), - ); - } - - if let Err(cost) = check_compact_commit::( - &msg.message, - voters, - msg.round, - msg.set_id, - logger.as_ref(), - ) { - if let Some(who) = notification.sender { - gossip_engine.lock().report(who, cost); - } + let process_commit = move | + msg: FullCommitMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &Arc>>, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { + let precommits_signed_by: Vec = + msg.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + + telemetry!(CONSENSUS_INFO; "afg.received_commit"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "target_number" => ?msg.message.target_number.clone(), + "target_hash" => ?msg.message.target_hash.clone(), + ); + } - return None; + if let Err(cost) = check_compact_commit::( + &msg.message, + voters, + msg.round, + msg.set_id, + ) { + if let Some(who) = notification.sender { + gossip_engine.lock().report(who, cost); } - let round = msg.round; - let set_id = msg.set_id; - let commit = msg.message; - let finalized_number = commit.target_number; - let gossip_validator = gossip_validator.clone(); - let gossip_engine = gossip_engine.clone(); - let neighbor_sender = neighbor_sender.clone(); - let cb = move |outcome| match outcome { - voter::CommitProcessingOutcome::Good(_) => { - // if it checks out, gossip it. not accounting for - // any discrepancy between the actual ghost and the claimed - // finalized number. - gossip_validator.note_commit_finalized( - round, - set_id, - finalized_number, - |to, neighbor| neighbor_sender.send(to, neighbor), - ); + return None; + } - gossip_engine.lock().gossip_message(topic, notification.message.clone(), false); - } - voter::CommitProcessingOutcome::Bad(_) => { - // report peer and do not gossip. - if let Some(who) = notification.sender.take() { - gossip_engine.lock().report(who, cost::INVALID_COMMIT); - } + let round = msg.round; + let set_id = msg.set_id; + let commit = msg.message; + let finalized_number = commit.target_number; + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); + let neighbor_sender = neighbor_sender.clone(); + let cb = move |outcome| match outcome { + voter::CommitProcessingOutcome::Good(_) => { + // if it checks out, gossip it. not accounting for + // any discrepancy between the actual ghost and the claimed + // finalized number. + gossip_validator.note_commit_finalized( + round, + set_id, + finalized_number, + |to, neighbor| neighbor_sender.send(to, neighbor), + ); + + gossip_engine.lock().gossip_message(topic, notification.message.clone(), false); + } + voter::CommitProcessingOutcome::Bad(_) => { + // report peer and do not gossip. + if let Some(who) = notification.sender.take() { + gossip_engine.lock().report(who, cost::INVALID_COMMIT); } - }; + } + }; - let cb = voter::Callback::Work(Box::new(cb)); + let cb = voter::Callback::Work(Box::new(cb)); - Some(voter::CommunicationIn::Commit(round.0, commit, cb)) - } + Some(voter::CommunicationIn::Commit(round.0, commit, cb)) }; - let process_catch_up = { - let logger = logger.clone(); - move | - msg: FullCatchUpMessage, - mut notification: sc_network_gossip::TopicNotification, - gossip_engine: &Arc>>, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - let gossip_validator = gossip_validator.clone(); - let gossip_engine = gossip_engine.clone(); - - if let Err(cost) = check_catch_up::( - &msg.message, - voters, - msg.set_id, - logger.as_ref(), - ) { - if let Some(who) = notification.sender { - gossip_engine.lock().report(who, cost); - } + let process_catch_up = move | + msg: FullCatchUpMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &Arc>>, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); - return None; + if let Err(cost) = check_catch_up::( + &msg.message, + voters, + msg.set_id, + ) { + if let Some(who) = notification.sender { + gossip_engine.lock().report(who, cost); } - let cb = move |outcome| { - if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { - // report peer - if let Some(who) = notification.sender.take() { - gossip_engine.lock().report(who, cost::INVALID_CATCH_UP); - } + return None; + } + + let cb = move |outcome| { + if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { + // report peer + if let Some(who) = notification.sender.take() { + gossip_engine.lock().report(who, cost::INVALID_CATCH_UP); } + } - gossip_validator.note_catch_up_message_processed(); - }; + gossip_validator.note_catch_up_message_processed(); + }; - let cb = voter::Callback::Work(Box::new(cb)); + let cb = voter::Callback::Work(Box::new(cb)); - Some(voter::CommunicationIn::CatchUp(msg.message, cb)) - } + Some(voter::CommunicationIn::CatchUp(msg.message, cb)) }; gossip_engine.clone().lock().messages_for(topic) @@ -647,7 +628,6 @@ impl> Clone for NetworkBridge { neighbor_sender: self.neighbor_sender.clone(), neighbor_packet_worker: self.neighbor_packet_worker.clone(), gossip_validator_report_stream: self.gossip_validator_report_stream.clone(), - logger: self.logger.clone(), } } } @@ -674,7 +654,6 @@ pub(crate) struct OutgoingMessages { sender: mpsc::Sender>, network: Arc>>, has_voted: HasVoted, - logger: Option, } impl Unpin for OutgoingMessages {} @@ -737,7 +716,7 @@ impl Sink> for OutgoingMessages ); telemetry!( - self.logger; CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; + CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; "block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id, ); @@ -776,7 +755,6 @@ fn check_compact_commit( voters: &VoterSet, round: Round, set_id: SetId, - logger: Option<&Logger>, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -818,7 +796,7 @@ fn check_compact_commit( &mut buf, ) { debug!(target: "afg", "Bad commit message signature {}", id); - telemetry!(logger; CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); let cost = Misbehavior::BadCommitMessage { signatures_checked: i as i32, blocks_loaded: 0, @@ -838,7 +816,6 @@ fn check_catch_up( msg: &CatchUp, voters: &VoterSet, set_id: SetId, - logger: Option<&Logger>, ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); @@ -889,7 +866,6 @@ fn check_catch_up( set_id: SetIdNumber, mut signatures_checked: usize, buf: &mut Vec, - logger: Option<&Logger>, ) -> Result where B: BlockT, I: Iterator, &'a AuthorityId, &'a AuthoritySignature)>, @@ -908,7 +884,7 @@ fn check_catch_up( buf, ) { debug!(target: "afg", "Bad catch up message signature {}", id); - telemetry!(logger; CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); let cost = Misbehavior::BadCatchUpMessage { signatures_checked: signatures_checked as i32, @@ -932,7 +908,6 @@ fn check_catch_up( set_id.0, 0, &mut buf, - logger, )?; // check signatures on all contained precommits. @@ -944,7 +919,6 @@ fn check_catch_up( set_id.0, signatures_checked, &mut buf, - logger, )?; Ok(()) @@ -957,7 +931,6 @@ struct CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Option, } impl CommitsOut { @@ -968,7 +941,6 @@ impl CommitsOut { is_voter: bool, gossip_validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, - logger: Option, ) -> Self { CommitsOut { network, @@ -976,7 +948,6 @@ impl CommitsOut { is_voter, gossip_validator, neighbor_sender, - logger, } } } @@ -996,7 +967,7 @@ impl Sink<(RoundNumber, Commit)> for CommitsOut { let (round, commit) = input; let round = Round(round); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.commit_issued"; + telemetry!(CONSENSUS_DEBUG; "afg.commit_issued"; "target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash, ); let (precommits, auth_data) = commit.precommits.into_iter() diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 5d307cbb8ea96..7f9e966c9acc2 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -39,7 +39,7 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, }; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; use crate::{ local_authority_id, CommandOrError, Commit, Config, Error, NewAuthoritySet, Precommit, Prevote, @@ -423,7 +423,6 @@ pub(crate) struct Environment, SC, pub(crate) voting_rule: VR, pub(crate) metrics: Option, pub(crate) justification_sender: Option>, - pub(crate) logger: Option, pub(crate) _phantom: PhantomData, } @@ -832,7 +831,7 @@ where }; let report_prevote_metrics = |prevote: &Prevote| { - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.prevote_issued"; + telemetry!(CONSENSUS_DEBUG; "afg.prevote_issued"; "round" => round, "target_number" => ?prevote.target_number, "target_hash" => ?prevote.target_hash, @@ -893,7 +892,7 @@ where }; let report_precommit_metrics = |precommit: &Precommit| { - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.precommit_issued"; + telemetry!(CONSENSUS_DEBUG; "afg.precommit_issued"; "round" => round, "target_number" => ?precommit.target_number, "target_hash" => ?precommit.target_hash, @@ -1087,7 +1086,6 @@ where (round, commit).into(), false, self.justification_sender.as_ref(), - self.logger.clone(), ) } @@ -1153,7 +1151,6 @@ pub(crate) fn finalize_block( justification_or_commit: JustificationOrCommit, initial_sync: bool, justification_sender: Option<&GrandpaJustificationSender>, - logger: Option, ) -> Result<(), CommandOrError>> where Block: BlockT, @@ -1198,7 +1195,6 @@ where number, &is_descendent_of::(&*client, None), initial_sync, - logger.as_ref(), ).map_err(|e| Error::Safety(e.to_string()))?; // check if this is this is the first finalization of some consensus changes @@ -1296,7 +1292,7 @@ where warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); e })?; - telemetry!(logger; CONSENSUS_INFO; "afg.finalized_blocks_up_to"; + telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to"; "number" => ?number, "hash" => ?hash, ); @@ -1316,7 +1312,7 @@ where ); } - telemetry!(logger; CONSENSUS_INFO; "afg.generating_new_authority_set"; + telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set"; "number" => ?canon_number, "hash" => ?canon_hash, "authorities" => ?set_ref.to_vec(), "set_id" => ?new_id, diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 56d3c939d3c2f..33dd69cc11d6e 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -52,7 +52,7 @@ use sp_runtime::{ traits::{NumberFor, Block as BlockT, Header as HeaderT, One}, }; use sp_core::storage::StorageKey; -use sc_telemetry::{slog::Logger, telemetry, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; use crate::justification::GrandpaJustification; @@ -468,7 +468,6 @@ pub(crate) fn check_finality_proof( current_authorities: AuthorityList, authorities_provider: &dyn AuthoritySetForFinalityChecker, remote_proof: Vec, - logger: Option<&Logger>, ) -> ClientResult> where NumberFor: BlockNumberOps, @@ -511,7 +510,7 @@ pub(crate) fn check_finality_proof( check_finality_proof_fragment always returns FinalityEffects;\ qed"); - telemetry!(logger; CONSENSUS_INFO; "afg.finality_proof_ok"; + telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok"; "set_id" => ?effects.new_set_id, "finalized_header_hash" => ?effects.block); Ok(effects) diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index fc7b396b24cd7..04df95a3187e1 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -24,7 +24,6 @@ use parking_lot::RwLockWriteGuard; use sp_blockchain::{BlockStatus, well_known_cache_keys}; use sc_client_api::{backend::Backend, utils::is_descendent_of}; -use sc_telemetry::slog::Logger; use sp_utils::mpsc::TracingUnboundedSender; use sp_api::{TransactionFor}; @@ -65,7 +64,6 @@ pub struct GrandpaBlockImport { consensus_changes: SharedConsensusChanges>, authority_set_hard_forks: HashMap>>, justification_sender: GrandpaJustificationSender, - logger: Option, _phantom: PhantomData, } @@ -81,7 +79,6 @@ impl Clone for consensus_changes: self.consensus_changes.clone(), authority_set_hard_forks: self.authority_set_hard_forks.clone(), justification_sender: self.justification_sender.clone(), - logger: self.logger.clone(), _phantom: PhantomData, } } @@ -340,13 +337,7 @@ where let applied_changes = { let forced_change_set = guard .as_mut() - .apply_forced_changes( - hash, - number, - &is_descendent_of, - initial_sync, - self.logger.as_ref(), - ) + .apply_forced_changes(hash, number, &is_descendent_of, initial_sync) .map_err(|e| ConsensusError::ClientImport(e.to_string())) .map_err(ConsensusError::from)?; @@ -573,7 +564,6 @@ impl GrandpaBlockImport>, authority_set_hard_forks: Vec<(SetId, PendingChange>)>, justification_sender: GrandpaJustificationSender, - logger: Option, ) -> GrandpaBlockImport { // check for and apply any forced authority set hard fork that applies // to the *current* authority set. @@ -618,7 +608,6 @@ impl GrandpaBlockImport( client: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, - logger: Option, ) -> Result< ( GrandpaBlockImport, @@ -519,7 +518,6 @@ where genesis_authorities_provider, select_chain, Default::default(), - logger, ) } @@ -533,7 +531,6 @@ pub fn block_import_with_authority_set_hard_forks genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, - logger: Option, ) -> Result< ( GrandpaBlockImport, @@ -555,11 +552,11 @@ where >::zero(), || { let authorities = genesis_authorities_provider.get()?; - telemetry!(logger; CONSENSUS_DEBUG; "afg.loading_authorities"; + telemetry!(CONSENSUS_DEBUG; "afg.loading_authorities"; "authorities_len" => ?authorities.len() ); Ok(authorities) - }, + } )?; let (voter_commands_tx, voter_commands_rx) = tracing_unbounded("mpsc_grandpa_voter_command"); @@ -594,7 +591,6 @@ where persistent_data.consensus_changes.clone(), authority_set_hard_forks, justification_sender.clone(), - logger, ), LinkHalf { client, @@ -669,8 +665,6 @@ pub struct GrandpaParams { pub prometheus_registry: Option, /// The voter state is exposed at an RPC endpoint. pub shared_voter_state: SharedVoterState, - /// Logger used by telemtry. - pub logger: Option, } /// Run a GRANDPA voter as a task. Provide configuration and a link to a @@ -697,7 +691,6 @@ where voting_rule, prometheus_registry, shared_voter_state, - logger, } = grandpa_params; // NOTE: we have recently removed `run_grandpa_observer` from the public @@ -720,12 +713,10 @@ where config.clone(), persistent_data.set_state.clone(), prometheus_registry.as_ref(), - logger.clone(), ); let conf = config.clone(); let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect { - let logger = logger.clone(); let authorities = persistent_data.authority_set.clone(); let events = telemetry_on_connect .for_each(move |_| { @@ -744,7 +735,7 @@ where elements are always of type string", ); - telemetry!(logger; CONSENSUS_INFO; "afg.authority_set"; + telemetry!(CONSENSUS_INFO; "afg.authority_set"; "authority_id" => authority_id.to_string(), "authority_set_id" => ?set_id, "authorities" => authorities, @@ -768,7 +759,6 @@ where prometheus_registry, shared_voter_state, justification_sender, - logger, ); let voter_work = voter_work.map(|res| match res { @@ -807,7 +797,6 @@ struct VoterWork, SC, VR> { env: Arc>, voter_commands_rx: TracingUnboundedReceiver>>, network: NetworkBridge, - logger: Option, /// Prometheus metrics. metrics: Option, @@ -835,7 +824,6 @@ where prometheus_registry: Option, shared_voter_state: SharedVoterState, justification_sender: GrandpaJustificationSender, - logger: Option, ) -> Self { let metrics = match prometheus_registry.as_ref().map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), @@ -860,7 +848,6 @@ where voter_set_state: persistent_data.set_state, metrics: metrics.as_ref().map(|m| m.environment.clone()), justification_sender: Some(justification_sender), - logger: logger.clone(), _phantom: PhantomData, }); @@ -872,7 +859,6 @@ where env, voter_commands_rx, network, - logger, metrics, }; work.rebuild_voter(); @@ -888,7 +874,7 @@ where let authority_id = local_authority_id(&self.env.voters, self.env.config.keystore.as_ref()) .unwrap_or_default(); - telemetry!(self.logger; CONSENSUS_DEBUG; "afg.starting_new_voter"; + telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; "name" => ?self.env.config.name(), "set_id" => ?self.env.set_id, "authority_id" => authority_id.to_string(), @@ -907,7 +893,7 @@ where "authorities is always at least an empty vector; elements are always of type string", ); - telemetry!(self.logger; CONSENSUS_INFO; "afg.authority_set"; + telemetry!(CONSENSUS_INFO; "afg.authority_set"; "number" => ?chain_info.finalized_number, "hash" => ?chain_info.finalized_hash, "authority_id" => authority_id.to_string(), @@ -967,7 +953,7 @@ where let voters: Vec = new.authorities.iter().map(move |(a, _)| { format!("{}", a) }).collect(); - telemetry!(self.logger; CONSENSUS_INFO; "afg.voter_command_change_authorities"; + telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; "number" => ?new.canon_number, "hash" => ?new.canon_hash, "voters" => ?voters, @@ -1008,7 +994,6 @@ where voting_rule: self.env.voting_rule.clone(), metrics: self.env.metrics.clone(), justification_sender: self.env.justification_sender.clone(), - logger: self.logger.clone(), _phantom: PhantomData, }); diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs index df4dfe00c6b8a..a7c9a655467c7 100644 --- a/client/finality-grandpa/src/light_import.rs +++ b/client/finality-grandpa/src/light_import.rs @@ -27,7 +27,6 @@ use sp_consensus::{ BlockCheckParams, Error as ConsensusError, }; use sc_network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; -use sc_telemetry::slog::Logger; use sp_runtime::Justification; use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor}; use sp_finality_grandpa::{self, AuthorityList}; @@ -53,7 +52,6 @@ pub fn light_block_import( backend: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, authority_set_provider: Arc>, - logger: Option, ) -> Result, ClientError> where BE: Backend, @@ -70,7 +68,6 @@ pub fn light_block_import( backend, authority_set_provider, data: Arc::new(RwLock::new(import_data)), - logger, }) } @@ -84,7 +81,6 @@ pub struct GrandpaLightBlockImport { backend: Arc, authority_set_provider: Arc>, data: Arc>>, - logger: Option, } impl Clone for GrandpaLightBlockImport { @@ -94,7 +90,6 @@ impl Clone for GrandpaLightBlockImport FinalityProofImport number, finality_proof, verifier, - self.logger.as_ref(), ) } } @@ -309,7 +303,6 @@ fn do_import_finality_proof( _number: NumberFor, finality_proof: Vec, verifier: &mut dyn Verifier, - logger: Option<&Logger>, ) -> Result<(Block::Hash, NumberFor), ConsensusError> where C: HeaderBackend @@ -330,7 +323,6 @@ fn do_import_finality_proof( authorities, authority_set_provider, finality_proof, - logger, ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; // try to import all new headers @@ -842,7 +834,7 @@ pub mod tests { let initial_set = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; let updated_set = vec![(AuthorityId::from_slice(&[2; 32]), 2)]; let babe_set_signal = vec![AuthorityId::from_slice(&[42; 32])].encode(); - + // import block #1 without justification let mut cache = HashMap::new(); cache.insert(well_known_cache_keys::AUTHORITIES, babe_set_signal); diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index 3806fd268e68a..fd00b35c40a73 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -29,7 +29,6 @@ use log::{debug, info, warn}; use sp_keystore::SyncCryptoStorePtr; use sp_consensus::SelectChain; use sc_client_api::backend::Backend; -use sc_telemetry::slog::Logger; use sp_utils::mpsc::TracingUnboundedReceiver; use sp_runtime::traits::{NumberFor, Block as BlockT}; use sp_blockchain::HeaderMetadata; @@ -75,7 +74,6 @@ fn grandpa_observer( last_finalized_number: NumberFor, commits: S, note_round: F, - logger: Option, ) -> impl Future>>> where NumberFor: BlockNumberOps, @@ -132,7 +130,6 @@ where (round, commit).into(), false, justification_sender.as_ref(), - logger.clone(), ) { Ok(_) => {}, Err(e) => return future::err(e), @@ -170,7 +167,6 @@ pub fn run_grandpa_observer( config: Config, link: LinkHalf, network: N, - logger: Option, ) -> sp_blockchain::Result + Unpin + Send + 'static> where BE: Backend + Unpin + 'static, @@ -193,7 +189,6 @@ where config.clone(), persistent_data.set_state.clone(), None, - logger.clone(), ); let observer_work = ObserverWork::new( @@ -203,7 +198,6 @@ where config.keystore, voter_commands_rx, Some(justification_sender), - logger, ); let observer_work = observer_work @@ -225,7 +219,6 @@ struct ObserverWork> { keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, - logger: Option, _phantom: PhantomData, } @@ -244,7 +237,6 @@ where keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, justification_sender: Option>, - logger: Option, ) -> Self { let mut work = ObserverWork { @@ -257,7 +249,6 @@ where keystore: keystore.clone(), voter_commands_rx, justification_sender, - logger, _phantom: PhantomData, }; work.rebuild_observer(); @@ -308,7 +299,6 @@ where last_finalized_number, global_in, note_round, - self.logger.clone(), ); self.observer = Box::pin(observer); diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index e54187962bf17..cc4319c628db8 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -259,7 +259,7 @@ pub fn new_full_parts( TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - let (telemetry, logger) = init_telemetry(&config); + let telemetry = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { @@ -310,7 +310,6 @@ pub fn new_full_parts( offchain_indexing_api: config.offchain_worker.indexing_enabled, wasm_runtime_overrides: config.wasm_runtime_overrides.clone(), }, - logger, )? }; @@ -330,7 +329,7 @@ pub fn new_light_parts( TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - let (telemetry, logger) = init_telemetry(&config); + let telemetry = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); @@ -369,7 +368,6 @@ pub fn new_light_parts( executor, Box::new(task_manager.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), - logger, )?); Ok((client, backend, keystore_container, task_manager, on_demand, telemetry)) @@ -386,7 +384,6 @@ pub fn new_client( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, - logger: Option, ) -> Result<( crate::client::Client< Backend, @@ -416,7 +413,6 @@ pub fn new_client( execution_extensions, prometheus_registry, config, - logger, )?, backend, )) @@ -544,7 +540,6 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - let logger = telemetry.as_ref().map(|x| x.logger.clone()); if let Some(telemetry) = telemetry.clone() { spawn_telemetry_worker( telemetry, @@ -558,7 +553,6 @@ pub fn spawn_tasks( info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( - logger; SUBSTRATE_INFO; "node.start"; "height" => chain_info.best_number.saturated_into::(), @@ -575,7 +569,7 @@ pub fn spawn_tasks( spawn_handle.spawn( "on-transaction-imported", - transaction_notifications(transaction_pool.clone(), network.clone(), logger.clone()), + transaction_notifications(transaction_pool.clone(), network.clone()), ); // Prometheus metrics. @@ -583,7 +577,7 @@ pub fn spawn_tasks( config.prometheus_config.clone() { // Set static metrics. - let metrics = MetricsService::with_prometheus(®istry, &config, logger)?; + let metrics = MetricsService::with_prometheus(®istry, &config)?; spawn_handle.spawn( "prometheus-endpoint", prometheus_endpoint::init_prometheus(port, registry).map(drop) @@ -591,7 +585,7 @@ pub fn spawn_tasks( metrics } else { - MetricsService::new(logger) + MetricsService::new() }; // Periodically updated metrics and telemetry updates. @@ -638,7 +632,6 @@ pub fn spawn_tasks( async fn transaction_notifications( transaction_pool: Arc, network: Arc::Hash>>, - logger: Option, ) where TBl: BlockT, @@ -649,7 +642,7 @@ async fn transaction_notifications( .for_each(move |hash| { network.propagate_transaction(hash); let status = transaction_pool.status(); - telemetry!(logger; SUBSTRATE_INFO; "txpool.import"; + telemetry!(SUBSTRATE_INFO; "txpool.import"; "ready" => status.ready, "future" => status.future ); @@ -658,19 +651,18 @@ async fn transaction_notifications( .await; } -fn init_telemetry(config: &Configuration) -> (Option, Option) { +fn init_telemetry(config: &Configuration) -> Option { let endpoints = match config.telemetry_endpoints.clone() { Some(endpoints) if !endpoints.is_empty() => endpoints, // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) - _ => return (None, None), + _ => return None, }; let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { endpoints, wasm_external_transport: config.telemetry_external_transport.clone(), }); - let logger = telemetry.logger.clone(); - (Some(telemetry), Some(logger)) + Some(telemetry) } fn spawn_telemetry_worker>( @@ -695,7 +687,6 @@ fn spawn_telemetry_worker>( let startup_time = SystemTime::UNIX_EPOCH.elapsed() .map(|dur| dur.as_millis()) .unwrap_or(0); - let logger = Some(telemetry.logger.clone()); spawn_handle.spawn( "telemetry-worker", @@ -704,7 +695,7 @@ fn spawn_telemetry_worker>( // Safe-guard in case we add more events in the future. let sc_telemetry::TelemetryEvent::Connected = event; - telemetry!(logger; SUBSTRATE_INFO; "system.connected"; + telemetry!(SUBSTRATE_INFO; "system.connected"; "name" => name.clone(), "implementation" => impl_name.clone(), "version" => impl_version.clone(), diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 6600cab84d810..d423fdee39b6c 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -35,7 +35,7 @@ use sp_core::{ }; #[cfg(feature="test-helpers")] use sp_keystore::SyncCryptoStorePtr; -use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_runtime::{ Justification, BuildStorage, generic::{BlockId, SignedBlock, DigestItem}, @@ -115,7 +115,6 @@ pub struct Client where Block: BlockT { block_rules: BlockRules, execution_extensions: ExecutionExtensions, config: ClientConfig, - logger: Option, _phantom: PhantomData, } @@ -155,7 +154,6 @@ pub fn new_in_mem( prometheus_registry: Option, spawn_handle: Box, config: ClientConfig, - logger: Option, ) -> sp_blockchain::Result, LocalCallExecutor, E>, @@ -174,7 +172,6 @@ pub fn new_in_mem( spawn_handle, prometheus_registry, config, - logger, ) } @@ -200,7 +197,6 @@ pub fn new_with_backend( spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, - logger: Option, ) -> sp_blockchain::Result, Block, RA>> where E: CodeExecutor + RuntimeInfo, @@ -219,7 +215,6 @@ pub fn new_with_backend( extensions, prometheus_registry, config, - logger, ) } @@ -300,7 +295,6 @@ impl Client where execution_extensions: ExecutionExtensions, prometheus_registry: Option, config: ClientConfig, - logger: Option, ) -> sp_blockchain::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { let genesis_storage = build_genesis_storage.build_storage()?; @@ -331,7 +325,6 @@ impl Client where block_rules: BlockRules::new(fork_blocks, bad_blocks), execution_extensions, config, - logger, _phantom: Default::default(), }) } @@ -674,7 +667,7 @@ impl Client where if origin != BlockOrigin::NetworkInitialSync || rand::thread_rng().gen_bool(0.1) { - telemetry!(self.logger; SUBSTRATE_INFO; "block.import"; + telemetry!(SUBSTRATE_INFO; "block.import"; "height" => height, "best" => ?hash, "origin" => ?origin @@ -994,7 +987,7 @@ impl Client where indicated in the tree route; qed" ); - telemetry!(self.logger; SUBSTRATE_INFO; "notify.finalized"; + telemetry!(SUBSTRATE_INFO; "notify.finalized"; "height" => format!("{}", header.number()), "best" => ?last, ); diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs index 4b2a497195cdc..6d4f9aa1c9d1b 100644 --- a/client/service/src/client/light.rs +++ b/client/service/src/client/light.rs @@ -30,7 +30,7 @@ use prometheus_endpoint::Registry; use super::{call_executor::LocalCallExecutor, client::{Client, ClientConfig}}; use sc_client_api::light::Storage as BlockchainStorage; use sc_light::{Backend, GenesisCallExecutor}; -use sc_telemetry::slog::Logger; + /// Create an instance of light client. pub fn new_light( @@ -39,7 +39,6 @@ pub fn new_light( code_executor: E, spawn_handle: Box, prometheus_registry: Option, - logger: Option, ) -> ClientResult< Client< Backend>, @@ -72,6 +71,5 @@ pub fn new_light( Default::default(), prometheus_registry, ClientConfig::default(), - logger, ) } diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index b3af19609b2b0..b8699fe455163 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -21,7 +21,7 @@ use std::{convert::TryFrom, time::SystemTime}; use crate::{NetworkStatus, NetworkState, NetworkStatusSinks, config::Configuration}; use futures_timer::Delay; use prometheus_endpoint::{register, Gauge, U64, Registry, PrometheusError, Opts, GaugeVec}; -use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_api::ProvideRuntimeApi; use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto}; use sp_transaction_pool::{PoolStatus, MaintainedTransactionPool}; @@ -112,19 +112,17 @@ pub struct MetricsService { last_update: Instant, last_total_bytes_inbound: u64, last_total_bytes_outbound: u64, - logger: Option, } impl MetricsService { /// Creates a `MetricsService` that only sends information /// to the telemetry. - pub fn new(logger: Option) -> Self { + pub fn new() -> Self { MetricsService { metrics: None, last_total_bytes_inbound: 0, last_total_bytes_outbound: 0, last_update: Instant::now(), - logger, } } @@ -133,7 +131,6 @@ impl MetricsService { pub fn with_prometheus( registry: &Registry, config: &Configuration, - logger: Option, ) -> Result { let role_bits = match config.role { Role::Full => 1u64, @@ -153,7 +150,6 @@ impl MetricsService { last_total_bytes_inbound: 0, last_total_bytes_outbound: 0, last_update: Instant::now(), - logger, }) } @@ -250,7 +246,6 @@ impl MetricsService { // Update/send metrics that are always available. telemetry!( - self.logger; SUBSTRATE_INFO; "system.interval"; "height" => best_number, @@ -313,7 +308,6 @@ impl MetricsService { }; telemetry!( - self.logger; SUBSTRATE_INFO; "system.interval"; "peers" => num_peers, @@ -335,7 +329,6 @@ impl MetricsService { // Send network state information, if any. if let Some(net_state) = net_state { telemetry!( - self.logger; SUBSTRATE_INFO; "system.network_state"; // TODO: not sure why I need `?` all of a sudden? diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f4e2f6b509694..e0f5186911084 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -346,8 +346,7 @@ impl slog::Drain for TelemetryDrain { /// parameter is added to the record as a key-value pair. #[macro_export(local_inner_macros)] macro_rules! telemetry { - ( $l:expr; $a:expr; $b:expr; $( $t:tt )* ) => {{ - // TODO: drop $l + ( $a:expr; $b:expr; $( $t:tt )* ) => {{ /* // NOTE: didn't work let record_static = $crate::slog::record_static!($crate::slog::Level::Info, $a); diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 5c598c6bf2c87..66e58d817c1e7 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -219,13 +219,11 @@ impl ProfilingLayer { /// either with a level: "pallet=trace,frame=debug" /// or without: "pallet,frame" in which case the level defaults to `trace`. /// wasm_tracing indicates whether to enable wasm traces - pub fn new(receiver: TracingReceiver, targets: &str, logger: Option) -> Self { + pub fn new(receiver: TracingReceiver, targets: &str) -> Self { match receiver { TracingReceiver::Log => Self::new_with_handler(Box::new(LogTraceHandler), targets), TracingReceiver::Telemetry => Self::new_with_handler( - Box::new(TelemetryTraceHandler { - logger, - }), + Box::new(TelemetryTraceHandler), targets, ), } @@ -407,13 +405,11 @@ impl TraceHandler for LogTraceHandler { /// TraceHandler for sending span data to telemetry, /// Please see telemetry documentation for details on how to specify endpoints and /// set the required telemetry level to activate tracing messages -pub struct TelemetryTraceHandler { - logger: Option, -} +pub struct TelemetryTraceHandler; impl TraceHandler for TelemetryTraceHandler { fn handle_span(&self, span_datum: SpanDatum) { - telemetry!(self.logger; SUBSTRATE_INFO; "tracing.profiling"; + telemetry!(SUBSTRATE_INFO; "tracing.profiling"; "name" => span_datum.name, "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), @@ -424,7 +420,7 @@ impl TraceHandler for TelemetryTraceHandler { } fn handle_event(&self, event: TraceEvent) { - telemetry!(self.logger; SUBSTRATE_INFO; "tracing.event"; + telemetry!(SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, "parent_id" => : event.parent_id.as_ref().map(|i| i.into_u64()), diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 6ccc87a919fd9..bde2156e0cc88 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -220,7 +220,6 @@ impl TestClientBuilder Date: Thu, 29 Oct 2020 11:48:12 +0100 Subject: [PATCH 017/222] WIP --- client/cli/src/config.rs | 12 ++++++------ client/cli/src/lib.rs | 7 ++++--- client/cli/src/runner.rs | 12 ++++++++++-- client/service/src/config.rs | 2 ++ client/service/test/src/lib.rs | 1 + utils/browser/src/lib.rs | 2 ++ 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index ab7a335c1ce64..4fd03c10ac438 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -455,6 +455,7 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, + telemetry_senders: sc_telemetry::Senders, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; @@ -525,6 +526,7 @@ pub trait CliConfiguration: Sized { role, base_path: Some(base_path), informant_output_format: Default::default(), + telemetry_senders, }) } @@ -545,28 +547,26 @@ pub trait CliConfiguration: Sized { /// 1. Sets the panic handler /// 2. Initializes the logger /// 3. Raises the FD limit - fn init(&self) -> Result<()> { + fn init(&self) -> Result { let logger_pattern = self.log_filters()?; let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; sp_panic_handler::set(&C::support_url(), &C::impl_version()); - if let Err(e) = init_logger(&logger_pattern, tracing_receiver, tracing_targets) { - log::warn!("💬 Problem initializing global logging framework: {:}", e) - } + let senders = init_logger(&logger_pattern, tracing_receiver, tracing_targets)?; if let Some(new_limit) = fdlimit::raise_fd_limit() { if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT { warn!( "Low open file descriptor limit configured for the process. \ - Current value: {:?}, recommended value: {:?}.", + Current value: {:?}, recommended value: {:?}.", new_limit, RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT, ); } } - Ok(()) + Ok(senders) } } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 2ecb5d41ad68c..0881676d971c1 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -221,15 +221,16 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, + telemetry_senders: sc_telemetry::Senders, ) -> error::Result { - command.create_configuration(self, task_executor) + command.create_configuration(self, task_executor, telemetry_senders) } /// Create a runner for the command provided in argument. This will create a Configuration and /// a tokio runtime fn create_runner(&self, command: &T) -> error::Result> { - command.init::()?; - Runner::new(self, command) + let telemetry_senders = command.init::()?; + Runner::new(self, command, telemetry_senders) } /// Native runtime version. diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index e6d35282ada2b..9a8c2dca7eae3 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -117,7 +117,11 @@ pub struct Runner { impl Runner { /// Create a new runtime with the command provided in argument - pub fn new(cli: &C, command: &T) -> Result> { + pub fn new( + cli: &C, + command: &T, + telemetry_senders: sc_telemetry::Senders, + ) -> Result> { let tokio_runtime = build_runtime()?; let runtime_handle = tokio_runtime.handle().clone(); @@ -131,7 +135,11 @@ impl Runner { }; Ok(Runner { - config: command.create_configuration(cli, task_executor.into())?, + config: command.create_configuration( + cli, + task_executor.into(), + telemetry_senders, + )?, tokio_runtime, phantom: PhantomData, }) diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 0caf05b2485db..9dce37d17a013 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -87,6 +87,8 @@ pub struct Configuration { /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, + /// Telemetry senders + pub telemetry_senders: sc_telemetry::Senders, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 8a9f0ace171d8..fad9cc695d4b0 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,6 +263,7 @@ fn node_config Date: Thu, 29 Oct 2020 11:57:38 +0100 Subject: [PATCH 018/222] CLEANUP --- client/service/src/builder.rs | 2 +- client/telemetry/src/async_record.rs | 155 --------------------------- client/telemetry/src/layer.rs | 23 ++-- client/telemetry/src/lib.rs | 39 +------ client/telemetry/src/worker.rs | 3 +- client/tracing/src/lib.rs | 1 - 6 files changed, 18 insertions(+), 205 deletions(-) delete mode 100644 client/telemetry/src/async_record.rs diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index cc4319c628db8..157db624a61e7 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -51,7 +51,7 @@ use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{slog::Logger, telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; diff --git a/client/telemetry/src/async_record.rs b/client/telemetry/src/async_record.rs deleted file mode 100644 index 34b7c1435afa1..0000000000000 --- a/client/telemetry/src/async_record.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! # Internal types to ssync drain slog -//! FIXME: REMOVE THIS ONCE THE PR WAS MERGE -//! https://github.com/slog-rs/async/pull/14 - -use slog::{Record, RecordStatic, Level, SingleKV, KV, BorrowedKV}; -use slog::{Serializer, OwnedKVList, Key}; - -use std::fmt; -use take_mut::take; - -struct ToSendSerializer { - kv: Box, -} - -impl ToSendSerializer { - fn new() -> Self { - ToSendSerializer { kv: Box::new(()) } - } - - fn finish(self) -> Box { - self.kv - } -} - -impl Serializer for ToSendSerializer { - fn emit_bool(&mut self, key: Key, val: bool) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_unit(&mut self, key: Key) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, ())))); - Ok(()) - } - fn emit_none(&mut self, key: Key) -> slog::Result { - let val: Option<()> = None; - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_char(&mut self, key: Key, val: char) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_u8(&mut self, key: Key, val: u8) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_i8(&mut self, key: Key, val: i8) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_u16(&mut self, key: Key, val: u16) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_i16(&mut self, key: Key, val: i16) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_u32(&mut self, key: Key, val: u32) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_i32(&mut self, key: Key, val: i32) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_f32(&mut self, key: Key, val: f32) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_u64(&mut self, key: Key, val: u64) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_i64(&mut self, key: Key, val: i64) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_f64(&mut self, key: Key, val: f64) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_usize(&mut self, key: Key, val: usize) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_isize(&mut self, key: Key, val: isize) -> slog::Result { - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_str(&mut self, key: Key, val: &str) -> slog::Result { - let val = val.to_owned(); - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - fn emit_arguments( - &mut self, - key: Key, - val: &fmt::Arguments, - ) -> slog::Result { - let val = fmt::format(*val); - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } - - fn emit_serde(&mut self, key: Key, value: &dyn slog::SerdeValue) -> slog::Result { - let val = value.to_sendable(); - take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); - Ok(()) - } -} - -pub(crate) struct AsyncRecord { - msg: String, - level: Level, - location: Box, - tag: String, - logger_values: OwnedKVList, - kv: Box, -} - -impl AsyncRecord { - /// Serializes a `Record` and an `OwnedKVList`. - pub fn from(record: &Record, logger_values: &OwnedKVList) -> Self { - let mut ser = ToSendSerializer::new(); - record - .kv() - .serialize(record, &mut ser) - .expect("`ToSendSerializer` can't fail"); - - AsyncRecord { - msg: fmt::format(*record.msg()), - level: record.level(), - location: Box::new(*record.location()), - tag: String::from(record.tag()), - logger_values: logger_values.clone(), - kv: ser.finish(), - } - } - - /// Deconstruct this `AsyncRecord` into a record and `OwnedKVList`. - pub fn as_record_values(&self, mut f: impl FnMut(&Record, &OwnedKVList)) { - let rs = RecordStatic { - location: &*self.location, - level: self.level, - tag: &self.tag, - }; - - f(&Record::new( - &rs, - &format_args!("{}", self.msg), - BorrowedKV(&self.kv), - ), &self.logger_values) - } -} diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 140c373953714..9aab86802d47c 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,9 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use futures::{channel::mpsc, prelude::*}; -use std::sync::{Arc}; -use tracing::{Subscriber, Event, Id, span::Attributes}; +use futures::channel::mpsc; +use std::sync::Arc; +use tracing::{Subscriber, Event}; use tracing_subscriber::{registry::LookupSpan, Layer, layer::Context}; use parking_lot::Mutex; use std::collections::HashMap; @@ -49,14 +49,21 @@ impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> match attrs { (Some(message_verbosity), Some(json)) => { let id = span.id().into_u64(); - self.0.0.lock().get_mut(&id) - .expect("a telemetry span has not been registered to the TelemetryLayer") - .send(( + if let Err(err) = self.0.0.lock().get_mut(&id) + .expect("telemetry span has not been registered to the TelemetryLayer") + .try_send(( message_verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), json, - )); + )) + { + log::warn!( + target: "telemetry", + "Ignored telemetry message because of error on channel: {:?}", + err, + ); + } }, _ => panic!("missing fields in telemetry log"), } @@ -68,7 +75,7 @@ impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> struct TelemetryAttrsVisitor<'a>(&'a mut (Option, Option)); impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { - fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) { + fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) { // noop } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index e0f5186911084..abc56c07fb8c5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -67,7 +67,6 @@ use parking_lot::Mutex; use serde::{Serialize, Deserialize, Deserializer}; use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::Duration}; use wasm_timer::Instant; -use slog::Logger; pub use libp2p::wasm_ext::ExtTransport; pub use slog; @@ -76,7 +75,6 @@ pub use tracing; pub use serde_json; pub use chrono; -mod async_record; mod layer; mod worker; @@ -203,12 +201,6 @@ struct TelemetryInner { receiver: mpsc::Receiver<(u8, String)>, } -/// Implements `slog::Drain`. -struct TelemetryDrain { - /// Sends log entries. - sender: std::panic::AssertUnwindSafe>, -} - /// Initializes the telemetry. See the crate root documentation for more information. /// /// Please be careful to not call this function twice in the same program. The `slog` crate @@ -218,12 +210,6 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { let (endpoints, wasm_external_transport) = (config.endpoints.0, config.wasm_external_transport); let (sender, receiver) = mpsc::channel(16); - /* - let logger = { - let logger = TelemetryDrain { sender: std::panic::AssertUnwindSafe(sender) }; - slog::Logger::root(slog::Drain::fuse(logger), slog::o!()) - }; - */ let worker = match worker::TelemetryWorker::new(endpoints, wasm_external_transport) { Ok(w) => Some(w), @@ -234,7 +220,6 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { }; let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let id = span.id(); Telemetry { inner: Arc::new(Mutex::new(TelemetryInner { @@ -299,7 +284,7 @@ impl Stream for Telemetry { ))) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) { if let Some(worker) = inner.worker.as_mut() { - worker.log(message_verbosity, json.as_str()); + let _ = worker.log(message_verbosity, json.as_str()); } } else { break; @@ -318,28 +303,6 @@ impl Stream for Telemetry { } } -impl slog::Drain for TelemetryDrain { - type Ok = (); - type Err = (); - - fn log(&self, record: &slog::Record, values: &slog::OwnedKVList) -> Result { - let before = Instant::now(); - - let serialized = async_record::AsyncRecord::from(record, values); - // Note: interestingly, `try_send` requires a `&mut` because it modifies some internal value, while `clone()` - // is lock-free. - if let Err(err) = self.sender.clone().try_send(serialized) { - warn!(target: "telemetry", "Ignored telemetry message because of error on channel: {:?}", err); - } - - if before.elapsed() > Duration::from_millis(50) { - warn!(target: "telemetry", "Writing a telemetry log took more than 50ms"); - } - - Ok(()) - } -} - /// TODO doc /// Translates to `slog_scope::info`, but contains an additional verbosity /// parameter which the log record is tagged with. Additionally the verbosity diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index f67ed525f209c..5c3deef4677f7 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -30,8 +30,7 @@ use futures::{prelude::*, ready}; use libp2p::{core::transport::OptionalTransport, Multiaddr, Transport, wasm_ext}; -use log::{trace, warn, error}; -use slog::Drain; +use log::{trace, error}; use std::{io, pin::Pin, task::Context, task::Poll, time}; mod node; diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 66e58d817c1e7..b961c88d69f1a 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -40,7 +40,6 @@ use tracing::{ subscriber::Subscriber, }; use tracing_subscriber::{CurrentSpan, layer::{Layer, Context}}; -use slog::Logger; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; From c7c634f19d02c87434b84a67432f76003a71672b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 12:48:04 +0100 Subject: [PATCH 019/222] Attempt to enter/exit the span when the struct is created/dropped --- client/telemetry/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index abc56c07fb8c5..a64d941120f72 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -181,10 +181,12 @@ impl Telemetry { self.sender.clone(), ) } +} - /// TODO - pub fn enter(&self) -> tracing::span::Entered { - self.span.enter() +impl Drop for Telemetry { + fn drop(&mut self) { + let span_id = self.span.id().expect("the span is enabled; qed"); + tracing::dispatcher::get_default(move |dispatch| dispatch.exit(&span_id)); } } @@ -220,6 +222,8 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { }; let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let span_id = span.id().expect("the span is enabled; qed"); + tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&span_id)); Telemetry { inner: Arc::new(Mutex::new(TelemetryInner { From aa2f4f394529d4a9b68e416f4255ad7e364017e1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 12:50:32 +0100 Subject: [PATCH 020/222] WIP --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index a64d941120f72..3783106abbf95 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -340,7 +340,7 @@ macro_rules! telemetry { json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); - $crate::tracing::info!(target: "telemetry-logger", + $crate::tracing::info!(target: TELEMETRY_LOG_SPAN, message_verbosity, //json = s.as_str() json = $crate::serde_json::to_string(&json) From 4802d7002a1d7d0146aa576e48778b40b864d2d9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 13:44:29 +0100 Subject: [PATCH 021/222] WIP --- client/cli/src/logging.rs | 4 +++ client/telemetry/src/layer.rs | 60 ++++++++++++++++++++--------------- client/telemetry/src/lib.rs | 19 +++++++---- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/client/cli/src/logging.rs b/client/cli/src/logging.rs index e1fc90505b45f..cdb7777180a2f 100644 --- a/client/cli/src/logging.rs +++ b/client/cli/src/logging.rs @@ -56,6 +56,10 @@ where writer: &mut dyn fmt::Write, event: &Event, ) -> fmt::Result { + if event.metadata().target() == sc_telemetry::TELEMETRY_LOG_SPAN { + return Ok(()); + } + let normalized_meta = event.normalized_metadata(); let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); time::write(&self.timer, writer, self.ansi)?; diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 9aab86802d47c..75e755c42590d 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -17,12 +17,12 @@ // along with this program. If not, see . use futures::channel::mpsc; -use std::sync::Arc; -use tracing::{Subscriber, Event}; -use tracing_subscriber::{registry::LookupSpan, Layer, layer::Context}; use parking_lot::Mutex; use std::collections::HashMap; use std::convert::TryInto; +use std::sync::Arc; +use tracing::{Event, Subscriber}; +use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; @@ -38,34 +38,40 @@ impl TelemetryLayer { } } -impl Layer for TelemetryLayer where S: Subscriber + for<'a> LookupSpan<'a> { +impl Layer for TelemetryLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ fn on_event(&self, event: &Event<'_>, ctx: Context) { + if event.metadata().target() != TELEMETRY_LOG_SPAN { + return; + } + for span in ctx.scope() { if span.name() == TELEMETRY_LOG_SPAN { - let mut attrs = (None, None); - let mut vis = TelemetryAttrsVisitor(&mut attrs); - event.record(&mut vis); - - match attrs { - (Some(message_verbosity), Some(json)) => { - let id = span.id().into_u64(); - if let Err(err) = self.0.0.lock().get_mut(&id) - .expect("telemetry span has not been registered to the TelemetryLayer") - .try_send(( + let id = span.id().into_u64(); + if let Some(sender) = (self.0).0.lock().get_mut(&id) { + let mut attrs = (None, None); + let mut vis = TelemetryAttrsVisitor(&mut attrs); + event.record(&mut vis); + + match attrs { + (Some(message_verbosity), Some(json)) => { + if let Err(err) = sender.try_send(( message_verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), json, - )) - { - log::warn!( - target: "telemetry", - "Ignored telemetry message because of error on channel: {:?}", - err, - ); + )) { + log::warn!( + target: "telemetry", + "Ignored telemetry message because of error on channel: {:?}", + err, + ); + } } - }, - _ => panic!("missing fields in telemetry log"), + _ => panic!("missing fields in telemetry log: {:?}", event), + } } } } @@ -93,10 +99,14 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { } #[derive(Default, Debug, Clone)] -pub struct Senders(Arc>>>>); +pub struct Senders( + Arc>>>>, +); impl Senders { pub fn insert(&mut self, id: u64, sender: mpsc::Sender<(u8, String)>) { - self.0.lock().insert(id, std::panic::AssertUnwindSafe(sender)); + self.0 + .lock() + .insert(id, std::panic::AssertUnwindSafe(sender)); } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 3783106abbf95..5e5808318035d 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -60,20 +60,25 @@ //! ``` //! -use futures::{prelude::*, channel::mpsc}; -use libp2p::{Multiaddr, wasm_ext}; +use futures::{channel::mpsc, prelude::*}; +use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; use parking_lot::Mutex; -use serde::{Serialize, Deserialize, Deserializer}; -use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::Duration}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::{ + pin::Pin, + sync::Arc, + task::{Context, Poll}, + time::Duration, +}; use wasm_timer::Instant; +pub use chrono; pub use libp2p::wasm_ext::ExtTransport; +pub use serde_json; pub use slog; pub use slog_json; pub use tracing; -pub use serde_json; -pub use chrono; mod layer; mod worker; @@ -340,7 +345,7 @@ macro_rules! telemetry { json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); - $crate::tracing::info!(target: TELEMETRY_LOG_SPAN, + $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, message_verbosity, //json = s.as_str() json = $crate::serde_json::to_string(&json) From 911ae793c4fdbb988819bf45af5a60293ca51f10 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 14:58:23 +0100 Subject: [PATCH 022/222] WIP --- client/service/src/builder.rs | 1 + client/telemetry/src/layer.rs | 4 +++- client/telemetry/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 157db624a61e7..e5e39c79dcd8d 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -661,6 +661,7 @@ fn init_telemetry(config: &Configuration) -> Option { endpoints, wasm_external_transport: config.telemetry_external_transport.clone(), }); + telemetry.push_sender(&config.telemetry_senders); Some(telemetry) } diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 75e755c42590d..fac0471a63666 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -72,6 +72,8 @@ where } _ => panic!("missing fields in telemetry log: {:?}", event), } + } else { + log::trace!(target: "telemetry", "Telemetry not set"); } } } @@ -104,7 +106,7 @@ pub struct Senders( ); impl Senders { - pub fn insert(&mut self, id: u64, sender: mpsc::Sender<(u8, String)>) { + pub fn insert(&self, id: u64, sender: mpsc::Sender<(u8, String)>) { self.0 .lock() .insert(id, std::panic::AssertUnwindSafe(sender)); diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5e5808318035d..4c4a06dcc0956 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -180,7 +180,7 @@ pub struct Telemetry { impl Telemetry { /// TODO - pub fn push_sender(&self, mut senders: Senders) { + pub fn push_sender(&self, senders: &Senders) { senders.insert( self.span.id().expect("the span is enabled; qed").into_u64(), self.sender.clone(), From 59429ab4d0c6d4271cfb227ae9ff84a42fa4099a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 17:40:52 +0100 Subject: [PATCH 023/222] WIP --- client/telemetry/src/layer.rs | 48 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index fac0471a63666..81c0b0fed7f0e 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -47,34 +47,32 @@ where return; } - for span in ctx.scope() { - if span.name() == TELEMETRY_LOG_SPAN { - let id = span.id().into_u64(); - if let Some(sender) = (self.0).0.lock().get_mut(&id) { - let mut attrs = (None, None); - let mut vis = TelemetryAttrsVisitor(&mut attrs); - event.record(&mut vis); - - match attrs { - (Some(message_verbosity), Some(json)) => { - if let Err(err) = sender.try_send(( - message_verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )) { - log::warn!( - target: "telemetry", - "Ignored telemetry message because of error on channel: {:?}", - err, - ); - } + if let Some(span) = ctx.scope().find(|x| x.name() == TELEMETRY_LOG_SPAN) { + let id = span.id().into_u64(); + if let Some(sender) = (self.0).0.lock().get_mut(&id) { + let mut attrs = (None, None); + let mut vis = TelemetryAttrsVisitor(&mut attrs); + event.record(&mut vis); + + match attrs { + (Some(message_verbosity), Some(json)) => { + if let Err(err) = sender.try_send(( + message_verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )) { + log::warn!( + target: "telemetry", + "Ignored telemetry message because of error on channel: {:?}", + err, + ); } - _ => panic!("missing fields in telemetry log: {:?}", event), } - } else { - log::trace!(target: "telemetry", "Telemetry not set"); + _ => panic!("missing fields in telemetry log: {:?}", event), } + } else { + log::trace!(target: "telemetry", "Telemetry not set"); } } } From c7e824a5297617a962e5b50d15c6938f931eb4db Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 29 Oct 2020 19:36:58 +0100 Subject: [PATCH 024/222] Serialize instead of stringify --- client/telemetry/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 4c4a06dcc0956..8c2aac10dc67b 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -359,12 +359,14 @@ macro_rules! telemetry { macro_rules! format_fields_to_json { ( $k:literal => $v:expr $(,)? ) => {{ let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), $crate::serde_json::Value::from(std::format!("{}", $v))); + map.insert($k.into(), $crate::serde_json::to_value($v) + .expect("telemetry values must be serializable")); map }}; ( $k:literal => ? $v:expr $(,)? ) => {{ let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), $crate::serde_json::Value::from(std::format!("{:?}", $v))); + map.insert($k.into(), $crate::serde_json::to_value($v) + .expect("telemetry values must be serializable")); map }}; ( $k:literal => : $v:expr $(,)? ) => {{ From 28a79a0199cb56f337b8e91e38c1b59ff530686b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 10:10:30 +0100 Subject: [PATCH 025/222] WIP --- client/telemetry/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 8c2aac10dc67b..0c922d6310e58 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -365,8 +365,7 @@ macro_rules! format_fields_to_json { }}; ( $k:literal => ? $v:expr $(,)? ) => {{ let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), $crate::serde_json::to_value($v) - .expect("telemetry values must be serializable")); + map.insert($k.into(), std::format!("{:?}", $v).into()); map }}; ( $k:literal => : $v:expr $(,)? ) => {{ From 6ac4ea83ce58aa665b179ad62980aa368cc30650 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 10:19:52 +0100 Subject: [PATCH 026/222] WIP --- client/consensus/slots/src/lib.rs | 2 +- client/service/src/metrics.rs | 3 +-- client/telemetry/Cargo.toml | 2 +- client/telemetry/src/lib.rs | 14 -------------- client/tracing/src/lib.rs | 4 ++-- 5 files changed, 5 insertions(+), 20 deletions(-) diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index ad4e4924bc850..681d4a6273ed9 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -238,7 +238,7 @@ pub trait SimpleSlotWorker { telemetry!( CONSENSUS_DEBUG; "slots.skipping_proposal_slot"; - "authorities_len" => : authorities_len, + "authorities_len" => authorities_len, ); return Box::pin(future::ready(None)); diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index b8699fe455163..d3ad780b5be62 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -331,8 +331,7 @@ impl MetricsService { telemetry!( SUBSTRATE_INFO; "system.network_state"; - // TODO: not sure why I need `?` all of a sudden? - "state" => ? net_state, + "state" => net_state, ); } } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index be03bf64cc62a..ba1c5994a3c24 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -30,5 +30,5 @@ take_mut = "0.2.2" void = "1.0.2" tracing = "0.1.10" tracing-subscriber = "0.2.13" -serde_json = "1.0.41" +serde_json = { version = "1.0.41", features = ["arbitrary_precision"] } chrono = "0.4.13" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 0c922d6310e58..2d6be186d4d86 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -368,15 +368,6 @@ macro_rules! format_fields_to_json { map.insert($k.into(), std::format!("{:?}", $v).into()); map }}; - ( $k:literal => : $v:expr $(,)? ) => {{ - $v - .map(|x| format_fields_to_json!($k => x)) - .unwrap_or_else(|| { - let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), $crate::serde_json::Value::Null); - map - }) - }}; ( $k:literal => $v:expr, $($t:tt)* ) => {{ let mut map = format_fields_to_json!($($t)*); map.append(&mut format_fields_to_json!($k => $v)); @@ -387,11 +378,6 @@ macro_rules! format_fields_to_json { map.append(&mut format_fields_to_json!($k => ? $v)); map }}; - ( $k:literal => : $v:expr, $($t:tt)* ) => {{ - let mut map = format_fields_to_json!($($t)*); - map.append(&mut format_fields_to_json!($k => : $v)); - map - }}; } #[cfg(test)] diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index b961c88d69f1a..2b261d8d5f802 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -413,7 +413,7 @@ impl TraceHandler for TelemetryTraceHandler { "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), "id" => span_datum.id.into_u64(), - "parent_id" => : span_datum.parent_id.as_ref().map(|i| i.into_u64()), + "parent_id" => span_datum.parent_id.as_ref().map(|i| i.into_u64()), "values" => span_datum.values ); } @@ -422,7 +422,7 @@ impl TraceHandler for TelemetryTraceHandler { telemetry!(SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, - "parent_id" => : event.parent_id.as_ref().map(|i| i.into_u64()), + "parent_id" => event.parent_id.as_ref().map(|i| i.into_u64()), "values" => event.values ); } From 6d6da6d12a5ffb4e7e4a3d9cdb41640160d24179 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 10:35:02 +0100 Subject: [PATCH 027/222] CLEANUP --- client/telemetry/src/lib.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2d6be186d4d86..643b9bf5e8b23 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -357,25 +357,21 @@ macro_rules! telemetry { #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! format_fields_to_json { - ( $k:literal => $v:expr $(,)? ) => {{ + ( $k:literal => $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), $crate::serde_json::to_value($v) .expect("telemetry values must be serializable")); + $( + map.append(&mut format_fields_to_json!($($t)*)); + )* map }}; - ( $k:literal => ? $v:expr $(,)? ) => {{ + ( $k:literal => ? $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), std::format!("{:?}", $v).into()); - map - }}; - ( $k:literal => $v:expr, $($t:tt)* ) => {{ - let mut map = format_fields_to_json!($($t)*); - map.append(&mut format_fields_to_json!($k => $v)); - map - }}; - ( $k:literal => ? $v:expr, $($t:tt)* ) => {{ - let mut map = format_fields_to_json!($($t)*); - map.append(&mut format_fields_to_json!($k => ? $v)); + $( + map.append(&mut format_fields_to_json!($($t)*)); + )* map }}; } From e1bd5920ee8f5341e59cbf9376c7bb7fd496a41e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 10:42:05 +0100 Subject: [PATCH 028/222] CLEANUP --- Cargo.lock | 39 ----------------------------- client/network/Cargo.toml | 2 -- client/network/src/network_state.rs | 3 +-- client/service/Cargo.toml | 1 - client/telemetry/Cargo.toml | 2 -- client/telemetry/README.md | 3 ++- client/telemetry/src/lib.rs | 25 +----------------- client/telemetry/src/worker.rs | 1 + client/tracing/Cargo.toml | 1 - client/tracing/src/lib.rs | 21 ---------------- 10 files changed, 5 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0a3a3930fc77..db1b2f439c26f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7105,8 +7105,6 @@ dependencies = [ "sc-peerset", "serde", "serde_json", - "slog", - "slog_derive", "smallvec 0.6.13", "sp-arithmetic", "sp-blockchain", @@ -7359,7 +7357,6 @@ dependencies = [ "sc-transaction-pool", "serde", "serde_json", - "slog", "sp-api", "sp-application-crypto", "sp-block-builder", @@ -7471,8 +7468,6 @@ dependencies = [ "rand 0.7.3", "serde", "serde_json", - "slog", - "slog-json", "take_mut", "tracing", "tracing-subscriber", @@ -7491,7 +7486,6 @@ dependencies = [ "sc-telemetry", "serde", "serde_json", - "slog", "sp-tracing", "tracing", "tracing-core", @@ -7842,39 +7836,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -[[package]] -name = "slog" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" -dependencies = [ - "erased-serde", -] - -[[package]] -name = "slog-json" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -dependencies = [ - "chrono", - "erased-serde", - "serde", - "serde_json", - "slog", -] - -[[package]] -name = "slog_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a945ec7f7ce853e89ffa36be1e27dce9a43e82ff9093bf3461c30d5da74ed11b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "smallvec" version = "0.6.13" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index af0e2a2dc10fa..cefa96e3c118a 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -48,8 +48,6 @@ sc-client-api = { version = "2.0.0", path = "../api" } sc-peerset = { version = "2.0.0", path = "../peerset" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -slog = { version = "2.5.2", features = ["nested-values"] } -slog_derive = "0.2.0" smallvec = "0.6.10" sp-arithmetic = { version = "2.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } diff --git a/client/network/src/network_state.rs b/client/network/src/network_state.rs index db2b6429304bb..cafa76df861e0 100644 --- a/client/network/src/network_state.rs +++ b/client/network/src/network_state.rs @@ -22,7 +22,6 @@ use libp2p::{core::ConnectedPoint, Multiaddr}; use serde::{Deserialize, Serialize}; -use slog_derive::SerdeValue; use std::{collections::{HashMap, HashSet}, time::Duration}; /// Returns general information about the networking. @@ -30,7 +29,7 @@ use std::{collections::{HashMap, HashSet}, time::Duration}; /// Meant for general diagnostic purposes. /// /// **Warning**: This API is not stable. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerdeValue)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NetworkState { /// PeerId of the local node. diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 3569b2e7e5853..c270e4ac239f1 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -33,7 +33,6 @@ rand = "0.7.3" parking_lot = "0.10.0" lazy_static = "1.4.0" log = "0.4.8" -slog = { version = "2.5.2", features = ["nested-values"] } futures-timer = "3.0.1" wasm-timer = "0.2" exit-future = "0.2.0" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index ba1c5994a3c24..04f50f4f03f87 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -24,8 +24,6 @@ log = "0.4.8" pin-project = "0.4.6" rand = "0.7.2" serde = { version = "1.0.101", features = ["derive"] } -slog = { version = "2.5.2", features = ["nested-values"] } -slog-json = { version = "2.3.0", features = ["nested-values"] } take_mut = "0.2.2" void = "1.0.2" tracing = "0.1.10" diff --git a/client/telemetry/README.md b/client/telemetry/README.md index 8fdf9e500722d..ccc0b0463d880 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -1,5 +1,6 @@ Telemetry utilities. +TODO update doc Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. After that, calling `slog_scope::with_logger` will return a logger that sends information to the telemetry endpoints. The `telemetry!` macro is a short-cut for calling @@ -42,4 +43,4 @@ sc_telemetry::telemetry!(sc_telemetry::SUBSTRATE_INFO; "test"; ``` -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 643b9bf5e8b23..48ed19a2723f9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// TODO update doc //! Telemetry utilities. //! //! Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. @@ -76,8 +77,6 @@ use wasm_timer::Instant; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; pub use serde_json; -pub use slog; -pub use slog_json; pub use tracing; mod layer; @@ -319,27 +318,6 @@ impl Stream for Telemetry { #[macro_export(local_inner_macros)] macro_rules! telemetry { ( $a:expr; $b:expr; $( $t:tt )* ) => {{ - /* - // NOTE: didn't work - let record_static = $crate::slog::record_static!($crate::slog::Level::Info, $a); - let format_args = format_args!(""); - let record = $crate::slog::Record::new(&record_static, &format_args, $crate::slog::b!()); - - let mut v = vec![]; - let mut cur = std::io::Cursor::new(&mut v); - let json = $crate::slog_json::Json::default(&mut cur); - use $crate::slog::Drain; - let kv = $crate::slog::o!($($t)*); - let kvl = $crate::slog::OwnedKVList::from(kv); - json.log(&record, &kvl).unwrap(); - let s = String::from_utf8(v).unwrap(); - */ - /* - // NOTE: old code - if let Some(ref l) = $l { - $crate::slog::slog_info!(l, #$a, $b; $($t)* ) - } - */ let message_verbosity: u8 = $a; let mut json = format_fields_to_json!($($t)*); json.insert("level".into(), "INFO".into()); @@ -347,7 +325,6 @@ macro_rules! telemetry { json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, message_verbosity, - //json = s.as_str() json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed").as_str() ); diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 5c3deef4677f7..ad1c64bf9a97e 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -135,6 +135,7 @@ impl TelemetryWorker { Poll::Pending } + // TODO update doc /// Equivalent to `slog::Drain::log`, but takes `self` by `&mut` instead, which is more convenient. /// /// Keep in mind that you should call `TelemetryWorker::poll` in order to process the messages. diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 35db326c94929..03695cdc95a3a 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -19,7 +19,6 @@ parking_lot = "0.10.0" rustc-hash = "1.1.0" serde = "1.0.101" serde_json = "1.0.41" -slog = { version = "2.5.2", features = ["nested-values"] } tracing = "0.1.21" tracing-core = "0.1.17" tracing-subscriber = "0.2.13" diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 2b261d8d5f802..f15ebd5f4e546 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -192,27 +192,6 @@ impl fmt::Display for Values { } } -impl slog::SerdeValue for Values { - fn as_serde(&self) -> &dyn erased_serde::Serialize { - self - } - - fn to_sendable(&self) -> Box { - Box::new(self.clone()) - } -} - -impl slog::Value for Values { - fn serialize( - &self, - _record: &slog::Record, - key: slog::Key, - ser: &mut dyn slog::Serializer, - ) -> slog::Result { - ser.emit_serde(key, self) - } -} - impl ProfilingLayer { /// Takes a `TracingReceiver` and a comma separated list of targets, /// either with a level: "pallet=trace,frame=debug" From 389da318cf94d8a47e824c0766675cb6ad279ec4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 11:05:45 +0100 Subject: [PATCH 029/222] CLEANUP --- client/tracing/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index f15ebd5f4e546..7422bca713854 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -24,8 +24,6 @@ //! //! Currently we provide `Log` (default), `Telemetry` variants for `Receiver` -#![recursion_limit="256"] - use rustc_hash::FxHashMap; use std::fmt; use std::time::{Duration, Instant}; @@ -392,7 +390,7 @@ impl TraceHandler for TelemetryTraceHandler { "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), "id" => span_datum.id.into_u64(), - "parent_id" => span_datum.parent_id.as_ref().map(|i| i.into_u64()), + "parent_id" => span_datum.parent_id.map(|i| i.into_u64()), "values" => span_datum.values ); } @@ -401,7 +399,7 @@ impl TraceHandler for TelemetryTraceHandler { telemetry!(SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, - "parent_id" => event.parent_id.as_ref().map(|i| i.into_u64()), + "parent_id" => event.parent_id.map(|i| i.into_u64()), "values" => event.values ); } From 4602bcf39c87931d501c7680747630f152724322 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 16:48:29 +0100 Subject: [PATCH 030/222] Re-using telemetry nodes --- bin/node/cli/src/service.rs | 4 +- client/cli/src/config.rs | 10 +- client/cli/src/lib.rs | 16 +-- client/cli/src/runner.rs | 4 +- client/service/src/builder.rs | 26 ++-- client/service/src/config.rs | 4 +- client/telemetry/src/layer.rs | 12 +- client/telemetry/src/lib.rs | 168 +++++++++++++++-------- client/telemetry/src/worker.rs | 26 +++- client/telemetry/src/worker/node_pool.rs | 38 +++++ 10 files changed, 202 insertions(+), 106 deletions(-) create mode 100644 client/telemetry/src/worker/node_pool.rs diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 627c10c2f8d5d..e54baad2626cb 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -237,7 +237,7 @@ pub fn new_full_base( telemetry_connection_sinks: telemetry_connection_sinks.clone(), network_status_sinks: network_status_sinks.clone(), system_rpc_tx, - telemetry: telemetry.clone(), + telemetry_stream: telemetry.map(|x| x.stream()), })?; let (block_import, grandpa_link, babe_link) = import_setup; @@ -449,7 +449,7 @@ pub fn new_light_base(config: Configuration) -> Result<( network: network.clone(), telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), task_manager: &mut task_manager, - telemetry, + telemetry_stream: telemetry.map(|x| x.stream()), })?; Ok((task_manager, rpc_handlers, client, network, transaction_pool)) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 4fd03c10ac438..4a198402cd9b4 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -455,7 +455,7 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, - telemetry_senders: sc_telemetry::Senders, + telemetries: sc_telemetry::Telemetries, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; @@ -526,7 +526,7 @@ pub trait CliConfiguration: Sized { role, base_path: Some(base_path), informant_output_format: Default::default(), - telemetry_senders, + telemetries, }) } @@ -547,14 +547,14 @@ pub trait CliConfiguration: Sized { /// 1. Sets the panic handler /// 2. Initializes the logger /// 3. Raises the FD limit - fn init(&self) -> Result { + fn init(&self) -> Result { let logger_pattern = self.log_filters()?; let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let senders = init_logger(&logger_pattern, tracing_receiver, tracing_targets)?; + let telemetries = init_logger(&logger_pattern, tracing_receiver, tracing_targets)?; if let Some(new_limit) = fdlimit::raise_fd_limit() { if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT { @@ -566,7 +566,7 @@ pub trait CliConfiguration: Sized { } } - Ok(senders) + Ok(telemetries) } } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 0881676d971c1..8524070522cef 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -221,16 +221,16 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, - telemetry_senders: sc_telemetry::Senders, + telemetries: sc_telemetry::Telemetries, ) -> error::Result { - command.create_configuration(self, task_executor, telemetry_senders) + command.create_configuration(self, task_executor, telemetries) } /// Create a runner for the command provided in argument. This will create a Configuration and /// a tokio runtime fn create_runner(&self, command: &T) -> error::Result> { - let telemetry_senders = command.init::()?; - Runner::new(self, command, telemetry_senders) + let telemetries = command.init::()?; + Runner::new(self, command, telemetries) } /// Native runtime version. @@ -244,7 +244,7 @@ pub fn init_logger( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option, -) -> std::result::Result { +) -> std::result::Result { fn parse_directives(dirs: impl AsRef) -> Vec { dirs.as_ref() .split(',') @@ -317,8 +317,8 @@ pub fn init_logger( "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetry_layer = sc_telemetry::TelemetryLayer::new(); - let senders = telemetry_layer.senders(); + let telemetry_layer = sc_telemetry::TelemetryLayer::default(); + let telemetries = telemetry_layer.telemetries(); let subscriber = FmtSubscriber::builder() .with_env_filter(env_filter) .with_writer(std::io::stderr) @@ -348,7 +348,7 @@ pub fn init_logger( )) } } - Ok(senders) + Ok(telemetries) } #[cfg(test)] diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 9a8c2dca7eae3..a233dcacea3df 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -120,7 +120,7 @@ impl Runner { pub fn new( cli: &C, command: &T, - telemetry_senders: sc_telemetry::Senders, + telemetries: sc_telemetry::Telemetries, ) -> Result> { let tokio_runtime = build_runtime()?; let runtime_handle = tokio_runtime.handle().clone(); @@ -138,7 +138,7 @@ impl Runner { config: command.create_configuration( cli, task_executor.into(), - telemetry_senders, + telemetries, )?, tokio_runtime, phantom: PhantomData, diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index e5e39c79dcd8d..511ba6c2114e4 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -448,7 +448,7 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { /// Shared Telemetry connection sinks, pub telemetry_connection_sinks: TelemetryConnectionSinks, /// Telemetry object. - pub telemetry: Option, + pub telemetry_stream: Option, } /// Build a shared offchain workers instance. @@ -529,7 +529,7 @@ pub fn spawn_tasks( network_status_sinks, system_rpc_tx, telemetry_connection_sinks, - telemetry, + telemetry_stream, } = params; let chain_info = client.usage_info().chain; @@ -540,9 +540,9 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - if let Some(telemetry) = telemetry.clone() { + if let Some(telemetry_stream) = telemetry_stream { spawn_telemetry_worker( - telemetry, + telemetry_stream, &mut config, telemetry_connection_sinks.clone(), network.clone(), @@ -623,8 +623,10 @@ pub fn spawn_tasks( config.informant_output_format, )); - // TODO: probably dont need this anymore - task_manager.keep_alive((telemetry, config.base_path, rpc, rpc_handlers.clone())); + // TODO I'm not 100% sure I don't need the keep alive anymore. Well, not in all our use cases + // but it is possible to call this function without having a telemetry coming from + // `Telemetries` + task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone())); Ok(rpc_handlers) } @@ -657,17 +659,17 @@ fn init_telemetry(config: &Configuration) -> Option { // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) _ => return None, }; - let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { + let telemetry = config.telemetries.get_or_create( endpoints, - wasm_external_transport: config.telemetry_external_transport.clone(), - }); - telemetry.push_sender(&config.telemetry_senders); + // TODO + //config.telemetry_external_transport.clone(), + ); Some(telemetry) } fn spawn_telemetry_worker>( - telemetry: sc_telemetry::Telemetry, + telemetry_stream: sc_telemetry::TelemetryStream, config: &mut Configuration, telemetry_connection_sinks: TelemetryConnectionSinks, network: Arc::Hash>>, @@ -691,7 +693,7 @@ fn spawn_telemetry_worker>( spawn_handle.spawn( "telemetry-worker", - telemetry + telemetry_stream .for_each(move |event| { // Safe-guard in case we add more events in the future. let sc_telemetry::TelemetryEvent::Connected = event; diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 9dce37d17a013..62dd71d90ed9f 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -87,8 +87,8 @@ pub struct Configuration { /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, - /// Telemetry senders - pub telemetry_senders: sc_telemetry::Senders, + /// All the telemetries. + pub telemetries: sc_telemetry::Telemetries, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 81c0b0fed7f0e..2c89649b69899 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::Telemetries; use futures::channel::mpsc; use parking_lot::Mutex; use std::collections::HashMap; @@ -26,14 +27,11 @@ use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; -pub struct TelemetryLayer(Senders); +#[derive(Debug, Default)] +pub struct TelemetryLayer(Telemetries); impl TelemetryLayer { - pub fn new() -> Self { - Self(Default::default()) - } - - pub fn senders(&self) -> Senders { + pub fn telemetries(&self) -> Telemetries { self.0.clone() } } @@ -49,7 +47,7 @@ where if let Some(span) = ctx.scope().find(|x| x.name() == TELEMETRY_LOG_SPAN) { let id = span.id().into_u64(); - if let Some(sender) = (self.0).0.lock().get_mut(&id) { + if let Some(sender) = self.0.senders.0.lock().get_mut(&id) { let mut attrs = (None, None); let mut vis = TelemetryAttrsVisitor(&mut attrs); event.record(&mut vis); diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 48ed19a2723f9..9676548506fc6 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -80,33 +80,16 @@ pub use serde_json; pub use tracing; mod layer; -mod worker; +pub mod worker; pub use layer::*; - -/// Configuration for telemetry. -pub struct TelemetryConfig { - /// Collection of telemetry WebSocket servers with a corresponding verbosity level. - pub endpoints: TelemetryEndpoints, - - /// Optional external implementation of a libp2p transport. Used in WASM contexts where we need - /// some binding between the networking provided by the operating system or environment and - /// libp2p. - /// - /// This parameter exists whatever the target platform is, but it is expected to be set to - /// `Some` only when compiling for WASM. - /// - /// > **Important**: Each individual call to `write` corresponds to one message. There is no - /// > internal buffering going on. In the context of WebSockets, each `write` - /// > must be one individual WebSockets frame. - pub wasm_external_transport: Option, -} +use worker::node_pool::*; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the /// maximum verbosity level. /// /// The URL string can be either a URL or a multiaddress. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct TelemetryEndpoints( #[serde(deserialize_with = "url_or_multiaddr_deser")] Vec<(Multiaddr, u8)> @@ -170,21 +153,10 @@ pub const CONSENSUS_INFO: u8 = 1; /// Contains an `Arc` and can be cloned and pass around. Only one clone needs to be polled /// regularly and should be polled regularly. /// Dropping all the clones unregisters the telemetry. -#[derive(Clone)] +#[derive(Debug)] pub struct Telemetry { inner: Arc>, span: tracing::Span, - sender: mpsc::Sender<(u8, String)>, -} - -impl Telemetry { - /// TODO - pub fn push_sender(&self, senders: &Senders) { - senders.insert( - self.span.id().expect("the span is enabled; qed").into_u64(), - self.sender.clone(), - ) - } } impl Drop for Telemetry { @@ -194,12 +166,14 @@ impl Drop for Telemetry { } } +/// TODO update doc as Telemetry isnt clonable anymore /// Behind the `Mutex` in `Telemetry`. /// /// Note that ideally we wouldn't have to make the `Telemetry` cloneable, as that would remove the /// need for a `Mutex`. However there is currently a weird hack in place in `sc-service` /// where we extract the telemetry registration so that it continues running during the shutdown /// process. +#[derive(Debug)] struct TelemetryInner { /// Worker for the telemetry. `None` if it failed to initialize. worker: Option, @@ -207,35 +181,54 @@ struct TelemetryInner { receiver: mpsc::Receiver<(u8, String)>, } -/// Initializes the telemetry. See the crate root documentation for more information. -/// -/// Please be careful to not call this function twice in the same program. The `slog` crate -/// doesn't provide any way of knowing whether a global logger has already been registered. -pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { - // Build the list of telemetry endpoints. - let (endpoints, wasm_external_transport) = (config.endpoints.0, config.wasm_external_transport); - - let (sender, receiver) = mpsc::channel(16); - - let worker = match worker::TelemetryWorker::new(endpoints, wasm_external_transport) { - Ok(w) => Some(w), - Err(err) => { - error!(target: "telemetry", "Failed to initialize telemetry worker: {:?}", err); - None - } - }; +impl Telemetry { + // TODO update doc + /// Initializes the telemetry. See the crate root documentation for more information. + /// + /// Please be careful to not call this function twice in the same program. The `slog` crate + /// doesn't provide any way of knowing whether a global logger has already been registered. + pub fn new( + endpoints: TelemetryEndpoints, + wasm_external_transport: Option, + node_pool: Option<&NodePool>, + ) -> (Self, mpsc::Sender<(u8, String)>) { + let endpoints = endpoints.0; + + let (sender, receiver) = mpsc::channel(16); + + let worker = match worker::TelemetryWorker::new( + endpoints, + wasm_external_transport, + node_pool, + ) { + Ok(w) => Some(w), + Err(err) => { + error!(target: "telemetry", "Failed to initialize telemetry worker: {:?}", err); + None + } + }; + + let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let span_id = span.id().expect("the span is enabled; qed"); + tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&span_id)); + + ( + Self { + inner: Arc::new(Mutex::new(TelemetryInner { + worker, + receiver, + })), + span, + }, + sender, + ) + } - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let span_id = span.id().expect("the span is enabled; qed"); - tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&span_id)); - - Telemetry { - inner: Arc::new(Mutex::new(TelemetryInner { - worker, - receiver, - })), - span, - sender, + /// TODO doc + pub fn stream(self) -> TelemetryStream { + TelemetryStream { + inner: self.inner.clone(), + } } } @@ -247,7 +240,13 @@ pub enum TelemetryEvent { Connected, } -impl Stream for Telemetry { +/// TODO doc +#[derive(Debug)] +pub struct TelemetryStream { + inner: Arc>, +} + +impl Stream for TelemetryStream { type Item = TelemetryEvent; fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { @@ -311,6 +310,53 @@ impl Stream for Telemetry { } } +/// TODO doc +#[derive(Debug, Default, Clone)] +pub struct Telemetries { + senders: Senders, + node_pool: Arc>, + wasm_external_transport: Option, +} + +impl Telemetries { + /// TODO doc + pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Self { + Self { + wasm_external_transport: Some(wasm_external_transport), + ..Default::default() + } + } + + // TODO update doc / move to root + /// endpoints: + /// + /// Collection of telemetry WebSocket servers with a corresponding verbosity level. + /// Optional external implementation of a libp2p transport. Used in WASM contexts where we need + /// some binding between the networking provided by the operating system or environment and + /// libp2p. + /// + /// wasm_external_transport: + /// + /// This parameter exists whatever the target platform is, but it is expected to be set to + /// `Some` only when compiling for WASM. + /// + /// > **Important**: Each individual call to `write` corresponds to one message. There is no + /// > internal buffering going on. In the context of WebSockets, each `write` + /// > must be one individual WebSockets frame. + pub fn get_or_create(&self, endpoints: TelemetryEndpoints) -> Telemetry { + let (telemetry, sender) = Telemetry::new( + endpoints.clone(), + self.wasm_external_transport.clone(), + Some(&self.node_pool.lock()), + ); + let id = telemetry.span.id().expect("the span is enabled; qed").into_u64(); + + self.senders.insert(id, sender); + + telemetry + } +} + /// TODO doc /// Translates to `slog_scope::info`, but contains an additional verbosity /// parameter which the log record is tagged with. Additionally the verbosity diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index ad1c64bf9a97e..d75f233272a58 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -31,9 +31,13 @@ use futures::{prelude::*, ready}; use libp2p::{core::transport::OptionalTransport, Multiaddr, Transport, wasm_ext}; use log::{trace, error}; -use std::{io, pin::Pin, task::Context, task::Poll, time}; +use parking_lot::Mutex; +use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; mod node; +pub(crate) mod node_pool; + +use node_pool::NodePool; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. @@ -51,13 +55,13 @@ pub enum TelemetryWorkerEvent { #[derive(Debug)] pub struct TelemetryWorker { /// List of nodes with their maximum verbosity level. - nodes: Vec<(node::Node, u8)>, + nodes: Vec<(Arc>>, u8)>, } -trait StreamAndSink: Stream + Sink {} +pub trait StreamAndSink: Stream + Sink {} impl, I> StreamAndSink for T {} -type WsTrans = libp2p::core::transport::boxed::Boxed< +pub type WsTrans = libp2p::core::transport::boxed::Boxed< Pin, Item = Result, io::Error>, @@ -67,6 +71,7 @@ type WsTrans = libp2p::core::transport::boxed::Boxed< >; impl TelemetryWorker { + // TODO update doc /// Builds a new `TelemetryWorker`. /// /// The endpoints must be a list of targets, plus a verbosity level. When you send a message @@ -74,7 +79,8 @@ impl TelemetryWorker { /// message will receive it. pub fn new( endpoints: impl IntoIterator, - wasm_external_transport: impl Into> + wasm_external_transport: impl Into>, + node_pool: Option<&NodePool>, ) -> Result { let transport = match wasm_external_transport.into() { Some(t) => OptionalTransport::some(t), @@ -113,7 +119,11 @@ impl TelemetryWorker { Ok(TelemetryWorker { nodes: endpoints.into_iter().map(|(addr, verbosity)| { - let node = node::Node::new(transport.clone(), addr); + let node = if let Some(node_pool) = node_pool { + node_pool.get_or_create(transport.clone(), addr) + } else { + Arc::new(Mutex::new(node::Node::new(transport.clone(), addr))) + }; (node, verbosity) }).collect() }) @@ -123,7 +133,7 @@ impl TelemetryWorker { pub fn poll(&mut self, cx: &mut Context) -> Poll { for (node, _) in &mut self.nodes { loop { - match node::Node::poll(Pin::new(node), cx) { + match node::Node::poll(Pin::new(&mut node.lock()), cx) { Poll::Ready(node::NodeEvent::Connected) => return Poll::Ready(TelemetryWorkerEvent::Connected), Poll::Ready(node::NodeEvent::Disconnected(_)) => continue, @@ -152,6 +162,8 @@ impl TelemetryWorker { } for (node, node_max_verbosity) in &mut self.nodes { + let mut node = node.lock(); + if msg_verbosity > *node_max_verbosity { trace!(target: "telemetry", "Skipping {:?} for log entry with verbosity {:?}", node.addr(), msg_verbosity); diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs new file mode 100644 index 0000000000000..8d888253b5f46 --- /dev/null +++ b/client/telemetry/src/worker/node_pool.rs @@ -0,0 +1,38 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::worker::{node::Node, WsTrans}; +use libp2p::Multiaddr; +use parking_lot::Mutex; +use std::collections::HashMap; +use std::sync::Arc; + +#[derive(Debug, Default)] +pub struct NodePool { + nodes: Mutex>>>>, +} + +impl NodePool { + pub fn get_or_create(&self, transport: WsTrans, addr: Multiaddr) -> Arc>> { + self.nodes + .lock() + .entry(addr.clone()) + .or_insert_with(|| Arc::new(Node::new(transport, addr).into())) + .clone() + } +} From aadae1cff84d2fcc740460e44f95074c94eb9274 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 17:07:39 +0100 Subject: [PATCH 031/222] Refactoring guarding object --- bin/node/cli/src/service.rs | 4 +-- client/service/src/builder.rs | 15 +++++------ client/telemetry/src/lib.rs | 48 ++++++----------------------------- 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index e54baad2626cb..dfb5b80eed8bf 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -237,7 +237,7 @@ pub fn new_full_base( telemetry_connection_sinks: telemetry_connection_sinks.clone(), network_status_sinks: network_status_sinks.clone(), system_rpc_tx, - telemetry_stream: telemetry.map(|x| x.stream()), + telemetry, })?; let (block_import, grandpa_link, babe_link) = import_setup; @@ -449,7 +449,7 @@ pub fn new_light_base(config: Configuration) -> Result<( network: network.clone(), telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), task_manager: &mut task_manager, - telemetry_stream: telemetry.map(|x| x.stream()), + telemetry, })?; Ok((task_manager, rpc_handlers, client, network, transaction_pool)) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 511ba6c2114e4..349c58c172afe 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -448,7 +448,7 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { /// Shared Telemetry connection sinks, pub telemetry_connection_sinks: TelemetryConnectionSinks, /// Telemetry object. - pub telemetry_stream: Option, + pub telemetry: Option, } /// Build a shared offchain workers instance. @@ -529,7 +529,7 @@ pub fn spawn_tasks( network_status_sinks, system_rpc_tx, telemetry_connection_sinks, - telemetry_stream, + telemetry, } = params; let chain_info = client.usage_info().chain; @@ -540,9 +540,9 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - if let Some(telemetry_stream) = telemetry_stream { + if let Some(telemetry) = telemetry { spawn_telemetry_worker( - telemetry_stream, + telemetry, &mut config, telemetry_connection_sinks.clone(), network.clone(), @@ -623,9 +623,6 @@ pub fn spawn_tasks( config.informant_output_format, )); - // TODO I'm not 100% sure I don't need the keep alive anymore. Well, not in all our use cases - // but it is possible to call this function without having a telemetry coming from - // `Telemetries` task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone())); Ok(rpc_handlers) @@ -669,7 +666,7 @@ fn init_telemetry(config: &Configuration) -> Option { } fn spawn_telemetry_worker>( - telemetry_stream: sc_telemetry::TelemetryStream, + telemetry: sc_telemetry::Telemetry, config: &mut Configuration, telemetry_connection_sinks: TelemetryConnectionSinks, network: Arc::Hash>>, @@ -693,7 +690,7 @@ fn spawn_telemetry_worker>( spawn_handle.spawn( "telemetry-worker", - telemetry_stream + telemetry .for_each(move |event| { // Safe-guard in case we add more events in the future. let sc_telemetry::TelemetryEvent::Connected = event; diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 9676548506fc6..f1b9d924db7a5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -155,7 +155,7 @@ pub const CONSENSUS_INFO: u8 = 1; /// Dropping all the clones unregisters the telemetry. #[derive(Debug)] pub struct Telemetry { - inner: Arc>, + inner: TelemetryInner, span: tracing::Span, } @@ -214,22 +214,15 @@ impl Telemetry { ( Self { - inner: Arc::new(Mutex::new(TelemetryInner { + inner: TelemetryInner { worker, receiver, - })), + }, span, }, sender, ) } - - /// TODO doc - pub fn stream(self) -> TelemetryStream { - TelemetryStream { - inner: self.inner.clone(), - } - } } /// Event generated when polling the worker. @@ -240,43 +233,18 @@ pub enum TelemetryEvent { Connected, } -/// TODO doc -#[derive(Debug)] -pub struct TelemetryStream { - inner: Arc>, -} - -impl Stream for TelemetryStream { +impl Stream for Telemetry { type Item = TelemetryEvent; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let before = Instant::now(); - // Because the `Telemetry` is cloneable, we need to put the actual fields behind a `Mutex`. - // However, the user is only ever supposed to poll from one instance of `Telemetry`, while - // the other instances are used only for RAII purposes. - // We assume that the user is following this advice and therefore that the `Mutex` is only - // ever locked once at a time. - let mut inner = match self.inner.try_lock() { - Some(l) => l, - None => { - warn!( - target: "telemetry", - "The telemetry seems to be polled multiple times simultaneously" - ); - // Returning `Pending` here means that we may never get polled again, but this is - // ok because we're in a situation where something else is actually currently doing - // the polling. - return Poll::Pending; - } - }; - let mut has_connected = false; // The polling pattern is: poll the worker so that it processes its queue, then add one // message from the receiver (if possible), then poll the worker again, and so on. loop { - if let Some(worker) = inner.worker.as_mut() { + if let Some(worker) = self.inner.worker.as_mut() { while let Poll::Ready(event) = worker.poll(cx) { // Right now we only have one possible event. This line is here in order to not // forget to handle any possible new event type. @@ -288,9 +256,9 @@ impl Stream for TelemetryStream { if let Poll::Ready(Some(( message_verbosity, json, - ))) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) + ))) = Stream::poll_next(Pin::new(&mut self.inner.receiver), cx) { - if let Some(worker) = inner.worker.as_mut() { + if let Some(worker) = self.inner.worker.as_mut() { let _ = worker.log(message_verbosity, json.as_str()); } } else { From 520c38b792c0a2544fb7585cfef66873a9c8b722 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 17:53:11 +0100 Subject: [PATCH 032/222] Inject span id in the json (not elegant) --- client/telemetry/src/layer.rs | 35 ++++++++++++++++++++++++++++++----- client/telemetry/src/lib.rs | 1 + 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 2c89649b69899..2a3a2f68aa19a 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -48,12 +48,16 @@ where if let Some(span) = ctx.scope().find(|x| x.name() == TELEMETRY_LOG_SPAN) { let id = span.id().into_u64(); if let Some(sender) = self.0.senders.0.lock().get_mut(&id) { - let mut attrs = (None, None); + let mut attrs = TelemetryAttrs::new(id); let mut vis = TelemetryAttrsVisitor(&mut attrs); event.record(&mut vis); match attrs { - (Some(message_verbosity), Some(json)) => { + TelemetryAttrs { + message_verbosity: Some(message_verbosity), + json: Some(json), + .. + } => { if let Err(err) = sender.try_send(( message_verbosity .try_into() @@ -76,7 +80,25 @@ where } } -struct TelemetryAttrsVisitor<'a>(&'a mut (Option, Option)); +#[derive(Debug)] +struct TelemetryAttrs { + message_verbosity: Option, + json: Option, + id: u64, +} + +impl TelemetryAttrs { + fn new(id: u64) -> Self { + Self { + message_verbosity: None, + json: None, + id, + } + } +} + +#[derive(Debug)] +struct TelemetryAttrsVisitor<'a>(&'a mut TelemetryAttrs); impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) { @@ -85,13 +107,16 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_u64(&mut self, field: &tracing::field::Field, value: u64) { if field.name() == "message_verbosity" { - (*self.0).0 = Some(value) + (*self.0).message_verbosity = Some(value) } } fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { - (*self.0).1 = Some(value.to_string()) + // NOTE: this is a hack to inject the span id into the json + let mut message = format!(r#"{{"id":{},"#, (*self.0).id); + message.push_str(&value[1..]); + (*self.0).json = Some(message) } } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f1b9d924db7a5..a7d52f9e3084e 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -334,6 +334,7 @@ macro_rules! telemetry { ( $a:expr; $b:expr; $( $t:tt )* ) => {{ let message_verbosity: u8 = $a; let mut json = format_fields_to_json!($($t)*); + // NOTE: the span id will be added later in the JSON for the greater good json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); From 7385c62478710ac14f0942547802578795c95b1d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 30 Oct 2020 18:13:30 +0100 Subject: [PATCH 033/222] Fix passing transport argument --- client/cli/src/config.rs | 7 ++++++- client/cli/src/lib.rs | 3 ++- client/service/src/builder.rs | 8 +------- client/telemetry/src/layer.rs | 15 ++++++++++++++- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 4a198402cd9b4..6e57d91a8f381 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -554,7 +554,12 @@ pub trait CliConfiguration: Sized { sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let telemetries = init_logger(&logger_pattern, tracing_receiver, tracing_targets)?; + let telemetries = init_logger( + &logger_pattern, + tracing_receiver, + tracing_targets, + self.telemetry_external_transport()?, + )?; if let Some(new_limit) = fdlimit::raise_fd_limit() { if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT { diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 8524070522cef..62e9a823c8de3 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -244,6 +244,7 @@ pub fn init_logger( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option, + telemetry_external_transport: Option, ) -> std::result::Result { fn parse_directives(dirs: impl AsRef) -> Vec { dirs.as_ref() @@ -317,7 +318,7 @@ pub fn init_logger( "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetry_layer = sc_telemetry::TelemetryLayer::default(); + let telemetry_layer = sc_telemetry::TelemetryLayer::new(telemetry_external_transport); let telemetries = telemetry_layer.telemetries(); let subscriber = FmtSubscriber::builder() .with_env_filter(env_filter) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 349c58c172afe..5e65c693c8727 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -656,13 +656,7 @@ fn init_telemetry(config: &Configuration) -> Option { // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) _ => return None, }; - let telemetry = config.telemetries.get_or_create( - endpoints, - // TODO - //config.telemetry_external_transport.clone(), - ); - - Some(telemetry) + Some(config.telemetries.get_or_create(endpoints)) } fn spawn_telemetry_worker>( diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 2a3a2f68aa19a..dd5cfdc46f3a8 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -18,6 +18,7 @@ use crate::Telemetries; use futures::channel::mpsc; +use libp2p::wasm_ext::ExtTransport; use parking_lot::Mutex; use std::collections::HashMap; use std::convert::TryInto; @@ -27,10 +28,22 @@ use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct TelemetryLayer(Telemetries); impl TelemetryLayer { + /// TODO + pub fn new(telemetry_external_transport: Option) -> Self { + if let Some(telemetry_external_transport) = telemetry_external_transport { + Self(Telemetries::with_wasm_external_transport( + telemetry_external_transport, + )) + } else { + Self(Default::default()) + } + } + + /// TODO pub fn telemetries(&self) -> Telemetries { self.0.clone() } From cc41d72b7997064a13a4329c334be67367c6c188 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 4 Nov 2020 10:16:08 +0100 Subject: [PATCH 034/222] CLEANUP --- client/cli/src/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 6e57d91a8f381..fd4a4153b3d24 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -551,6 +551,7 @@ pub trait CliConfiguration: Sized { let logger_pattern = self.log_filters()?; let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; + let telemetry_external_transport = self.telemetry_external_transport()?; sp_panic_handler::set(&C::support_url(), &C::impl_version()); @@ -558,7 +559,7 @@ pub trait CliConfiguration: Sized { &logger_pattern, tracing_receiver, tracing_targets, - self.telemetry_external_transport()?, + telemetry_external_transport, )?; if let Some(new_limit) = fdlimit::raise_fd_limit() { From a5c64fda1ed6d41f29126a01b4fe0cc84e16c87e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 4 Nov 2020 11:17:24 +0100 Subject: [PATCH 035/222] Spawn 2 nodes instead of one --- bin/node/cli/src/command.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index f8a0f3f9b3a34..d62a71690f36c 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -73,10 +73,18 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } + // TODO revert after test + let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetries.clone()).unwrap(); + let mut task_manager = match config.role { + Role::Light => service::new_light(config).unwrap(), + _ => service::new_full(config).unwrap(), + }; + let task_manager2 = match config2.role { + Role::Light => service::new_light(config2).unwrap(), + _ => service::new_full(config2).unwrap(), + }; + task_manager.add_child(task_manager2); + Ok(task_manager) }) } Some(Subcommand::Inspect(cmd)) => { From 79f05aca3c4b9373ae79b01f6c0bbda75a4a98b8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 4 Nov 2020 17:29:01 +0100 Subject: [PATCH 036/222] WIP --- client/telemetry/src/layer.rs | 65 ++++++++++++++---------- client/telemetry/src/worker.rs | 31 ++++++++--- client/telemetry/src/worker/node_pool.rs | 23 ++++++--- 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index dd5cfdc46f3a8..8aaf262181ae4 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -58,36 +58,49 @@ where return; } - if let Some(span) = ctx.scope().find(|x| x.name() == TELEMETRY_LOG_SPAN) { - let id = span.id().into_u64(); - if let Some(sender) = self.0.senders.0.lock().get_mut(&id) { - let mut attrs = TelemetryAttrs::new(id); - let mut vis = TelemetryAttrsVisitor(&mut attrs); - event.record(&mut vis); - - match attrs { - TelemetryAttrs { - message_verbosity: Some(message_verbosity), - json: Some(json), - .. - } => { - if let Err(err) = sender.try_send(( - message_verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )) { - log::warn!( - target: "telemetry", - "Ignored telemetry message because of error on channel: {:?}", - err, + if let Some(span) = ctx.lookup_current() { + let parents = span.parents(); + + if let Some(span) = std::iter::once(span) + .chain(parents) + .find(|x| x.name() == TELEMETRY_LOG_SPAN) + { + let id = span.id().into_u64(); + if let Some(sender) = self.0.senders.0.lock().get_mut(&id) { + let mut attrs = TelemetryAttrs::new(id); + let mut vis = TelemetryAttrsVisitor(&mut attrs); + event.record(&mut vis); + + match attrs { + TelemetryAttrs { + message_verbosity: Some(message_verbosity), + json: Some(json), + .. + } => { + eprintln!( + //target: "telemetry", + "###### sent message as {}: {}", id, json, ); + if let Err(err) = sender.try_send(( + message_verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json.clone(), + )) { + // TODO logs dont work here + log::warn!( + target: "telemetry", + "Ignored telemetry message because of error on channel: {:?}", + err, + ); + } } + _ => panic!("missing fields in telemetry log: {:?}", event), } - _ => panic!("missing fields in telemetry log: {:?}", event), + } else { + // TODO logs dont work here + log::trace!(target: "telemetry", "Telemetry not set"); } - } else { - log::trace!(target: "telemetry", "Telemetry not set"); } } } diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 1beb568491929..b4220a58646e1 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -61,6 +61,8 @@ pub enum TelemetryWorkerEvent { pub struct TelemetryWorker { /// List of nodes with their maximum verbosity level. nodes: Vec<(Arc>>, u8)>, + /// Force `poll()` to return `Connected`. + force_connected: bool, } pub trait StreamAndSink: Stream + Sink {} @@ -120,20 +122,33 @@ impl TelemetryWorker { CONNECT_TIMEOUT ).boxed(); + let mut force_connected = false; + let nodes = endpoints.into_iter().map(|(addr, verbosity)| { + let node = if let Some(node_pool) = node_pool { + let (node, is_new) = node_pool.get_or_create(transport.clone(), addr); + if !is_new { + force_connected = true; + } + node + } else { + Arc::new(Mutex::new(node::Node::new(transport.clone(), addr))) + }; + (node, verbosity) + }).collect(); + Ok(TelemetryWorker { - nodes: endpoints.into_iter().map(|(addr, verbosity)| { - let node = if let Some(node_pool) = node_pool { - node_pool.get_or_create(transport.clone(), addr) - } else { - Arc::new(Mutex::new(node::Node::new(transport.clone(), addr))) - }; - (node, verbosity) - }).collect() + nodes, + force_connected, }) } /// Polls the worker for events that happened. pub fn poll(&mut self, cx: &mut Context) -> Poll { + if self.force_connected { + self.force_connected = false; + return Poll::Ready(TelemetryWorkerEvent::Connected); + } + for (node, _) in &mut self.nodes { loop { match node::Node::poll(Pin::new(&mut node.lock()), cx) { diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs index 8d888253b5f46..61947a113430a 100644 --- a/client/telemetry/src/worker/node_pool.rs +++ b/client/telemetry/src/worker/node_pool.rs @@ -19,7 +19,7 @@ use crate::worker::{node::Node, WsTrans}; use libp2p::Multiaddr; use parking_lot::Mutex; -use std::collections::HashMap; +use std::collections::{hash_map::Entry, HashMap}; use std::sync::Arc; #[derive(Debug, Default)] @@ -28,11 +28,20 @@ pub struct NodePool { } impl NodePool { - pub fn get_or_create(&self, transport: WsTrans, addr: Multiaddr) -> Arc>> { - self.nodes - .lock() - .entry(addr.clone()) - .or_insert_with(|| Arc::new(Node::new(transport, addr).into())) - .clone() + pub fn get_or_create( + &self, + transport: WsTrans, + addr: Multiaddr, + ) -> (Arc>>, bool) { + let mut nodes = self.nodes.lock(); + let entry = nodes.entry(addr.clone()); + let new = matches!(entry, Entry::Vacant(..)); + + ( + entry + .or_insert_with(|| Arc::new(Node::new(transport, addr).into())) + .clone(), + new, + ) } } From 24f3c0d55b79dab4efebd13a04fd058cd50da23b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 5 Nov 2020 13:00:49 +0100 Subject: [PATCH 037/222] WIP --- bin/node-template/node/src/service.rs | 2 +- client/service/test/src/lib.rs | 2 +- utils/browser/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index a8d335cc49382..38e0ef661d681 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -159,7 +159,7 @@ pub fn new_full(config: Configuration) -> Result { network_status_sinks, system_rpc_tx, config, - telemetry: telemetry.clone(), + telemetry, })?; if role.is_authority() { diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index fad9cc695d4b0..370ccac62e9be 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,7 +263,7 @@ fn node_config Date: Thu, 5 Nov 2020 17:08:46 +0100 Subject: [PATCH 038/222] WIP --- Cargo.lock | 34 +++--- bin/node/cli/browser-demo/build.sh | 2 +- bin/node/cli/src/browser.rs | 6 +- client/cli/Cargo.toml | 6 +- client/cli/src/config.rs | 2 +- client/cli/src/lib.rs | 122 ++++---------------- client/service/Cargo.toml | 4 + client/service/src/lib.rs | 1 + client/{cli => service}/src/logging.rs | 153 +++++++++++++++++++++++-- utils/browser/Cargo.toml | 5 +- utils/browser/src/lib.rs | 30 ++++- 11 files changed, 225 insertions(+), 140 deletions(-) rename client/{cli => service}/src/logging.rs (60%) diff --git a/Cargo.lock b/Cargo.lock index 25da12e3aeb1a..621aabde752ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -831,16 +831,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "console_log" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7871d2947441b0fdd8e2bd1ce2a2f75304f896582c0d572162d48290683c48" -dependencies = [ - "log", - "web-sys", -] - [[package]] name = "const-random" version = "0.1.11" @@ -6519,8 +6509,6 @@ dependencies = [ name = "sc-cli" version = "0.8.0" dependencies = [ - "ansi_term 0.12.1", - "atty", "bip39", "chrono", "fdlimit", @@ -6555,8 +6543,6 @@ dependencies = [ "thiserror", "tokio 0.2.22", "tracing", - "tracing-log", - "tracing-subscriber", ] [[package]] @@ -7354,7 +7340,9 @@ dependencies = [ name = "sc-service" version = "0.8.0" dependencies = [ + "ansi_term 0.12.1", "async-std", + "atty", "derive_more", "directories", "exit-future", @@ -7416,6 +7404,8 @@ dependencies = [ "tokio 0.2.22", "tracing", "tracing-futures", + "tracing-log", + "tracing-subscriber", "wasm-timer", ] @@ -8835,7 +8825,6 @@ version = "0.8.0" dependencies = [ "chrono", "console_error_panic_hook", - "console_log", "futures 0.1.29", "futures 0.3.5", "futures-timer 3.0.2", @@ -8849,7 +8838,11 @@ dependencies = [ "sc-informant", "sc-network", "sc-service", + "sc-telemetry", "sp-database", + "tracing", + "tracing-subscriber", + "tracing-wasm", "wasm-bindgen", "wasm-bindgen-futures", ] @@ -9670,6 +9663,17 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd96394d3d2f119de6c1078fa065b99217db4377f9aac6e87f8393276a0d7962" +dependencies = [ + "tracing", + "tracing-subscriber", + "wasm-bindgen", +] + [[package]] name = "treeline" version = "0.1.0" diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh index be52b7a523f01..337c36db7f39f 100755 --- a/bin/node/cli/browser-demo/build.sh +++ b/bin/node/cli/browser-demo/build.sh @@ -1,4 +1,4 @@ #!/usr/bin/env sh cargo +nightly build --release -p node-cli --target wasm32-unknown-unknown --no-default-features --features browser -Z features=itarget wasm-bindgen ../../../../target/wasm32-unknown-unknown/release/node_cli.wasm --out-dir pkg --target web -python -m http.server 8000 +python -m http.server 8080 diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 41770f5fcde6d..4451a39e2e665 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -23,7 +23,6 @@ use browser_utils::{ Client, browser_configuration, set_console_error_panic_hook, init_console_log, }; -use std::str::FromStr; /// Starts the client. #[wasm_bindgen] @@ -35,14 +34,15 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_level: String) -> Result> { set_console_error_panic_hook(); - init_console_log(log::Level::from_str(&log_level)?)?; + let telemetries = init_console_log(log_level.as_str())?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let config = browser_configuration(chain_spec).await?; + let mut config = browser_configuration(chain_spec, telemetries).await?; + config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_string(), 10)]).unwrap()); info!("Substrate browser node"); info!("✌️ version {}", config.impl_version); diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index b7e798a3ba1c1..d2682d7dbf12a 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -14,9 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -atty = "0.2.13" regex = "1.3.4" -ansi_term = "0.12.1" tokio = { version = "0.2.21", features = [ "signal", "rt-core", "rt-threaded", "blocking" ] } futures = "0.3.4" fdlimit = "0.2.1" @@ -44,9 +42,7 @@ structopt = "0.3.8" sc-tracing = { version = "2.0.0", path = "../tracing" } chrono = "0.4.10" serde = "1.0.111" -tracing = "0.1.10" -tracing-log = "0.1.1" -tracing-subscriber = "0.2.10" +tracing = "0.1.19" sc-cli-proc-macro = { version = "2.0.0", path = "./proc-macro" } thiserror = "1.0.21" diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index fd4a4153b3d24..d62b81b50f456 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -558,7 +558,7 @@ pub trait CliConfiguration: Sized { let telemetries = init_logger( &logger_pattern, tracing_receiver, - tracing_targets, + tracing_targets.as_ref().map(|x| x.as_str()), telemetry_external_transport, )?; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 62e9a823c8de3..2f4d5303d9b0f 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -27,7 +27,6 @@ pub mod arg_enums; mod commands; mod config; mod error; -mod logging; mod params; mod runner; @@ -49,11 +48,9 @@ use structopt::{ }; #[doc(hidden)] pub use tracing; -use tracing_subscriber::{ - filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, FmtSubscriber, Layer, -}; -pub use logging::PREFIX_LOG_SPAN; +/// TODO used by the macro +pub use sc_service::logging::PREFIX_LOG_SPAN; /// Substrate client CLI /// @@ -243,113 +240,38 @@ pub trait SubstrateCli: Sized { pub fn init_logger( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, - profiling_targets: Option, + profiling_targets: Option<&str>, telemetry_external_transport: Option, ) -> std::result::Result { - fn parse_directives(dirs: impl AsRef) -> Vec { - dirs.as_ref() - .split(',') - .filter_map(|s| s.parse().ok()) - .collect() - } - - if let Err(e) = tracing_log::LogTracer::init() { - return Err(format!( - "Registering Substrate logger failed: {:}!", e - )) - } - - let mut env_filter = tracing_subscriber::EnvFilter::default() - // Disable info logging by default for some modules. - .add_directive("ws=off".parse().expect("provided directive is valid")) - .add_directive("yamux=off".parse().expect("provided directive is valid")) - .add_directive("cranelift_codegen=off".parse().expect("provided directive is valid")) - // Set warn logging by default for some modules. - .add_directive("cranelift_wasm=warn".parse().expect("provided directive is valid")) - .add_directive("hyper=warn".parse().expect("provided directive is valid")) - // Enable info for others. - .add_directive(tracing_subscriber::filter::LevelFilter::INFO.into()); - - if let Ok(lvl) = std::env::var("RUST_LOG") { - if lvl != "" { - // We're not sure if log or tracing is available at this moment, so silently ignore the - // parse error. - for directive in parse_directives(lvl) { - env_filter = env_filter.add_directive(directive); - } - } - } - - if pattern != "" { - // We're not sure if log or tracing is available at this moment, so silently ignore the - // parse error. - for directive in parse_directives(pattern) { - env_filter = env_filter.add_directive(directive); - } - } + Ok(if let Some(profiling_targets) = profiling_targets { + let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries_with_profiling( + pattern, + telemetry_external_transport, + tracing_receiver, + profiling_targets, + )?; - // If we're only logging `INFO` entries then we'll use a simplified logging format. - let simple = match Layer::::max_level_hint(&env_filter) { - Some(level) if level <= tracing_subscriber::filter::LevelFilter::INFO => true, - _ => false, - }; - - // Always log the special target `sc_tracing`, overrides global level. - // NOTE: this must be done after we check the `max_level_hint` otherwise - // it is always raised to `TRACE`. - env_filter = env_filter.add_directive( - "sc_tracing=trace" - .parse() - .expect("provided directive is valid"), - ); - - // Make sure to include profiling targets in the filter - if let Some(profiling_targets) = profiling_targets.clone() { - for directive in parse_directives(profiling_targets) { - env_filter = env_filter.add_directive(directive); - } - } - - let isatty = atty::is(atty::Stream::Stderr); - let enable_color = isatty; - let timer = ChronoLocal::with_format(if simple { - "%Y-%m-%d %H:%M:%S".to_string() - } else { - "%Y-%m-%d %H:%M:%S%.3f".to_string() - }); - - let telemetry_layer = sc_telemetry::TelemetryLayer::new(telemetry_external_transport); - let telemetries = telemetry_layer.telemetries(); - let subscriber = FmtSubscriber::builder() - .with_env_filter(env_filter) - .with_writer(std::io::stderr) - .event_format(logging::EventFormat { - timer, - ansi: enable_color, - display_target: !simple, - display_level: !simple, - display_thread_name: !simple, - }) - .finish() - .with(logging::NodeNameLayer) - .with(telemetry_layer); - - if let Some(profiling_targets) = profiling_targets { - let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets); - - if let Err(e) = tracing::subscriber::set_global_default(subscriber.with(profiling)) { + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { return Err(format!( "Registering Substrate tracing subscriber failed: {:}!", e )) } + + telemetries } else { + let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries( + pattern, + telemetry_external_transport, + )?; + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e + "Registering Substrate tracing subscriber failed: {:}!", e )) } - } - Ok(telemetries) + + telemetries + }) } #[cfg(test)] diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index c270e4ac239f1..a207a305c20d4 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -24,6 +24,8 @@ wasmtime = [ test-helpers = [] [dependencies] +ansi_term = "0.12.1" +atty = "0.2.13" derive_more = "0.99.2" futures01 = { package = "futures", version = "0.1.29" } futures = { version = "0.3.4", features = ["compat"] } @@ -77,6 +79,8 @@ sc-tracing = { version = "2.0.0", path = "../tracing" } sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } tracing = "0.1.19" tracing-futures = { version = "0.2.4" } +tracing-log = "0.1.1" +tracing-subscriber = "0.2.10" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 5183af9ccd889..54531996e1c09 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -33,6 +33,7 @@ pub mod client; #[cfg(not(feature = "test-helpers"))] mod client; mod task_manager; +pub mod logging; use std::{io, pin::Pin}; use std::net::SocketAddr; diff --git a/client/cli/src/logging.rs b/client/service/src/logging.rs similarity index 60% rename from client/cli/src/logging.rs rename to client/service/src/logging.rs index cdb7777180a2f..c01f145aef2da 100644 --- a/client/cli/src/logging.rs +++ b/client/service/src/logging.rs @@ -16,29 +16,39 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +//! TODO doc + use ansi_term::Colour; use std::fmt; use tracing::{span::Attributes, Event, Id, Level, Subscriber}; use tracing_log::NormalizeEvent; use tracing_subscriber::{ + filter::Directive, fmt::{ - time::{FormatTime, SystemTime}, + time::{ChronoLocal, FormatTime, SystemTime}, FmtContext, FormatEvent, FormatFields, }, - layer::Context, + layer::{Context, SubscriberExt}, registry::LookupSpan, + FmtSubscriber, Layer, }; /// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; -pub(crate) struct EventFormat { - pub(crate) timer: T, - pub(crate) ansi: bool, - pub(crate) display_target: bool, - pub(crate) display_level: bool, - pub(crate) display_thread_name: bool, +/// TODO doc +pub struct EventFormat { + /// TODO doc + pub timer: T, + /// TODO doc + pub ansi: bool, + /// TODO doc + pub display_target: bool, + /// TODO doc + pub display_level: bool, + /// TODO doc + pub display_thread_name: bool, } // NOTE: the following code took inspiration from tracing-subscriber @@ -56,6 +66,7 @@ where writer: &mut dyn fmt::Write, event: &Event, ) -> fmt::Result { + write!(writer, "############# boo"); if event.metadata().target() == sc_telemetry::TELEMETRY_LOG_SPAN { return Ok(()); } @@ -102,7 +113,8 @@ where } } -pub(crate) struct NodeNameLayer; +/// TODO doc +pub struct NodeNameLayer; impl Layer for NodeNameLayer where @@ -270,3 +282,126 @@ mod time { Ok(()) } } + +/// Initialize the global logger TODO update doc +/// +/// This sets various global logging and tracing instances and thus may only be called once. +pub fn get_default_subscriber_and_telemetries( + pattern: &str, + telemetry_external_transport: Option, +) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { + get_default_subscriber_and_telemetries_internal( + parse_directives(pattern), + telemetry_external_transport, + ) +} + +/// Initialize the global logger TODO update doc +/// +/// This sets various global logging and tracing instances and thus may only be called once. +pub fn get_default_subscriber_and_telemetries_with_profiling( + pattern: &str, + telemetry_external_transport: Option, + tracing_receiver: sc_tracing::TracingReceiver, + profiling_targets: &str, +) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { + let (subscriber, telemetries) = get_default_subscriber_and_telemetries_internal( + parse_directives(pattern).into_iter() + .chain(parse_directives(profiling_targets).into_iter()), + telemetry_external_transport, + )?; + let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, profiling_targets); + + Ok((subscriber.with(profiling), telemetries)) +} + +fn get_default_subscriber_and_telemetries_internal( + extra_directives: impl IntoIterator, + telemetry_external_transport: Option, +) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { + if let Err(e) = tracing_log::LogTracer::init() { + return Err(format!( + "Registering Substrate logger failed: {:}!", e + )) + } + + let mut env_filter = tracing_subscriber::EnvFilter::default() + // Disable info logging by default for some modules. + .add_directive("ws=off".parse().expect("provided directive is valid")) + .add_directive("yamux=off".parse().expect("provided directive is valid")) + .add_directive("cranelift_codegen=off".parse().expect("provided directive is valid")) + // Set warn logging by default for some modules. + .add_directive("cranelift_wasm=warn".parse().expect("provided directive is valid")) + .add_directive("hyper=warn".parse().expect("provided directive is valid")) + // Enable info for others. + .add_directive(tracing_subscriber::filter::LevelFilter::INFO.into()); + + if let Ok(lvl) = std::env::var("RUST_LOG") { + if lvl != "" { + // We're not sure if log or tracing is available at this moment, so silently ignore the + // parse error. + for directive in parse_directives(lvl) { + env_filter = env_filter.add_directive(directive); + } + } + } + + for directive in extra_directives { + // We're not sure if log or tracing is available at this moment, so silently ignore the + // parse error. + env_filter = env_filter.add_directive(directive); + } + + // If we're only logging `INFO` entries then we'll use a simplified logging format. + let simple = match Layer::::max_level_hint(&env_filter) { + Some(level) if level <= tracing_subscriber::filter::LevelFilter::INFO => true, + _ => false, + }; + + // Always log the special target `sc_tracing`, overrides global level. + // NOTE: this must be done after we check the `max_level_hint` otherwise + // it is always raised to `TRACE`. + env_filter = env_filter.add_directive( + "sc_tracing=trace" + .parse() + .expect("provided directive is valid"), + ); + + let isatty = atty::is(atty::Stream::Stderr); + let enable_color = isatty; + let timer = ChronoLocal::with_format(if simple { + "%Y-%m-%d %H:%M:%S".to_string() + } else { + "%Y-%m-%d %H:%M:%S%.3f".to_string() + }); + + let telemetry_layer = sc_telemetry::TelemetryLayer::new(telemetry_external_transport); + let telemetries = telemetry_layer.telemetries(); + let subscriber = FmtSubscriber::builder() + .with_env_filter(env_filter) + .with_writer(std::io::stderr) + .event_format(EventFormat { + timer, + ansi: enable_color, + display_target: !simple, + display_level: !simple, + display_thread_name: !simple, + }) + .finish() + .with(NodeNameLayer) + .with(telemetry_layer); + + Ok((subscriber, telemetries)) +} + +fn parse_directives(dirs: impl AsRef) -> Vec { + let dirs = dirs.as_ref(); + + if dirs.is_empty() { + return Default::default(); + } + + dirs.split(',') + .filter_map(|s| s.parse().ok()) + .collect() +} diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 90668f4e51fe8..c806ae7566a26 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -18,8 +18,10 @@ futures01 = { package = "futures", version = "0.1.29" } log = "0.4.8" libp2p-wasm-ext = { version = "0.23", features = ["websocket"] } console_error_panic_hook = "0.1.6" -console_log = "0.1.2" js-sys = "0.3.34" +tracing-wasm = "0.1.0" +tracing = "0.1.10" +tracing-subscriber = "0.2.10" wasm-bindgen = "0.2.57" wasm-bindgen-futures = "0.4.7" kvdb-web = "0.7" @@ -28,6 +30,7 @@ sc-informant = { version = "0.8.0", path = "../../client/informant" } sc-service = { version = "0.8.0", path = "../../client/service", default-features = false } sc-network = { path = "../../client/network", version = "0.8.0"} sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0"} +sc-telemetry = { path = "../../client/telemetry", version = "2.0.0"} # Imported just for the `wasm-bindgen` feature rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index a83e8e16deefd..302b08cb93dd1 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -30,15 +30,36 @@ use futures::{ use std::pin::Pin; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; +use tracing_wasm::{WASMLayerConfig, WASMLayer}; +use tracing_subscriber::layer::SubscriberExt; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; -pub use console_log::init_with_level as init_console_log; + +/// TODO doc +pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed anymore I think */) -> Result { + // TODO move to lazy static? + let transport = ExtTransport::new(ffi::websocket_transport()); + let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries( + pattern, + Some(transport), + )?; + + // TODO telemetry is working but WASMLayer bypasses FormatEvent + let subscriber = subscriber.with(WASMLayer::new(WASMLayerConfig::default())); + + tracing::subscriber::set_global_default(subscriber) + .map_err(|e| format!("could not set global default subscriber: {}", e))?; + + Ok(telemetries) +} /// Create a service configuration from a chain spec. /// /// This configuration contains good defaults for a browser light client. -pub async fn browser_configuration(chain_spec: GenericChainSpec) - -> Result> +pub async fn browser_configuration( + chain_spec: GenericChainSpec, + telemetries: sc_telemetry::Telemetries, +) -> Result> where G: RuntimeGenesis + 'static, E: Extension + 'static + Send + Sync, @@ -68,8 +89,7 @@ where async {} }).into(), telemetry_external_transport: Some(transport), - // TODO if telemetry is possible here then we need to call sc_cli::init_logger somehow - telemetries: Default::default(), + telemetries, role: Role::Light, database: { info!("Opening Indexed DB database '{}'...", name); From 295a18e1b95ca8472b50dadab620024c7ee9ddbc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 6 Nov 2020 13:51:29 +0100 Subject: [PATCH 039/222] Use proper FormatEvent in the browser --- Cargo.lock | 13 +- client/service/Cargo.toml | 3 + client/service/src/logging.rs | 229 ++++++++++++++++++++++++++++++---- utils/browser/Cargo.toml | 1 - utils/browser/src/lib.rs | 4 - 5 files changed, 211 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 621aabde752ee..e311f97ffaed9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7406,6 +7406,7 @@ dependencies = [ "tracing-futures", "tracing-log", "tracing-subscriber", + "wasm-bindgen", "wasm-timer", ] @@ -8842,7 +8843,6 @@ dependencies = [ "sp-database", "tracing", "tracing-subscriber", - "tracing-wasm", "wasm-bindgen", "wasm-bindgen-futures", ] @@ -9663,17 +9663,6 @@ dependencies = [ "tracing-serde", ] -[[package]] -name = "tracing-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd96394d3d2f119de6c1078fa065b99217db4377f9aac6e87f8393276a0d7962" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - [[package]] name = "treeline" version = "0.1.0" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index a207a305c20d4..a70d7a1a5b50e 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -87,6 +87,9 @@ parity-util-mem = { version = "0.7.0", default-features = false, features = ["pr tempfile = "3.1.0" directories = "2.0.2" +[target.'cfg(target_os = "unknown")'.dependencies] +wasm-bindgen = "0.2.67" + [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime/" } diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index c01f145aef2da..15339d507617a 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -19,24 +19,42 @@ //! TODO doc use ansi_term::Colour; -use std::fmt; +use std::{fmt, marker::PhantomData, cell::RefCell}; use tracing::{span::Attributes, Event, Id, Level, Subscriber}; use tracing_log::NormalizeEvent; use tracing_subscriber::{ filter::Directive, + field::RecordFields, fmt::{ - time::{ChronoLocal, FormatTime, SystemTime}, + format, time::{ChronoLocal, FormatTime, SystemTime}, FmtContext, FormatEvent, FormatFields, }, layer::{Context, SubscriberExt}, - registry::LookupSpan, + registry::{LookupSpan, SpanRef}, FmtSubscriber, Layer, }; +#[cfg(target_os = "unknown")] +use wasm_bindgen::prelude::*; /// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; +#[cfg(target_os = "unknown")] +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console, js_name = error)] + fn error(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = warn)] + fn warn(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = info)] + fn info(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = log)] + fn log(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = debug)] + fn debug(message: &str); +} + /// TODO doc pub struct EventFormat { /// TODO doc @@ -51,22 +69,23 @@ pub struct EventFormat { pub display_thread_name: bool, } -// NOTE: the following code took inspiration from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 -impl FormatEvent for EventFormat +impl EventFormat where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, T: FormatTime, { - fn format_event( + // NOTE: the following code took inspiration from tracing-subscriber + // + // https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 + fn format_event_custom<'b, S, N>( &self, - ctx: &FmtContext, + ctx: CustomFmtContext<'b, S, N>, writer: &mut dyn fmt::Write, event: &Event, - ) -> fmt::Result { - write!(writer, "############# boo"); + ) -> fmt::Result + where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, + { if event.metadata().target() == sc_telemetry::TELEMETRY_LOG_SPAN { return Ok(()); } @@ -113,6 +132,25 @@ where } } +// NOTE: the following code took inspiration from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 +impl FormatEvent for EventFormat +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, + T: FormatTime, +{ + fn format_event( + &self, + ctx: &FmtContext, + writer: &mut dyn fmt::Write, + event: &Event, + ) -> fmt::Result { + self.format_event_custom(CustomFmtContext::FmtContext(ctx), writer, event) + } +} + /// TODO doc pub struct NodeNameLayer; @@ -283,6 +321,140 @@ mod time { } } +struct ConsoleLogLayer { + event_format: EventFormat, + fmt_fields: N, + _inner: PhantomData, +} + +impl ConsoleLogLayer { + fn new(event_format: EventFormat) -> Self { + Self { + event_format, + fmt_fields: format::DefaultFields::default(), + _inner: PhantomData, + } + } +} + +// NOTE: the following code took inspiration from `EventFormat` (in this file) +impl ConsoleLogLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + fn format_event( + &self, + ctx: &Context<'_, S>, + writer: &mut dyn fmt::Write, + event: &Event, + ) -> fmt::Result { + self.event_format.format_event_custom( + CustomFmtContext::ContextWithFormatFields(ctx, &self.fmt_fields), + writer, + event, + ) + } +} + +// NOTE: the following code took inspiration from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L717 +impl Layer for ConsoleLogLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'writer> FormatFields<'writer> + 'static, + T: FormatTime + 'static, +{ + + fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { + thread_local! { + static BUF: RefCell = RefCell::new(String::new()); + } + + BUF.with(|buf| { + let borrow = buf.try_borrow_mut(); + let mut a; + let mut b; + let mut buf = match borrow { + Ok(buf) => { + a = buf; + &mut *a + } + _ => { + b = String::new(); + &mut b + } + }; + + if self.format_event(&ctx, &mut buf, event).is_ok() { + if !buf.is_empty() { + let meta = event.metadata(); + let level = meta.level(); + // NOTE: the following code took inspiration from tracing-subscriber + // + // https://github.com/iamcodemaker/console_log/blob/f13b5d6755/src/lib.rs#L149 + match *level { + Level::ERROR => error(&buf), + Level::WARN => warn(&buf), + Level::INFO => info(&buf), + Level::DEBUG => log(&buf), + Level::TRACE => debug(&buf), + } + } + } + + buf.clear(); + }); + } +} + +// NOTE: `FmtContext`'s fields are private. This enum allows us to make a `format_event` function +// that works with `FmtContext` or `Context` with `FormatFields` +enum CustomFmtContext<'a, S, N> +{ + FmtContext(&'a FmtContext<'a, S, N>), + ContextWithFormatFields(&'a Context<'a, S>, &'a N), +} + +impl<'a, S, N> FormatFields<'a> for CustomFmtContext<'a, S, N> +where + S: Subscriber + for<'lookup> LookupSpan<'lookup>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + fn format_fields( + &self, + writer: &'a mut dyn fmt::Write, + fields: R, + ) -> fmt::Result { + match self { + CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.format_fields(writer, fields), + CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) => + fmt_fields.format_fields(writer, fields), + } + } +} + +// NOTE: the following code has been duplicated from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L788 +impl<'a, S, N> CustomFmtContext<'a, S, N> +where + S: Subscriber + for<'lookup> LookupSpan<'lookup>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + #[inline] + pub fn lookup_current(&self) -> Option> + where + S: for<'lookup> LookupSpan<'lookup>, + { + match self { + CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.lookup_current(), + CustomFmtContext::ContextWithFormatFields(ctx, _) => ctx.lookup_current(), + } + } +} + /// Initialize the global logger TODO update doc /// /// This sets various global logging and tracing instances and thus may only be called once. @@ -377,20 +549,33 @@ fn get_default_subscriber_and_telemetries_internal( let telemetry_layer = sc_telemetry::TelemetryLayer::new(telemetry_external_transport); let telemetries = telemetry_layer.telemetries(); - let subscriber = FmtSubscriber::builder() + let event_format = EventFormat { + timer, + ansi: enable_color, + display_target: !simple, + display_level: !simple, + display_thread_name: !simple, + }; + let builder = FmtSubscriber::builder() .with_env_filter(env_filter) - .with_writer(std::io::stderr) - .event_format(EventFormat { - timer, - ansi: enable_color, - display_target: !simple, - display_level: !simple, - display_thread_name: !simple, - }) + .with_writer( + #[cfg(not(target_os = "unknown"))] + std::io::stderr, + #[cfg(target_os = "unknown")] + std::io::sink, + ); + + #[cfg(not(target_os = "unknown"))] + let builder = builder.event_format(event_format); + + let subscriber = builder .finish() .with(NodeNameLayer) .with(telemetry_layer); + #[cfg(target_os = "unknown")] + let subscriber = subscriber.with(ConsoleLogLayer::new(event_format)); + Ok((subscriber, telemetries)) } diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index c806ae7566a26..92de6c18cf093 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -19,7 +19,6 @@ log = "0.4.8" libp2p-wasm-ext = { version = "0.23", features = ["websocket"] } console_error_panic_hook = "0.1.6" js-sys = "0.3.34" -tracing-wasm = "0.1.0" tracing = "0.1.10" tracing-subscriber = "0.2.10" wasm-bindgen = "0.2.57" diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 302b08cb93dd1..e09d6e03cc4c6 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -30,7 +30,6 @@ use futures::{ use std::pin::Pin; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; -use tracing_wasm::{WASMLayerConfig, WASMLayer}; use tracing_subscriber::layer::SubscriberExt; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; @@ -44,9 +43,6 @@ pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed any Some(transport), )?; - // TODO telemetry is working but WASMLayer bypasses FormatEvent - let subscriber = subscriber.with(WASMLayer::new(WASMLayerConfig::default())); - tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; From 2f40937a5812aac8abd1bcc837ddc6e02d6bc8d0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 6 Nov 2020 14:35:12 +0100 Subject: [PATCH 040/222] Smol fix --- client/service/src/logging.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index 15339d507617a..b0e451ae5ca9c 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -360,6 +360,7 @@ where // NOTE: the following code took inspiration from tracing-subscriber // // https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L717 +#[cfg(target_os = "unknown")] impl Layer for ConsoleLogLayer where S: Subscriber + for<'a> LookupSpan<'a>, From b17aa9de9e22aa5ec9bd2909ab19bd6cdc8a6982 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 6 Nov 2020 15:18:19 +0100 Subject: [PATCH 041/222] CLEANUP --- Cargo.lock | 10 +++++----- client/service/Cargo.toml | 1 + client/service/src/logging.rs | 13 ++++++++----- utils/browser/Cargo.toml | 1 - utils/browser/src/lib.rs | 1 - 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e311f97ffaed9..923b7eb106f10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2601,9 +2601,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.39" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7" +checksum = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73" dependencies = [ "wasm-bindgen", ] @@ -7408,6 +7408,7 @@ dependencies = [ "tracing-subscriber", "wasm-bindgen", "wasm-timer", + "web-sys", ] [[package]] @@ -8842,7 +8843,6 @@ dependencies = [ "sc-telemetry", "sp-database", "tracing", - "tracing-subscriber", "wasm-bindgen", "wasm-bindgen-futures", ] @@ -10297,9 +10297,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.39" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642" +checksum = "dda38f4e5ca63eda02c059d243aa25b5f35ab98451e518c51612cd0f1bd19a47" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index a70d7a1a5b50e..62e58db117956 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -89,6 +89,7 @@ directories = "2.0.2" [target.'cfg(target_os = "unknown")'.dependencies] wasm-bindgen = "0.2.67" +web-sys = "0.3.44" [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index b0e451ae5ca9c..179987dcbba6d 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -321,12 +321,14 @@ mod time { } } +#[cfg(target_os = "unknown")] struct ConsoleLogLayer { event_format: EventFormat, fmt_fields: N, _inner: PhantomData, } +#[cfg(target_os = "unknown")] impl ConsoleLogLayer { fn new(event_format: EventFormat) -> Self { Self { @@ -338,6 +340,7 @@ impl ConsoleLogLayer { } // NOTE: the following code took inspiration from `EventFormat` (in this file) +#[cfg(target_os = "unknown")] impl ConsoleLogLayer where S: Subscriber + for<'a> LookupSpan<'a>, @@ -396,11 +399,11 @@ where // // https://github.com/iamcodemaker/console_log/blob/f13b5d6755/src/lib.rs#L149 match *level { - Level::ERROR => error(&buf), - Level::WARN => warn(&buf), - Level::INFO => info(&buf), - Level::DEBUG => log(&buf), - Level::TRACE => debug(&buf), + Level::ERROR => web_sys::console::error_1(&JsValue::from(buf.as_str())), + Level::WARN => web_sys::console::warn_1(&JsValue::from(buf.as_str())), + Level::INFO => web_sys::console::info_1(&JsValue::from(buf.as_str())), + Level::DEBUG => web_sys::console::log_1(&JsValue::from(buf.as_str())), + Level::TRACE => web_sys::console::debug_1(&JsValue::from(buf.as_str())), } } } diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 92de6c18cf093..f1e0bd0235af2 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -20,7 +20,6 @@ libp2p-wasm-ext = { version = "0.23", features = ["websocket"] } console_error_panic_hook = "0.1.6" js-sys = "0.3.34" tracing = "0.1.10" -tracing-subscriber = "0.2.10" wasm-bindgen = "0.2.57" wasm-bindgen-futures = "0.4.7" kvdb-web = "0.7" diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index e09d6e03cc4c6..9bed688ef6a7a 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -30,7 +30,6 @@ use futures::{ use std::pin::Pin; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; -use tracing_subscriber::layer::SubscriberExt; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; From a8c6e8cd17d9266003a20844c6d74aa143f9e053 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 10:26:30 +0100 Subject: [PATCH 042/222] Removed Arc> in Telemetries --- client/service/src/logging.rs | 29 +++++++++++++++++------------ client/telemetry/src/layer.rs | 20 +++++--------------- client/telemetry/src/lib.rs | 10 +++++++--- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index 179987dcbba6d..25cd7a8f97ad8 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -43,16 +43,16 @@ pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; #[cfg(target_os = "unknown")] #[wasm_bindgen] extern "C" { - #[wasm_bindgen(js_namespace = console, js_name = error)] - fn error(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = warn)] - fn warn(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = info)] - fn info(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = log)] - fn log(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = debug)] - fn debug(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = error)] + fn error(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = warn)] + fn warn(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = info)] + fn info(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = log)] + fn log(message: &str); + #[wasm_bindgen(js_namespace = console, js_name = debug)] + fn debug(message: &str); } /// TODO doc @@ -551,8 +551,13 @@ fn get_default_subscriber_and_telemetries_internal( "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetry_layer = sc_telemetry::TelemetryLayer::new(telemetry_external_transport); - let telemetries = telemetry_layer.telemetries(); + let telemetries = if let Some(telemetry_external_transport) = telemetry_external_transport { + sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) + } else { + Default::default() + }; + let senders = telemetries.senders(); + let telemetry_layer = sc_telemetry::TelemetryLayer::new(senders); let event_format = EventFormat { timer, ansi: enable_color, diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 8aaf262181ae4..ff6e4f996f7bb 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -29,23 +29,12 @@ use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; #[derive(Debug)] -pub struct TelemetryLayer(Telemetries); +pub struct TelemetryLayer(Senders); impl TelemetryLayer { /// TODO - pub fn new(telemetry_external_transport: Option) -> Self { - if let Some(telemetry_external_transport) = telemetry_external_transport { - Self(Telemetries::with_wasm_external_transport( - telemetry_external_transport, - )) - } else { - Self(Default::default()) - } - } - - /// TODO - pub fn telemetries(&self) -> Telemetries { - self.0.clone() + pub fn new(senders: Senders) -> Self { + Self(senders) } } @@ -66,7 +55,7 @@ where .find(|x| x.name() == TELEMETRY_LOG_SPAN) { let id = span.id().into_u64(); - if let Some(sender) = self.0.senders.0.lock().get_mut(&id) { + if let Some(sender) = (self.0).0.lock().get_mut(&id) { let mut attrs = TelemetryAttrs::new(id); let mut vis = TelemetryAttrsVisitor(&mut attrs); event.record(&mut vis); @@ -153,6 +142,7 @@ pub struct Senders( ); impl Senders { + /// TODO doc pub fn insert(&self, id: u64, sender: mpsc::Sender<(u8, String)>) { self.0 .lock() diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index a7d52f9e3084e..0ba808ce86bcd 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -279,10 +279,10 @@ impl Stream for Telemetry { } /// TODO doc -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default)] pub struct Telemetries { senders: Senders, - node_pool: Arc>, + node_pool: NodePool, wasm_external_transport: Option, } @@ -315,7 +315,7 @@ impl Telemetries { let (telemetry, sender) = Telemetry::new( endpoints.clone(), self.wasm_external_transport.clone(), - Some(&self.node_pool.lock()), + Some(&self.node_pool), ); let id = telemetry.span.id().expect("the span is enabled; qed").into_u64(); @@ -323,6 +323,10 @@ impl Telemetries { telemetry } + + pub fn senders(&self) -> Senders { + self.senders.clone() + } } /// TODO doc From 1b83b6f39c1e9b6428584cd67cebdcb9e066f9be Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 12:17:37 +0100 Subject: [PATCH 043/222] CLEANUP --- client/service/src/logging.rs | 5 +++-- client/telemetry/src/layer.rs | 2 -- client/telemetry/src/lib.rs | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index 25cd7a8f97ad8..69f0166f9486a 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -19,14 +19,14 @@ //! TODO doc use ansi_term::Colour; -use std::{fmt, marker::PhantomData, cell::RefCell}; +use std::fmt; use tracing::{span::Attributes, Event, Id, Level, Subscriber}; use tracing_log::NormalizeEvent; use tracing_subscriber::{ filter::Directive, field::RecordFields, fmt::{ - format, time::{ChronoLocal, FormatTime, SystemTime}, + time::{ChronoLocal, FormatTime, SystemTime}, FmtContext, FormatEvent, FormatFields, }, layer::{Context, SubscriberExt}, @@ -415,6 +415,7 @@ where // NOTE: `FmtContext`'s fields are private. This enum allows us to make a `format_event` function // that works with `FmtContext` or `Context` with `FormatFields` +#[allow(dead_code)] enum CustomFmtContext<'a, S, N> { FmtContext(&'a FmtContext<'a, S, N>), diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index ff6e4f996f7bb..bb799cb18f5d3 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,9 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::Telemetries; use futures::channel::mpsc; -use libp2p::wasm_ext::ExtTransport; use parking_lot::Mutex; use std::collections::HashMap; use std::convert::TryInto; diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 0ba808ce86bcd..2a5ed5f4398a0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -64,11 +64,9 @@ use futures::{channel::mpsc, prelude::*}; use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; -use parking_lot::Mutex; use serde::{Deserialize, Deserializer, Serialize}; use std::{ pin::Pin, - sync::Arc, task::{Context, Poll}, time::Duration, }; From 66a2db9f370388dc7089c6b9e5ce6022bde61f80 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 12:59:07 +0100 Subject: [PATCH 044/222] browser: share transport instance --- bin/node/cli/src/browser.rs | 4 ++-- client/service/src/logging.rs | 16 ++++++++++------ utils/browser/src/lib.rs | 10 +++++----- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 4451a39e2e665..e1062f11c0f3a 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,14 +34,14 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_level: String) -> Result> { set_console_error_panic_hook(); - let telemetries = init_console_log(log_level.as_str())?; + let (telemetries, transport) = init_console_log(log_level.as_str())?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, telemetries).await?; + let mut config = browser_configuration(chain_spec, telemetries, transport).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_string(), 10)]).unwrap()); info!("Substrate browser node"); diff --git a/client/service/src/logging.rs b/client/service/src/logging.rs index 69f0166f9486a..e557317f164b2 100644 --- a/client/service/src/logging.rs +++ b/client/service/src/logging.rs @@ -322,19 +322,23 @@ mod time { } #[cfg(target_os = "unknown")] -struct ConsoleLogLayer { +struct ConsoleLogLayer< + S, + N = tracing_subscriber::fmt::format::DefaultFields, + T = SystemTime, +> { event_format: EventFormat, fmt_fields: N, - _inner: PhantomData, + _inner: std::marker::PhantomData, } #[cfg(target_os = "unknown")] -impl ConsoleLogLayer { +impl ConsoleLogLayer { fn new(event_format: EventFormat) -> Self { Self { event_format, - fmt_fields: format::DefaultFields::default(), - _inner: PhantomData, + fmt_fields: Default::default(), + _inner: std::marker::PhantomData, } } } @@ -373,7 +377,7 @@ where fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { thread_local! { - static BUF: RefCell = RefCell::new(String::new()); + static BUF: std::cell::RefCell = std::cell::RefCell::new(String::new()); } BUF.with(|buf| { diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 9bed688ef6a7a..5bcd1b60bfdec 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -34,18 +34,18 @@ use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// TODO doc -pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed anymore I think */) -> Result { - // TODO move to lazy static? +// TODO should probably renamed to "init()"? +pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed anymore I think */) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries( pattern, - Some(transport), + Some(transport.clone()), )?; tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok(telemetries) + Ok((telemetries, transport)) } /// Create a service configuration from a chain spec. @@ -54,6 +54,7 @@ pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed any pub async fn browser_configuration( chain_spec: GenericChainSpec, telemetries: sc_telemetry::Telemetries, + transport: ExtTransport, ) -> Result> where G: RuntimeGenesis + 'static, @@ -61,7 +62,6 @@ where { let name = chain_spec.name().to_string(); - let transport = ExtTransport::new(ffi::websocket_transport()); let mut network = NetworkConfiguration::new( format!("{} (Browser)", name), "unknown", From 0320c95e84092ed6ae28f2d33f17932eb9bccfe2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 13:44:46 +0100 Subject: [PATCH 045/222] Telemetries still need to be clonable to pass it to other nodes --- client/{service/src/logging.rs => logging/src/lib.rs} | 0 client/telemetry/src/lib.rs | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename client/{service/src/logging.rs => logging/src/lib.rs} (100%) diff --git a/client/service/src/logging.rs b/client/logging/src/lib.rs similarity index 100% rename from client/service/src/logging.rs rename to client/logging/src/lib.rs diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2a5ed5f4398a0..b2701c531625c 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -67,6 +67,7 @@ use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ pin::Pin, + sync::Arc, task::{Context, Poll}, time::Duration, }; @@ -277,10 +278,10 @@ impl Stream for Telemetry { } /// TODO doc -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Telemetries { senders: Senders, - node_pool: NodePool, + node_pool: Arc, wasm_external_transport: Option, } From 76f12bb32740d614ab9208c4f8b0843f30c84365 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 14:03:27 +0100 Subject: [PATCH 046/222] Move logging.rs to its own crate sc-logging --- Cargo.lock | 17 +++++++++++++++++ Cargo.toml | 1 + client/cli/Cargo.toml | 1 + client/cli/src/lib.rs | 6 +++--- client/logging/Cargo.toml | 27 +++++++++++++++++++++++++++ client/logging/src/lib.rs | 15 --------------- client/service/src/lib.rs | 1 - utils/browser/Cargo.toml | 1 + utils/browser/src/lib.rs | 2 +- 9 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 client/logging/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 923b7eb106f10..3ce8265694134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6524,6 +6524,7 @@ dependencies = [ "sc-cli-proc-macro", "sc-client-api", "sc-keystore", + "sc-logging", "sc-network", "sc-service", "sc-telemetry", @@ -7085,6 +7086,21 @@ dependencies = [ "sp-state-machine", ] +[[package]] +name = "sc-logging" +version = "2.0.0" +dependencies = [ + "ansi_term 0.12.1", + "atty", + "sc-telemetry", + "sc-tracing", + "tracing", + "tracing-log", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "sc-network" version = "0.8.0" @@ -8838,6 +8854,7 @@ dependencies = [ "rand 0.7.3", "sc-chain-spec", "sc-informant", + "sc-logging", "sc-network", "sc-service", "sc-telemetry", diff --git a/Cargo.toml b/Cargo.toml index b78c4da055801..cf39650ce0092 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ members = [ "client/finality-grandpa", "client/informant", "client/light", + "client/logging", "client/tracing", "client/keystore", "client/network", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index d2682d7dbf12a..d4bd31c55d317 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -36,6 +36,7 @@ sp-core = { version = "2.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.8.0", path = "../../primitives/keystore" } sc-service = { version = "0.8.0", default-features = false, path = "../service" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sc-logging = { version = "2.0.0", path = "../logging" } sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } names = "0.11.0" structopt = "0.3.8" diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 2f4d5303d9b0f..7ab6168467347 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -50,7 +50,7 @@ use structopt::{ pub use tracing; /// TODO used by the macro -pub use sc_service::logging::PREFIX_LOG_SPAN; +pub use sc_logging::PREFIX_LOG_SPAN; /// Substrate client CLI /// @@ -244,7 +244,7 @@ pub fn init_logger( telemetry_external_transport: Option, ) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { - let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries_with_profiling( + let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries_with_profiling( pattern, telemetry_external_transport, tracing_receiver, @@ -259,7 +259,7 @@ pub fn init_logger( telemetries } else { - let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( pattern, telemetry_external_transport, )?; diff --git a/client/logging/Cargo.toml b/client/logging/Cargo.toml new file mode 100644 index 0000000000000..b76289daa5f4d --- /dev/null +++ b/client/logging/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sc-logging" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate CLI interface." +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +documentation = "https://docs.rs/sc-logging" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +ansi_term = "0.12.1" +atty = "0.2.13" +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sc-tracing = { version = "2.0.0", path = "../tracing" } +tracing = "0.1.19" +tracing-log = "0.1.1" +tracing-subscriber = "0.2.10" + +[target.'cfg(target_os = "unknown")'.dependencies] +wasm-bindgen = "0.2.67" +web-sys = "0.3.44" diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index e557317f164b2..b1f67f12fae5c 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -40,21 +40,6 @@ use wasm_bindgen::prelude::*; /// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; -#[cfg(target_os = "unknown")] -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_namespace = console, js_name = error)] - fn error(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = warn)] - fn warn(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = info)] - fn info(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = log)] - fn log(message: &str); - #[wasm_bindgen(js_namespace = console, js_name = debug)] - fn debug(message: &str); -} - /// TODO doc pub struct EventFormat { /// TODO doc diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 54531996e1c09..5183af9ccd889 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -33,7 +33,6 @@ pub mod client; #[cfg(not(feature = "test-helpers"))] mod client; mod task_manager; -pub mod logging; use std::{io, pin::Pin}; use std::net::SocketAddr; diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index f1e0bd0235af2..aabbd8187c6db 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -29,6 +29,7 @@ sc-service = { version = "0.8.0", path = "../../client/service", default-feature sc-network = { path = "../../client/network", version = "0.8.0"} sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0"} sc-telemetry = { path = "../../client/telemetry", version = "2.0.0"} +sc-logging = { path = "../../client/logging", version = "2.0.0"} # Imported just for the `wasm-bindgen` feature rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 5bcd1b60bfdec..8b02ce96a58fb 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -37,7 +37,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; // TODO should probably renamed to "init()"? pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed anymore I think */) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); - let (subscriber, telemetries) = sc_service::logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( pattern, Some(transport.clone()), )?; From 12b7d528f516baab050c1010061097d6a673e040 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 14:33:48 +0100 Subject: [PATCH 047/222] Split module to pieces RIP --- client/logging/Cargo.toml | 2 +- client/logging/src/event_format.rs | 284 ++++++++++++++ client/logging/src/layers/console_log.rs | 123 ++++++ client/logging/src/layers/mod.rs | 25 ++ client/logging/src/layers/prefix_layer.rs | 87 +++++ client/logging/src/lib.rs | 433 +--------------------- 6 files changed, 530 insertions(+), 424 deletions(-) create mode 100644 client/logging/src/event_format.rs create mode 100644 client/logging/src/layers/console_log.rs create mode 100644 client/logging/src/layers/mod.rs create mode 100644 client/logging/src/layers/prefix_layer.rs diff --git a/client/logging/Cargo.toml b/client/logging/Cargo.toml index b76289daa5f4d..d2d1d62315b62 100644 --- a/client/logging/Cargo.toml +++ b/client/logging/Cargo.toml @@ -24,4 +24,4 @@ tracing-subscriber = "0.2.10" [target.'cfg(target_os = "unknown")'.dependencies] wasm-bindgen = "0.2.67" -web-sys = "0.3.44" +web-sys = { version = "0.3.44", features = ["console"] } diff --git a/client/logging/src/event_format.rs b/client/logging/src/event_format.rs new file mode 100644 index 0000000000000..4ed81355dcff3 --- /dev/null +++ b/client/logging/src/event_format.rs @@ -0,0 +1,284 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use ansi_term::Colour; +use std::fmt; +use tracing::{Event, Level, Subscriber}; +use tracing_log::NormalizeEvent; +use tracing_subscriber::{ + field::RecordFields, + fmt::{ + time::{FormatTime, SystemTime}, + FmtContext, FormatEvent, FormatFields, + }, + layer::{Context}, + registry::{LookupSpan, SpanRef}, +}; + +/// TODO doc +pub struct EventFormat { + /// TODO doc + pub timer: T, + /// TODO doc + pub ansi: bool, + /// TODO doc + pub display_target: bool, + /// TODO doc + pub display_level: bool, + /// TODO doc + pub display_thread_name: bool, +} + +impl EventFormat +where + T: FormatTime, +{ + // NOTE: the following code took inspiration from tracing-subscriber + // + // https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 + pub(crate) fn format_event_custom<'b, S, N>( + &self, + ctx: CustomFmtContext<'b, S, N>, + writer: &mut dyn fmt::Write, + event: &Event, + ) -> fmt::Result + where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, + { + if event.metadata().target() == sc_telemetry::TELEMETRY_LOG_SPAN { + return Ok(()); + } + + let normalized_meta = event.normalized_metadata(); + let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); + time::write(&self.timer, writer, self.ansi)?; + + if self.display_level { + let fmt_level = { FmtLevel::new(meta.level(), self.ansi) }; + write!(writer, "{} ", fmt_level)?; + } + + if self.display_thread_name { + let current_thread = std::thread::current(); + match current_thread.name() { + Some(name) => { + write!(writer, "{} ", FmtThreadName::new(name))?; + } + // fall-back to thread id when name is absent and ids are not enabled + None => { + write!(writer, "{:0>2?} ", current_thread.id())?; + } + } + } + + // Custom code to display node name + if let Some(span) = ctx.lookup_current() { + let parents = span.parents(); + for span in std::iter::once(span).chain(parents) { + let exts = span.extensions(); + if let Some(prefix) = exts.get::() { + write!(writer, "{}", prefix.as_str())?; + break; + } + } + } + + if self.display_target { + write!(writer, "{}:", meta.target())?; + } + ctx.format_fields(writer, event)?; + writeln!(writer) + } +} + +// NOTE: the following code took inspiration from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 +impl FormatEvent for EventFormat +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, + T: FormatTime, +{ + fn format_event( + &self, + ctx: &FmtContext, + writer: &mut dyn fmt::Write, + event: &Event, + ) -> fmt::Result { + self.format_event_custom(CustomFmtContext::FmtContext(ctx), writer, event) + } +} + +struct FmtLevel<'a> { + level: &'a Level, + ansi: bool, +} + +impl<'a> FmtLevel<'a> { + pub(crate) fn new(level: &'a Level, ansi: bool) -> Self { + Self { level, ansi } + } +} + +const TRACE_STR: &str = "TRACE"; +const DEBUG_STR: &str = "DEBUG"; +const INFO_STR: &str = " INFO"; +const WARN_STR: &str = " WARN"; +const ERROR_STR: &str = "ERROR"; + +impl<'a> fmt::Display for FmtLevel<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.ansi { + match *self.level { + Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)), + Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)), + Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)), + Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)), + Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)), + } + } else { + match *self.level { + Level::TRACE => f.pad(TRACE_STR), + Level::DEBUG => f.pad(DEBUG_STR), + Level::INFO => f.pad(INFO_STR), + Level::WARN => f.pad(WARN_STR), + Level::ERROR => f.pad(ERROR_STR), + } + } + } +} + +struct FmtThreadName<'a> { + name: &'a str, +} + +impl<'a> FmtThreadName<'a> { + pub(crate) fn new(name: &'a str) -> Self { + Self { name } + } +} + +// NOTE: the following code has been duplicated from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L845 +impl<'a> fmt::Display for FmtThreadName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use std::sync::atomic::{ + AtomicUsize, + Ordering::{AcqRel, Acquire, Relaxed}, + }; + + // Track the longest thread name length we've seen so far in an atomic, + // so that it can be updated by any thread. + static MAX_LEN: AtomicUsize = AtomicUsize::new(0); + let len = self.name.len(); + // Snapshot the current max thread name length. + let mut max_len = MAX_LEN.load(Relaxed); + + while len > max_len { + // Try to set a new max length, if it is still the value we took a + // snapshot of. + match MAX_LEN.compare_exchange(max_len, len, AcqRel, Acquire) { + // We successfully set the new max value + Ok(_) => break, + // Another thread set a new max value since we last observed + // it! It's possible that the new length is actually longer than + // ours, so we'll loop again and check whether our length is + // still the longest. If not, we'll just use the newer value. + Err(actual) => max_len = actual, + } + } + + // pad thread name using `max_len` + write!(f, "{:>width$}", self.name, width = max_len) + } +} + +// NOTE: the following code has been duplicated from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/time/mod.rs#L252 +mod time { + use ansi_term::Style; + use std::fmt; + use tracing_subscriber::fmt::time::FormatTime; + + pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result + where + T: FormatTime, + { + if with_ansi { + let style = Style::new().dimmed(); + write!(writer, "{}", style.prefix())?; + timer.format_time(writer)?; + write!(writer, "{}", style.suffix())?; + } else { + timer.format_time(writer)?; + } + writer.write_char(' ')?; + Ok(()) + } +} + +// NOTE: `FmtContext`'s fields are private. This enum allows us to make a `format_event` function +// that works with `FmtContext` or `Context` with `FormatFields` +#[allow(dead_code)] +pub(crate) enum CustomFmtContext<'a, S, N> +{ + FmtContext(&'a FmtContext<'a, S, N>), + ContextWithFormatFields(&'a Context<'a, S>, &'a N), +} + +impl<'a, S, N> FormatFields<'a> for CustomFmtContext<'a, S, N> +where + S: Subscriber + for<'lookup> LookupSpan<'lookup>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + fn format_fields( + &self, + writer: &'a mut dyn fmt::Write, + fields: R, + ) -> fmt::Result { + match self { + CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.format_fields(writer, fields), + CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) => + fmt_fields.format_fields(writer, fields), + } + } +} + +// NOTE: the following code has been duplicated from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L788 +impl<'a, S, N> CustomFmtContext<'a, S, N> +where + S: Subscriber + for<'lookup> LookupSpan<'lookup>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + #[inline] + pub fn lookup_current(&self) -> Option> + where + S: for<'lookup> LookupSpan<'lookup>, + { + match self { + CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.lookup_current(), + CustomFmtContext::ContextWithFormatFields(ctx, _) => ctx.lookup_current(), + } + } +} diff --git a/client/logging/src/layers/console_log.rs b/client/logging/src/layers/console_log.rs new file mode 100644 index 0000000000000..60f06e439cba5 --- /dev/null +++ b/client/logging/src/layers/console_log.rs @@ -0,0 +1,123 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::event_format::{EventFormat, CustomFmtContext}; +use std::fmt; +use tracing::{Event, Level, Subscriber}; +use tracing_subscriber::{ + fmt::{ + time::{FormatTime, SystemTime}, + FormatFields, + }, + layer::{Context}, + registry::{LookupSpan}, + Layer, +}; +use wasm_bindgen::prelude::*; + +pub struct ConsoleLogLayer< + S, + N = tracing_subscriber::fmt::format::DefaultFields, + T = SystemTime, +> { + event_format: EventFormat, + fmt_fields: N, + _inner: std::marker::PhantomData, +} + +impl ConsoleLogLayer { + pub fn new(event_format: EventFormat) -> Self { + Self { + event_format, + fmt_fields: Default::default(), + _inner: std::marker::PhantomData, + } + } +} + +// NOTE: the following code took inspiration from `EventFormat` (in this file) +impl ConsoleLogLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'writer> FormatFields<'writer> + 'static, +{ + fn format_event( + &self, + ctx: &Context<'_, S>, + writer: &mut dyn fmt::Write, + event: &Event, + ) -> fmt::Result { + self.event_format.format_event_custom( + CustomFmtContext::ContextWithFormatFields(ctx, &self.fmt_fields), + writer, + event, + ) + } +} + +// NOTE: the following code took inspiration from tracing-subscriber +// +// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L717 +impl Layer for ConsoleLogLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'writer> FormatFields<'writer> + 'static, + T: FormatTime + 'static, +{ + + fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { + thread_local! { + static BUF: std::cell::RefCell = std::cell::RefCell::new(String::new()); + } + + BUF.with(|buf| { + let borrow = buf.try_borrow_mut(); + let mut a; + let mut b; + let mut buf = match borrow { + Ok(buf) => { + a = buf; + &mut *a + } + _ => { + b = String::new(); + &mut b + } + }; + + if self.format_event(&ctx, &mut buf, event).is_ok() { + if !buf.is_empty() { + let meta = event.metadata(); + let level = meta.level(); + // NOTE: the following code took inspiration from tracing-subscriber + // + // https://github.com/iamcodemaker/console_log/blob/f13b5d6755/src/lib.rs#L149 + match *level { + Level::ERROR => web_sys::console::error_1(&JsValue::from(buf.as_str())), + Level::WARN => web_sys::console::warn_1(&JsValue::from(buf.as_str())), + Level::INFO => web_sys::console::info_1(&JsValue::from(buf.as_str())), + Level::DEBUG => web_sys::console::log_1(&JsValue::from(buf.as_str())), + Level::TRACE => web_sys::console::debug_1(&JsValue::from(buf.as_str())), + } + } + } + + buf.clear(); + }); + } +} diff --git a/client/logging/src/layers/mod.rs b/client/logging/src/layers/mod.rs new file mode 100644 index 0000000000000..c35a3fb2f7680 --- /dev/null +++ b/client/logging/src/layers/mod.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +mod prefix_layer; +#[cfg(target_os = "unknown")] +mod console_log; + +pub use prefix_layer::*; +#[cfg(target_os = "unknown")] +pub use console_log::*; diff --git a/client/logging/src/layers/prefix_layer.rs b/client/logging/src/layers/prefix_layer.rs new file mode 100644 index 0000000000000..97e2ebe56fe99 --- /dev/null +++ b/client/logging/src/layers/prefix_layer.rs @@ -0,0 +1,87 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use tracing::{span::Attributes, Id, Subscriber}; +use tracing_subscriber::{ + layer::{Context}, + registry::{LookupSpan}, + Layer, +}; + +/// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` +pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; + +/// TODO doc +pub struct PrefixLayer; + +impl Layer for PrefixLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { + let span = ctx + .span(id) + .expect("new_span has been called for this span; qed"); + + if span.name() != PREFIX_LOG_SPAN { + return; + } + + let mut extensions = span.extensions_mut(); + + if extensions.get_mut::().is_none() { + let mut s = String::new(); + let mut v = PrefixVisitor(&mut s); + attrs.record(&mut v); + + if !s.is_empty() { + let fmt_fields = Prefix(s); + extensions.insert(fmt_fields); + } + } + } +} + +struct PrefixVisitor<'a, W: std::fmt::Write>(&'a mut W); + +macro_rules! write_node_name { + ($method:ident, $type:ty, $format:expr) => { + fn $method(&mut self, field: &tracing::field::Field, value: $type) { + if field.name() == "name" { + write!(self.0, $format, value).expect("no way to return the err; qed"); + } + } + }; +} + +impl<'a, W: std::fmt::Write> tracing::field::Visit for PrefixVisitor<'a, W> { + write_node_name!(record_debug, &dyn std::fmt::Debug, "[{:?}] "); + write_node_name!(record_str, &str, "[{}] "); + write_node_name!(record_i64, i64, "[{}] "); + write_node_name!(record_u64, u64, "[{}] "); + write_node_name!(record_bool, bool, "[{}] "); +} + +#[derive(Debug)] +pub(crate) struct Prefix(String); + +impl Prefix { + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() + } +} diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index b1f67f12fae5c..51d08937604c6 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -18,436 +18,23 @@ //! TODO doc -use ansi_term::Colour; -use std::fmt; -use tracing::{span::Attributes, Event, Id, Level, Subscriber}; -use tracing_log::NormalizeEvent; +mod layers; +mod event_format; + +use tracing::{Subscriber}; use tracing_subscriber::{ filter::Directive, - field::RecordFields, fmt::{ - time::{ChronoLocal, FormatTime, SystemTime}, - FmtContext, FormatEvent, FormatFields, + time::{ChronoLocal}, }, - layer::{Context, SubscriberExt}, - registry::{LookupSpan, SpanRef}, + layer::{SubscriberExt}, + registry::{LookupSpan}, FmtSubscriber, Layer, }; -#[cfg(target_os = "unknown")] -use wasm_bindgen::prelude::*; - -/// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` -pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; - -/// TODO doc -pub struct EventFormat { - /// TODO doc - pub timer: T, - /// TODO doc - pub ansi: bool, - /// TODO doc - pub display_target: bool, - /// TODO doc - pub display_level: bool, - /// TODO doc - pub display_thread_name: bool, -} - -impl EventFormat -where - T: FormatTime, -{ - // NOTE: the following code took inspiration from tracing-subscriber - // - // https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 - fn format_event_custom<'b, S, N>( - &self, - ctx: CustomFmtContext<'b, S, N>, - writer: &mut dyn fmt::Write, - event: &Event, - ) -> fmt::Result - where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, - { - if event.metadata().target() == sc_telemetry::TELEMETRY_LOG_SPAN { - return Ok(()); - } - - let normalized_meta = event.normalized_metadata(); - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - time::write(&self.timer, writer, self.ansi)?; - - if self.display_level { - let fmt_level = { FmtLevel::new(meta.level(), self.ansi) }; - write!(writer, "{} ", fmt_level)?; - } - - if self.display_thread_name { - let current_thread = std::thread::current(); - match current_thread.name() { - Some(name) => { - write!(writer, "{} ", FmtThreadName::new(name))?; - } - // fall-back to thread id when name is absent and ids are not enabled - None => { - write!(writer, "{:0>2?} ", current_thread.id())?; - } - } - } - - // Custom code to display node name - if let Some(span) = ctx.lookup_current() { - let parents = span.parents(); - for span in std::iter::once(span).chain(parents) { - let exts = span.extensions(); - if let Some(node_name) = exts.get::() { - write!(writer, "{}", node_name.as_str())?; - break; - } - } - } - - if self.display_target { - write!(writer, "{}:", meta.target())?; - } - ctx.format_fields(writer, event)?; - writeln!(writer) - } -} - -// NOTE: the following code took inspiration from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449 -impl FormatEvent for EventFormat -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &FmtContext, - writer: &mut dyn fmt::Write, - event: &Event, - ) -> fmt::Result { - self.format_event_custom(CustomFmtContext::FmtContext(ctx), writer, event) - } -} - -/// TODO doc -pub struct NodeNameLayer; - -impl Layer for NodeNameLayer -where - S: Subscriber + for<'a> LookupSpan<'a>, -{ - fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - let span = ctx - .span(id) - .expect("new_span has been called for this span; qed"); - - if span.name() != PREFIX_LOG_SPAN { - return; - } - - let mut extensions = span.extensions_mut(); - - if extensions.get_mut::().is_none() { - let mut s = String::new(); - let mut v = NodeNameVisitor(&mut s); - attrs.record(&mut v); - - if !s.is_empty() { - let fmt_fields = NodeName(s); - extensions.insert(fmt_fields); - } - } - } -} - -struct NodeNameVisitor<'a, W: std::fmt::Write>(&'a mut W); - -macro_rules! write_node_name { - ($method:ident, $type:ty, $format:expr) => { - fn $method(&mut self, field: &tracing::field::Field, value: $type) { - if field.name() == "name" { - write!(self.0, $format, value).expect("no way to return the err; qed"); - } - } - }; -} - -impl<'a, W: std::fmt::Write> tracing::field::Visit for NodeNameVisitor<'a, W> { - write_node_name!(record_debug, &dyn std::fmt::Debug, "[{:?}] "); - write_node_name!(record_str, &str, "[{}] "); - write_node_name!(record_i64, i64, "[{}] "); - write_node_name!(record_u64, u64, "[{}] "); - write_node_name!(record_bool, bool, "[{}] "); -} - -#[derive(Debug)] -struct NodeName(String); - -impl NodeName { - fn as_str(&self) -> &str { - self.0.as_str() - } -} - -struct FmtLevel<'a> { - level: &'a Level, - ansi: bool, -} - -impl<'a> FmtLevel<'a> { - pub(crate) fn new(level: &'a Level, ansi: bool) -> Self { - Self { level, ansi } - } -} - -const TRACE_STR: &str = "TRACE"; -const DEBUG_STR: &str = "DEBUG"; -const INFO_STR: &str = " INFO"; -const WARN_STR: &str = " WARN"; -const ERROR_STR: &str = "ERROR"; -impl<'a> fmt::Display for FmtLevel<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.ansi { - match *self.level { - Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)), - Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)), - Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)), - Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)), - Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)), - } - } else { - match *self.level { - Level::TRACE => f.pad(TRACE_STR), - Level::DEBUG => f.pad(DEBUG_STR), - Level::INFO => f.pad(INFO_STR), - Level::WARN => f.pad(WARN_STR), - Level::ERROR => f.pad(ERROR_STR), - } - } - } -} - -struct FmtThreadName<'a> { - name: &'a str, -} - -impl<'a> FmtThreadName<'a> { - pub(crate) fn new(name: &'a str) -> Self { - Self { name } - } -} - -// NOTE: the following code has been duplicated from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L845 -impl<'a> fmt::Display for FmtThreadName<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use std::sync::atomic::{ - AtomicUsize, - Ordering::{AcqRel, Acquire, Relaxed}, - }; - - // Track the longest thread name length we've seen so far in an atomic, - // so that it can be updated by any thread. - static MAX_LEN: AtomicUsize = AtomicUsize::new(0); - let len = self.name.len(); - // Snapshot the current max thread name length. - let mut max_len = MAX_LEN.load(Relaxed); - - while len > max_len { - // Try to set a new max length, if it is still the value we took a - // snapshot of. - match MAX_LEN.compare_exchange(max_len, len, AcqRel, Acquire) { - // We successfully set the new max value - Ok(_) => break, - // Another thread set a new max value since we last observed - // it! It's possible that the new length is actually longer than - // ours, so we'll loop again and check whether our length is - // still the longest. If not, we'll just use the newer value. - Err(actual) => max_len = actual, - } - } - - // pad thread name using `max_len` - write!(f, "{:>width$}", self.name, width = max_len) - } -} - -// NOTE: the following code has been duplicated from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/time/mod.rs#L252 -mod time { - use ansi_term::Style; - use std::fmt; - use tracing_subscriber::fmt::time::FormatTime; - - pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result - where - T: FormatTime, - { - if with_ansi { - let style = Style::new().dimmed(); - write!(writer, "{}", style.prefix())?; - timer.format_time(writer)?; - write!(writer, "{}", style.suffix())?; - } else { - timer.format_time(writer)?; - } - writer.write_char(' ')?; - Ok(()) - } -} - -#[cfg(target_os = "unknown")] -struct ConsoleLogLayer< - S, - N = tracing_subscriber::fmt::format::DefaultFields, - T = SystemTime, -> { - event_format: EventFormat, - fmt_fields: N, - _inner: std::marker::PhantomData, -} - -#[cfg(target_os = "unknown")] -impl ConsoleLogLayer { - fn new(event_format: EventFormat) -> Self { - Self { - event_format, - fmt_fields: Default::default(), - _inner: std::marker::PhantomData, - } - } -} - -// NOTE: the following code took inspiration from `EventFormat` (in this file) -#[cfg(target_os = "unknown")] -impl ConsoleLogLayer -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - fn format_event( - &self, - ctx: &Context<'_, S>, - writer: &mut dyn fmt::Write, - event: &Event, - ) -> fmt::Result { - self.event_format.format_event_custom( - CustomFmtContext::ContextWithFormatFields(ctx, &self.fmt_fields), - writer, - event, - ) - } -} - -// NOTE: the following code took inspiration from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L717 -#[cfg(target_os = "unknown")] -impl Layer for ConsoleLogLayer -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'writer> FormatFields<'writer> + 'static, - T: FormatTime + 'static, -{ - - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - thread_local! { - static BUF: std::cell::RefCell = std::cell::RefCell::new(String::new()); - } - - BUF.with(|buf| { - let borrow = buf.try_borrow_mut(); - let mut a; - let mut b; - let mut buf = match borrow { - Ok(buf) => { - a = buf; - &mut *a - } - _ => { - b = String::new(); - &mut b - } - }; - - if self.format_event(&ctx, &mut buf, event).is_ok() { - if !buf.is_empty() { - let meta = event.metadata(); - let level = meta.level(); - // NOTE: the following code took inspiration from tracing-subscriber - // - // https://github.com/iamcodemaker/console_log/blob/f13b5d6755/src/lib.rs#L149 - match *level { - Level::ERROR => web_sys::console::error_1(&JsValue::from(buf.as_str())), - Level::WARN => web_sys::console::warn_1(&JsValue::from(buf.as_str())), - Level::INFO => web_sys::console::info_1(&JsValue::from(buf.as_str())), - Level::DEBUG => web_sys::console::log_1(&JsValue::from(buf.as_str())), - Level::TRACE => web_sys::console::debug_1(&JsValue::from(buf.as_str())), - } - } - } - - buf.clear(); - }); - } -} - -// NOTE: `FmtContext`'s fields are private. This enum allows us to make a `format_event` function -// that works with `FmtContext` or `Context` with `FormatFields` -#[allow(dead_code)] -enum CustomFmtContext<'a, S, N> -{ - FmtContext(&'a FmtContext<'a, S, N>), - ContextWithFormatFields(&'a Context<'a, S>, &'a N), -} - -impl<'a, S, N> FormatFields<'a> for CustomFmtContext<'a, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - fn format_fields( - &self, - writer: &'a mut dyn fmt::Write, - fields: R, - ) -> fmt::Result { - match self { - CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.format_fields(writer, fields), - CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) => - fmt_fields.format_fields(writer, fields), - } - } -} - -// NOTE: the following code has been duplicated from tracing-subscriber -// -// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/fmt_layer.rs#L788 -impl<'a, S, N> CustomFmtContext<'a, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - #[inline] - pub fn lookup_current(&self) -> Option> - where - S: for<'lookup> LookupSpan<'lookup>, - { - match self { - CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.lookup_current(), - CustomFmtContext::ContextWithFormatFields(ctx, _) => ctx.lookup_current(), - } - } -} +pub use layers::*; +pub use event_format::*; /// Initialize the global logger TODO update doc /// @@ -569,7 +156,7 @@ fn get_default_subscriber_and_telemetries_internal( let subscriber = builder .finish() - .with(NodeNameLayer) + .with(PrefixLayer) .with(telemetry_layer); #[cfg(target_os = "unknown")] From e49e1810edd90f19e312a5507fb467d5f51eee54 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 14:35:00 +0100 Subject: [PATCH 048/222] rustfmt --- client/logging/src/event_format.rs | 10 ++-- client/logging/src/layers/console_log.rs | 13 ++--- client/logging/src/layers/mod.rs | 4 +- client/logging/src/layers/prefix_layer.rs | 6 +- client/logging/src/lib.rs | 68 ++++++++++++++--------- 5 files changed, 53 insertions(+), 48 deletions(-) diff --git a/client/logging/src/event_format.rs b/client/logging/src/event_format.rs index 4ed81355dcff3..d818ee96ea596 100644 --- a/client/logging/src/event_format.rs +++ b/client/logging/src/event_format.rs @@ -26,7 +26,7 @@ use tracing_subscriber::{ time::{FormatTime, SystemTime}, FmtContext, FormatEvent, FormatFields, }, - layer::{Context}, + layer::Context, registry::{LookupSpan, SpanRef}, }; @@ -239,8 +239,7 @@ mod time { // NOTE: `FmtContext`'s fields are private. This enum allows us to make a `format_event` function // that works with `FmtContext` or `Context` with `FormatFields` #[allow(dead_code)] -pub(crate) enum CustomFmtContext<'a, S, N> -{ +pub(crate) enum CustomFmtContext<'a, S, N> { FmtContext(&'a FmtContext<'a, S, N>), ContextWithFormatFields(&'a Context<'a, S>, &'a N), } @@ -257,8 +256,9 @@ where ) -> fmt::Result { match self { CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.format_fields(writer, fields), - CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) => - fmt_fields.format_fields(writer, fields), + CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) => { + fmt_fields.format_fields(writer, fields) + } } } } diff --git a/client/logging/src/layers/console_log.rs b/client/logging/src/layers/console_log.rs index 60f06e439cba5..0c28ef5dde4d7 100644 --- a/client/logging/src/layers/console_log.rs +++ b/client/logging/src/layers/console_log.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::event_format::{EventFormat, CustomFmtContext}; +use crate::event_format::{CustomFmtContext, EventFormat}; use std::fmt; use tracing::{Event, Level, Subscriber}; use tracing_subscriber::{ @@ -24,17 +24,13 @@ use tracing_subscriber::{ time::{FormatTime, SystemTime}, FormatFields, }, - layer::{Context}, - registry::{LookupSpan}, + layer::Context, + registry::LookupSpan, Layer, }; use wasm_bindgen::prelude::*; -pub struct ConsoleLogLayer< - S, - N = tracing_subscriber::fmt::format::DefaultFields, - T = SystemTime, -> { +pub struct ConsoleLogLayer { event_format: EventFormat, fmt_fields: N, _inner: std::marker::PhantomData, @@ -79,7 +75,6 @@ where N: for<'writer> FormatFields<'writer> + 'static, T: FormatTime + 'static, { - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { thread_local! { static BUF: std::cell::RefCell = std::cell::RefCell::new(String::new()); diff --git a/client/logging/src/layers/mod.rs b/client/logging/src/layers/mod.rs index c35a3fb2f7680..8281570a3607a 100644 --- a/client/logging/src/layers/mod.rs +++ b/client/logging/src/layers/mod.rs @@ -16,10 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -mod prefix_layer; #[cfg(target_os = "unknown")] mod console_log; +mod prefix_layer; -pub use prefix_layer::*; #[cfg(target_os = "unknown")] pub use console_log::*; +pub use prefix_layer::*; diff --git a/client/logging/src/layers/prefix_layer.rs b/client/logging/src/layers/prefix_layer.rs index 97e2ebe56fe99..282c5665f1a61 100644 --- a/client/logging/src/layers/prefix_layer.rs +++ b/client/logging/src/layers/prefix_layer.rs @@ -17,11 +17,7 @@ // along with this program. If not, see . use tracing::{span::Attributes, Id, Subscriber}; -use tracing_subscriber::{ - layer::{Context}, - registry::{LookupSpan}, - Layer, -}; +use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; /// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index 51d08937604c6..979091e08b63a 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -18,23 +18,17 @@ //! TODO doc -mod layers; mod event_format; +mod layers; -use tracing::{Subscriber}; +use tracing::Subscriber; use tracing_subscriber::{ - filter::Directive, - fmt::{ - time::{ChronoLocal}, - }, - layer::{SubscriberExt}, - registry::{LookupSpan}, - FmtSubscriber, - Layer, + filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, registry::LookupSpan, + FmtSubscriber, Layer, }; -pub use layers::*; pub use event_format::*; +pub use layers::*; /// Initialize the global logger TODO update doc /// @@ -42,7 +36,13 @@ pub use event_format::*; pub fn get_default_subscriber_and_telemetries( pattern: &str, telemetry_external_transport: Option, -) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { +) -> std::result::Result< + ( + impl Subscriber + for<'a> LookupSpan<'a>, + sc_telemetry::Telemetries, + ), + String, +> { get_default_subscriber_and_telemetries_internal( parse_directives(pattern), telemetry_external_transport, @@ -57,9 +57,16 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( telemetry_external_transport: Option, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: &str, -) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { +) -> std::result::Result< + ( + impl Subscriber + for<'a> LookupSpan<'a>, + sc_telemetry::Telemetries, + ), + String, +> { let (subscriber, telemetries) = get_default_subscriber_and_telemetries_internal( - parse_directives(pattern).into_iter() + parse_directives(pattern) + .into_iter() .chain(parse_directives(profiling_targets).into_iter()), telemetry_external_transport, )?; @@ -71,20 +78,32 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( fn get_default_subscriber_and_telemetries_internal( extra_directives: impl IntoIterator, telemetry_external_transport: Option, -) -> std::result::Result<(impl Subscriber + for<'a> LookupSpan<'a>, sc_telemetry::Telemetries), String> { +) -> std::result::Result< + ( + impl Subscriber + for<'a> LookupSpan<'a>, + sc_telemetry::Telemetries, + ), + String, +> { if let Err(e) = tracing_log::LogTracer::init() { - return Err(format!( - "Registering Substrate logger failed: {:}!", e - )) + return Err(format!("Registering Substrate logger failed: {:}!", e)); } let mut env_filter = tracing_subscriber::EnvFilter::default() // Disable info logging by default for some modules. .add_directive("ws=off".parse().expect("provided directive is valid")) .add_directive("yamux=off".parse().expect("provided directive is valid")) - .add_directive("cranelift_codegen=off".parse().expect("provided directive is valid")) + .add_directive( + "cranelift_codegen=off" + .parse() + .expect("provided directive is valid"), + ) // Set warn logging by default for some modules. - .add_directive("cranelift_wasm=warn".parse().expect("provided directive is valid")) + .add_directive( + "cranelift_wasm=warn" + .parse() + .expect("provided directive is valid"), + ) .add_directive("hyper=warn".parse().expect("provided directive is valid")) // Enable info for others. .add_directive(tracing_subscriber::filter::LevelFilter::INFO.into()); @@ -154,10 +173,7 @@ fn get_default_subscriber_and_telemetries_internal( #[cfg(not(target_os = "unknown"))] let builder = builder.event_format(event_format); - let subscriber = builder - .finish() - .with(PrefixLayer) - .with(telemetry_layer); + let subscriber = builder.finish().with(PrefixLayer).with(telemetry_layer); #[cfg(target_os = "unknown")] let subscriber = subscriber.with(ConsoleLogLayer::new(event_format)); @@ -172,7 +188,5 @@ fn parse_directives(dirs: impl AsRef) -> Vec { return Default::default(); } - dirs.split(',') - .filter_map(|s| s.parse().ok()) - .collect() + dirs.split(',').filter_map(|s| s.parse().ok()).collect() } From 6416651bf5ddcf158e6bbd76b33eaf30209b5a0d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 15:01:53 +0100 Subject: [PATCH 049/222] Fix tests --- client/cli/src/lib.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 7ab6168467347..98ee7b4e06a4b 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -284,7 +284,12 @@ mod tests { #[test] fn test_logger_filters() { let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; - init_logger(&test_pattern, Default::default(), Default::default()).unwrap(); + init_logger( + &test_pattern, + Default::default(), + Default::default(), + Default::default(), + ).unwrap(); tracing::dispatcher::get_default(|dispatcher| { let test_filter = |target, level| { @@ -343,7 +348,12 @@ mod tests { fn log_something_with_dash_target_name() { if env::var("ENABLE_LOGGING").is_ok() { let test_pattern = "test-target=info"; - init_logger(&test_pattern, Default::default(), Default::default()).unwrap(); + init_logger( + &test_pattern, + Default::default(), + Default::default(), + Default::default(), + ).unwrap(); log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE); } @@ -379,7 +389,12 @@ mod tests { fn prefix_in_log_lines_entrypoint() { if env::var("ENABLE_LOGGING").is_ok() { let test_pattern = "test-target=info"; - init_logger(&test_pattern, Default::default(), Default::default()).unwrap(); + init_logger( + &test_pattern, + Default::default(), + Default::default(), + Default::default(), + ).unwrap(); prefix_in_log_lines_process(); } } From 00f34bdd3f36a3dfe8eddd6c5a7f62b7a762f22e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 15:38:52 +0100 Subject: [PATCH 050/222] Revert "Spawn 2 nodes instead of one" This reverts commit a5c64fda1ed6d41f29126a01b4fe0cc84e16c87e. --- bin/node/cli/src/command.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index d62a71690f36c..f8a0f3f9b3a34 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -73,18 +73,10 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - // TODO revert after test - let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetries.clone()).unwrap(); - let mut task_manager = match config.role { - Role::Light => service::new_light(config).unwrap(), - _ => service::new_full(config).unwrap(), - }; - let task_manager2 = match config2.role { - Role::Light => service::new_light(config2).unwrap(), - _ => service::new_full(config2).unwrap(), - }; - task_manager.add_child(task_manager2); - Ok(task_manager) + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } }) } Some(Subcommand::Inspect(cmd)) => { From 6960f4f58b0dd238a9a8ac80939a1e439aef9456 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 16:06:55 +0100 Subject: [PATCH 051/222] Doc --- client/cli/src/lib.rs | 2 - client/logging/src/event_format.rs | 12 +++--- client/logging/src/layers/prefix_layer.rs | 5 ++- client/logging/src/lib.rs | 2 + client/telemetry/src/layer.rs | 8 +++- client/telemetry/src/lib.rs | 49 +++++++++-------------- client/telemetry/src/worker.rs | 2 + 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 98ee7b4e06a4b..1a56a61d0ad0c 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -48,8 +48,6 @@ use structopt::{ }; #[doc(hidden)] pub use tracing; - -/// TODO used by the macro pub use sc_logging::PREFIX_LOG_SPAN; /// Substrate client CLI diff --git a/client/logging/src/event_format.rs b/client/logging/src/event_format.rs index d818ee96ea596..b03161f3390b3 100644 --- a/client/logging/src/event_format.rs +++ b/client/logging/src/event_format.rs @@ -30,17 +30,17 @@ use tracing_subscriber::{ registry::{LookupSpan, SpanRef}, }; -/// TODO doc +/// A pre-configured event formatter. pub struct EventFormat { - /// TODO doc + /// Use the given timer for log message timestamps. pub timer: T, - /// TODO doc + /// Enable ANSI terminal colors for formatted output. pub ansi: bool, - /// TODO doc + /// Sets whether or not an event's target is displayed. pub display_target: bool, - /// TODO doc + /// Sets whether or not an event's level is displayed. pub display_level: bool, - /// TODO doc + /// Sets whether or not the name of the current thread is displayed when formatting events. pub display_thread_name: bool, } diff --git a/client/logging/src/layers/prefix_layer.rs b/client/logging/src/layers/prefix_layer.rs index 282c5665f1a61..feae8f85f22e0 100644 --- a/client/logging/src/layers/prefix_layer.rs +++ b/client/logging/src/layers/prefix_layer.rs @@ -22,7 +22,10 @@ use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; /// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; -/// TODO doc +/// A `Layer` that captures the prefix span ([`PREFIX_LOG_SPAN`]) which is then used by +/// [`EventFormat`] to prefix the log lines by customizable string. +/// +/// See the macro `sc_cli::prefix_logs_with!` for more details. pub struct PrefixLayer; impl Layer for PrefixLayer diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index 979091e08b63a..62c8c6530638c 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -18,6 +18,8 @@ //! TODO doc +#![warn(missing_docs)] + mod event_format; mod layers; diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index bb799cb18f5d3..696bade3f93c1 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -24,13 +24,15 @@ use std::sync::Arc; use tracing::{Event, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; +/// Span name used to report the telemetry. pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; +/// `Layer` that handles the logs for telemetries. #[derive(Debug)] pub struct TelemetryLayer(Senders); impl TelemetryLayer { - /// TODO + /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. pub fn new(senders: Senders) -> Self { Self(senders) } @@ -134,6 +136,10 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { } } +/// A collection of `futures::channel::mpsc::Sender` with their associated span's ID. +/// +/// This is used by [`TelemetryLayer`] to route the log events to the correct channel based on the +/// span's ID. #[derive(Default, Debug, Clone)] pub struct Senders( Arc>>>>, diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index b2701c531625c..7ddb088852b75 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -106,6 +106,7 @@ fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result) -> Result { let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) @@ -165,13 +166,6 @@ impl Drop for Telemetry { } } -/// TODO update doc as Telemetry isnt clonable anymore -/// Behind the `Mutex` in `Telemetry`. -/// -/// Note that ideally we wouldn't have to make the `Telemetry` cloneable, as that would remove the -/// need for a `Mutex`. However there is currently a weird hack in place in `sc-service` -/// where we extract the telemetry registration so that it continues running during the shutdown -/// process. #[derive(Debug)] struct TelemetryInner { /// Worker for the telemetry. `None` if it failed to initialize. @@ -181,11 +175,7 @@ struct TelemetryInner { } impl Telemetry { - // TODO update doc /// Initializes the telemetry. See the crate root documentation for more information. - /// - /// Please be careful to not call this function twice in the same program. The `slog` crate - /// doesn't provide any way of knowing whether a global logger has already been registered. pub fn new( endpoints: TelemetryEndpoints, wasm_external_transport: Option, @@ -277,7 +267,9 @@ impl Stream for Telemetry { } } -/// TODO doc +/// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. +/// +/// [`Telemetry`] created through this object re-use connections if possible. #[derive(Debug, Default, Clone)] pub struct Telemetries { senders: Senders, @@ -286,7 +278,16 @@ pub struct Telemetries { } impl Telemetries { - /// TODO doc + /// Create a [`Telemetries`] object using an `ExtTransport`. + /// + /// This is used in WASM contexts where we need some binding between the networking provided by + /// the operating system or environment and libp2p. + /// + /// This constructor is expected to be used only when compiling for WASM. + /// + /// > **Important**: Each individual call to `write` corresponds to one message. There is no + /// > internal buffering going on. In the context of WebSockets, each `write` + /// > must be one individual WebSockets frame. pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Self { Self { wasm_external_transport: Some(wasm_external_transport), @@ -294,22 +295,10 @@ impl Telemetries { } } - // TODO update doc / move to root - /// endpoints: - /// - /// Collection of telemetry WebSocket servers with a corresponding verbosity level. - /// Optional external implementation of a libp2p transport. Used in WASM contexts where we need - /// some binding between the networking provided by the operating system or environment and - /// libp2p. - /// - /// wasm_external_transport: - /// - /// This parameter exists whatever the target platform is, but it is expected to be set to - /// `Some` only when compiling for WASM. + /// Create a new [`Telemetry`] for the endpoints provided in argument. /// - /// > **Important**: Each individual call to `write` corresponds to one message. There is no - /// > internal buffering going on. In the context of WebSockets, each `write` - /// > must be one individual WebSockets frame. + /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding + /// verbosity level. pub fn get_or_create(&self, endpoints: TelemetryEndpoints) -> Telemetry { let (telemetry, sender) = Telemetry::new( endpoints.clone(), @@ -323,13 +312,13 @@ impl Telemetries { telemetry } + /// Get a clone of the channel's [`Senders`]. pub fn senders(&self) -> Senders { self.senders.clone() } } -/// TODO doc -/// Translates to `slog_scope::info`, but contains an additional verbosity +/// Translates to `tracing::info!`, but contains an additional verbosity /// parameter which the log record is tagged with. Additionally the verbosity /// parameter is added to the record as a key-value pair. #[macro_export(local_inner_macros)] diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index b4220a58646e1..76e3e3e038c66 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -65,9 +65,11 @@ pub struct TelemetryWorker { force_connected: bool, } +/// A trait that implements `Stream` and `Sink`. pub trait StreamAndSink: Stream + Sink {} impl, I> StreamAndSink for T {} +/// A type alias for the WebSocket transport. pub type WsTrans = libp2p::core::transport::Boxed< Pin, From 07081475a752b739fb841c978f8df1f62b5ace90 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 17:38:17 +0100 Subject: [PATCH 052/222] Replace Vec by Iterator --- client/cli/src/commands/run_cmd.rs | 2 +- client/telemetry/src/lib.rs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 019b760e5b4ae..cfdbd376acaad 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -349,7 +349,7 @@ impl CliConfiguration for RunCmd { None } else if !self.telemetry_endpoints.is_empty() { Some( - TelemetryEndpoints::new(self.telemetry_endpoints.clone()) + TelemetryEndpoints::new(self.telemetry_endpoints.iter()) .map_err(|e| e.to_string())?, ) } else { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 7ddb088852b75..5b3437d4831ca 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -107,11 +107,13 @@ fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result) -> Result { - let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() - .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) - .collect(); - endpoints.map(Self) + pub fn new<'a>( + endpoints: impl Iterator, + ) -> Result { + endpoints + .map(|(url, max_verbosity)| Ok((url_to_multiaddr(&url)?, *max_verbosity))) + .collect::, libp2p::multiaddr::Error>>() + .map(Self) } } From 4b6091c1197b6ef072b3e0fa725fc468728a7428 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 18:21:14 +0100 Subject: [PATCH 053/222] Doc --- client/telemetry/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5b3437d4831ca..11b84bdcf39ab 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -142,13 +142,18 @@ fn url_to_multiaddr(url: &str) -> Result { Err(parse_error) } -/// Log levels. +/// Substrate DEBUG log level. pub const SUBSTRATE_DEBUG: u8 = 9; +/// Substrate INFO log level. pub const SUBSTRATE_INFO: u8 = 0; +/// Consensus TRACE log level. pub const CONSENSUS_TRACE: u8 = 9; +/// Consensus DEBUG log level. pub const CONSENSUS_DEBUG: u8 = 5; +/// Consensus WARN log level. pub const CONSENSUS_WARN: u8 = 4; +/// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; /// Telemetry object. Implements `Future` and must be polled regularly. From fa4265ebcb24baac6750999a9c6acd441a84bf49 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 12 Nov 2020 18:21:41 +0100 Subject: [PATCH 054/222] Revert "Replace Vec by Iterator" This reverts commit 07081475a752b739fb841c978f8df1f62b5ace90. --- client/cli/src/commands/run_cmd.rs | 2 +- client/telemetry/src/lib.rs | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index cfdbd376acaad..019b760e5b4ae 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -349,7 +349,7 @@ impl CliConfiguration for RunCmd { None } else if !self.telemetry_endpoints.is_empty() { Some( - TelemetryEndpoints::new(self.telemetry_endpoints.iter()) + TelemetryEndpoints::new(self.telemetry_endpoints.clone()) .map_err(|e| e.to_string())?, ) } else { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 11b84bdcf39ab..7a9846a8935d0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -107,13 +107,11 @@ fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result( - endpoints: impl Iterator, - ) -> Result { - endpoints - .map(|(url, max_verbosity)| Ok((url_to_multiaddr(&url)?, *max_verbosity))) - .collect::, libp2p::multiaddr::Error>>() - .map(Self) + pub fn new(endpoints: Vec<(String, u8)>) -> Result { + let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() + .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) + .collect(); + endpoints.map(Self) } } From 33268f1b5041cd2057ed7242ac91c50a12ffd698 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 13 Nov 2020 13:41:14 +0100 Subject: [PATCH 055/222] Solving weird bug In polkadot: ---- call_function_actually_work stdout ---- thread 'call_function_actually_work' panicked at 'called `Result::unwrap()` on an `Err` value: RpcTransactionError { code: -32700, message: "Parse error", data: None }', node/test/service/tests/call-function.rs:29:60 Issues related: https://github.com/serde-rs/json/issues/559 https://github.com/serde-rs/serde/issues/773 --- client/rpc-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 0947dc47819cd..156410c1d7a3d 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "1.3.4" } derive_more = "0.99.2" futures = { version = "0.3.1", features = ["compat"] } -jsonrpc-core = "15.1.0" +jsonrpc-core = { version = "15.1.0", features = ["arbitrary_precision"] } jsonrpc-core-client = "15.1.0" jsonrpc-derive = "15.1.0" jsonrpc-pubsub = "15.1.0" From 4522330b096697afc05fc8800df621b804fdb3fd Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 13 Nov 2020 16:07:11 +0100 Subject: [PATCH 056/222] Clever trick taken from jsonrpc-core to circumvent the deserializing issue with u128 --- frame/contracts/rpc/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 6d43ea75c035f..5011caf14465d 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -306,7 +306,7 @@ mod tests { #[test] fn call_request_should_serialize_deserialize_properly() { type Req = CallRequest; - let req: Req = serde_json::from_str(r#" + let value: serde_json::Value = serde_json::from_str(r#" { "origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", "dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom", @@ -315,6 +315,7 @@ mod tests { "inputData": "0x8c97db39" } "#).unwrap(); + let req = Req::deserialize(value).unwrap(); assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64)); } From dc5cfb0755a48629e3b2d9515f25bc315dae5861 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 13 Nov 2020 17:01:24 +0100 Subject: [PATCH 057/222] Same trick to fix serialization issue in tests --- Cargo.lock | 1 + client/finality-grandpa/Cargo.toml | 1 + client/finality-grandpa/rpc/src/lib.rs | 7 +++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa0606df3d832..374cbf930c4a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7005,6 +7005,7 @@ dependencies = [ "sc-network-gossip", "sc-network-test", "sc-telemetry", + "serde", "serde_json", "sp-api", "sp-application-crypto", diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 8966f5e8f657a..c17eabd61f995 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -59,3 +59,4 @@ sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } tokio = { version = "0.2", features = ["rt-core"] } tempfile = "3.1.0" sp-api = { version = "2.0.0", path = "../../primitives/api" } +serde = "1.0.101" diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index 172473ad6518b..c0619e16c4802 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -197,6 +197,7 @@ where #[cfg(test)] mod tests { use super::*; + use serde::Deserialize; use std::{collections::HashSet, convert::TryInto, sync::Arc}; use jsonrpc_core::{Notification, Output, types::Params}; @@ -385,7 +386,8 @@ mod tests { // Subscribe let sub_request = r#"{"jsonrpc":"2.0","method":"grandpa_subscribeJustifications","params":[],"id":1}"#; let resp = io.handle_request_sync(sub_request, meta.clone()); - let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); + let val: serde_json::Value = serde_json::from_str(&resp.unwrap()).unwrap(); + let resp = Output::deserialize(val).unwrap(); let sub_id = match resp { Output::Success(success) => success.result, @@ -417,7 +419,8 @@ mod tests { // Subscribe let sub_request = r#"{"jsonrpc":"2.0","method":"grandpa_subscribeJustifications","params":[],"id":1}"#; let resp = io.handle_request_sync(sub_request, meta.clone()); - let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); + let val: serde_json::Value = serde_json::from_str(&resp.unwrap()).unwrap(); + let resp = Output::deserialize(val).unwrap(); assert!(matches!(resp, Output::Success(_))); // Unsubscribe with wrong ID From 326feb5443418fc01a8df30b090b5322f41a2674 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 13 Nov 2020 17:16:14 +0100 Subject: [PATCH 058/222] Fixing again --- client/telemetry/src/lib.rs | 9 +++++---- primitives/rpc/src/lib.rs | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 7a9846a8935d0..d323316027f76 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -40,14 +40,15 @@ //! ```no_run //! use futures::prelude::*; //! -//! let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { -//! endpoints: sc_telemetry::TelemetryEndpoints::new(vec![ +//! let (telemetry, _sender) = sc_telemetry::Telemetry::new( +//! sc_telemetry::TelemetryEndpoints::new(vec![ //! // The `0` is the maximum verbosity level of messages to send to this endpoint. //! ("wss://example.com".into(), 0) //! ]).expect("Invalid URL or multiaddr provided"), //! // Can be used to pass an external implementation of WebSockets. -//! wasm_external_transport: None, -//! }); +//! None, +//! None, +//! ); //! //! // The `telemetry` object implements `Stream` and must be processed. //! std::thread::spawn(move || { diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index c479f0df8b60e..669ba764b2438 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -27,8 +27,9 @@ pub mod list; pub(crate) fn assert_deser(s: &str, expected: T) where T: std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned + PartialEq { + let val: serde_json::Value = serde_json::from_str(s).unwrap(); assert_eq!( - serde_json::from_str::(s).unwrap(), + T::deserialize(val).unwrap(), expected ); assert_eq!( From deb7c426f0d555e2ffd7fda3a4e5ca364fc80a79 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 12:19:53 +0100 Subject: [PATCH 059/222] Cargo.lock --- Cargo.lock | 223 +++++++++++++++++++++++++++++------------------------ 1 file changed, 121 insertions(+), 102 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df24f4afa5dc2..769d5ea25e24f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,7 +262,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38628c78a34f111c5a6b98fc87dfc056cd1590b61afe748b145be4623c56d194" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "concurrent-queue", "fastrand", "futures-lite", @@ -389,7 +389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 0.1.10", "libc", "miniz_oxide", "object 0.20.0", @@ -438,7 +438,7 @@ checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36" dependencies = [ "bitflags", "cexpr", - "cfg-if", + "cfg-if 0.1.10", "clang-sys", "clap", "env_logger", @@ -605,6 +605,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + [[package]] name = "bstr" version = "0.2.13" @@ -718,6 +724,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chacha20" version = "0.4.3" @@ -827,7 +839,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "wasm-bindgen", ] @@ -977,7 +989,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1034,7 +1046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg 1.0.0", - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils", "lazy_static", "maybe-uninit", @@ -1048,7 +1060,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils", "maybe-uninit", ] @@ -1060,7 +1072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg 1.0.0", - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -1215,7 +1227,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "dirs-sys", ] @@ -1567,7 +1579,7 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crc32fast", "libc", "libz-sys", @@ -2028,7 +2040,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi", "wasm-bindgen", @@ -2040,7 +2052,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi", ] @@ -2848,9 +2860,9 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libp2p" -version = "0.29.1" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021f703bfef6e3da78ef9828c8a244d639b8d57eedf58360922aca5ff69dfdcd" +checksum = "e3c2b4c99f8798be90746fc226acf95d3e6cff0655883634cc30dab1f64f438b" dependencies = [ "atomic", "bytes 0.5.6", @@ -2887,12 +2899,12 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3960524389409633550567e8a9e0684d25a33f4f8408887ff897dd9fdfbdb771" +checksum = "1b8186060d6bd415e4e928e6cb44c4fe7e7a7dd53437bd936ce7e5f421e45a51" dependencies = [ "asn1_der", - "bs58", + "bs58 0.4.0", "ed25519-dalek", "either", "fnv", @@ -2931,9 +2943,9 @@ dependencies = [ [[package]] name = "libp2p-deflate" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567962c5c5f8a1282979441300e1739ba939024010757c3dbfab4d462189df77" +checksum = "34aea69349e70a58ef9ecd21ac12c5eaa36255ac6986828079d26393f9e618cb" dependencies = [ "flate2", "futures 0.3.5", @@ -2942,9 +2954,9 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436280f5fe21a58fcaff82c2606945579241f32bc0eaf2d39321aa4624a66e7f" +checksum = "0baeff71fb5cb1fe1604f74a712a44b66a8c5900f4022411a1d550f09d6bb776" dependencies = [ "futures 0.3.5", "libp2p-core", @@ -2953,9 +2965,9 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc175613c5915332fd6458895407ec242ea055ae3b107a586626d5e3349350a" +checksum = "db0f925a45f310b678e70faf71a10023b829d02eb9cc2628a63de928936f3ade" dependencies = [ "cuckoofilter", "fnv", @@ -2971,9 +2983,9 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d500ad89ba14de4d18bebdff61a0ce3e769f1c5c5a95026c5da90187e5fff5c9" +checksum = "efeb65567174974f551a91f9f5719445b6695cad56f6a7a47a27111f37efb6b8" dependencies = [ "base64 0.13.0", "byteorder", @@ -2997,9 +3009,9 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b90b350e37f398b73d778bd94422f4e6a3afa2c1582742ce2446b8a0dba787" +checksum = "e074124669840484de564901d47f2d0892e73f6d8ee7c37e9c2644af1b217bf4" dependencies = [ "futures 0.3.5", "libp2p-core", @@ -3013,9 +3025,9 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb78341f114bf686d5fe50b33ff1a804d88fb326c0d39ee1c22db4346b21fc27" +checksum = "78a2653b2e3254a3bbeb66bfc3f0dca7d6cba6aa2a96791db114003dec1b5394" dependencies = [ "arrayvec 0.5.1", "bytes 0.5.6", @@ -3040,9 +3052,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b575514fce0a3ccbd065d6aa377bd4d5102001b05c1a22a5eee49c450254ef0f" +checksum = "786b068098794322239f8f04df88a52daeb7863b2e77501c4d85d32e0a8f2d26" dependencies = [ "async-std", "data-encoding", @@ -3062,9 +3074,9 @@ dependencies = [ [[package]] name = "libp2p-mplex" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92b538238c80067c6417a58a07e41002b69d129355b60ec147d6337fdff0eb0" +checksum = "ed764eab613a8fb6b7dcf6c796f55a06fef2270e528329903e25cd3311b99663" dependencies = [ "bytes 0.5.6", "futures 0.3.5", @@ -3080,9 +3092,9 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c77142e3e5b18fefa7d267305c777c9cbe9b2232ec489979390100bebcc1e6" +checksum = "fb441fb015ec16690099c5d910fcba271d357763b3dcb784db7b27bbb0b68372" dependencies = [ "bytes 0.5.6", "curve25519-dalek 3.0.0", @@ -3102,9 +3114,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7257135609e8877f4d286935cbe1e572b2018946881c3e7f63054577074a7ee7" +checksum = "82e5c50936cfdbe96a514e8992f304fa44cd3a681b6f779505f1ae62b3474705" dependencies = [ "futures 0.3.5", "libp2p-core", @@ -3117,9 +3129,9 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c88d59ba3e710a8c8e0535cb4a52e9e46534924cbbea4691f8c3aaad17b58c61" +checksum = "21026557c335d3639591f247b19b7536195772034ec7e9c463137227f95eaaa1" dependencies = [ "bytes 0.5.6", "futures 0.3.5", @@ -3148,9 +3160,9 @@ dependencies = [ [[package]] name = "libp2p-request-response" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02ba1aa5727ccc118c09ba5111480873f2fe5608cb304e258fd12c173ecf27c9" +checksum = "2dd9a1e0e6563dec1c9e702f7e68bdaa43da62a84536aa06372d3fed3e25d4ca" dependencies = [ "async-trait", "bytes 0.5.6", @@ -3168,9 +3180,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa6fa33b16956b8a58afbfebe1406866011a1ab8960765bd36868952d7be6a1" +checksum = "565f0e06674b4033c978471e4083d5aaa8e03cef0719a0ec0905aaeaad39a919" dependencies = [ "either", "futures 0.3.5", @@ -3184,9 +3196,9 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0b6f4ef48d9493607fae069deecce0579320a1f3de6cb056770b151018a9a5" +checksum = "33f3dce259c0d3127af5167f45c275b6c047320efdd0e40fde947482487af0a3" dependencies = [ "async-std", "futures 0.3.5", @@ -3200,9 +3212,9 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945bed3c989a1b290b5a0d4e8fa6e44e01840efb9a5ab3f0d3d174f0e451ac0e" +checksum = "5e0aba04370a00d8d0236e350bc862926c1b42542a169aa6a481e660e5b990fe" dependencies = [ "async-std", "futures 0.3.5", @@ -3212,9 +3224,9 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66518a4455e15c283637b4d7b579aef928b75a3fc6c50a41e7e6b9fa86672ca0" +checksum = "6c703816f4170477a375b49c56d349e535ce68388f81ba1d9a3c8e2517effa82" dependencies = [ "futures 0.3.5", "js-sys", @@ -3226,9 +3238,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc561870477523245efaaea1b6b743c70115f10c670e62bcbbe4d3153be5f0c" +checksum = "8d5e7268a959748040a0cf7456ad655be55b87f0ceda03bdb5b53674726b28f7" dependencies = [ "async-tls", "either", @@ -3246,9 +3258,9 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0c9b6ef7a168c2ae854170b0b6b77550599afe06cc3ac390eb45c5d9c7110" +checksum = "1a0798cbb58535162c40858493d09af06eac42a26e4966e58de0df701f559348" dependencies = [ "futures 0.3.5", "libp2p-core", @@ -3374,7 +3386,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -3511,18 +3523,18 @@ dependencies = [ [[package]] name = "minicbor" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2ef6aa869726518c5d8206fa5d1337bda8a0442807611be617891c018fa781" +checksum = "0164190d1771b1458c3742075b057ed55d25cd9dfb930aade99315a1eb1fe12d" dependencies = [ "minicbor-derive", ] [[package]] name = "minicbor-derive" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3569c0dbfff1b8d5f1434c642b67f5bf81c0f354a3f5f8f180b549dba3c07c" +checksum = "2e071b3159835ee91df62dbdbfdd7ec366b7ea77c838f43aff4acda6b61bcfb9" dependencies = [ "proc-macro2", "quote", @@ -3544,7 +3556,7 @@ version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -3622,17 +3634,17 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "multihash" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75db05d738947aa5389863aadafbcf2e509d7ba099dc2ddcdf4fc66bf7a9e03" +checksum = "567122ab6492f49b59def14ecc36e13e64dca4188196dd0cd41f9f3f979f3df6" dependencies = [ "blake2b_simd", "blake2s_simd", - "digest 0.8.1", - "sha-1", - "sha2 0.8.2", - "sha3 0.8.2", - "unsigned-varint 0.3.3", + "digest 0.9.0", + "sha-1 0.9.2", + "sha2 0.9.1", + "sha3 0.9.1", + "unsigned-varint 0.5.1", ] [[package]] @@ -3643,9 +3655,9 @@ checksum = "d8883adfde9756c1d30b0f519c9b8c502a94b41ac62f696453c37c7fc0a958ce" [[package]] name = "multistream-select" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a6aa6e32fbaf16795142335967214b8564a7a4661eb6dc846ef343a6e00ac1" +checksum = "93faf2e41f9ee62fb01680ed48f3cc26652352327aa2e59869070358f6b7dd75" dependencies = [ "bytes 0.5.6", "futures 0.3.5", @@ -3687,7 +3699,7 @@ version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] @@ -3700,7 +3712,7 @@ checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ "bitflags", "cc", - "cfg-if", + "cfg-if 0.1.10", "libc", "void", ] @@ -5178,12 +5190,12 @@ dependencies = [ [[package]] name = "parity-multiaddr" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7ad66970bbab360c97179b60906e2dc4aef1f7fca8ab4e5c5db8c97b16814a" +checksum = "43244a26dc1ddd3097216bb12eaa6cf8a07b060c72718d9ebd60fd297d6401df" dependencies = [ "arrayref", - "bs58", + "bs58 0.4.0", "byteorder", "data-encoding", "multihash", @@ -5250,7 +5262,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297ff91fa36aec49ce183484b102f6b75b46776822bd81525bfc4cc9b0dd0f5c" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "ethereum-types", "hashbrown 0.8.1", "impl-trait-for-tuples", @@ -5301,7 +5313,7 @@ dependencies = [ "mio", "mio-extras", "rand 0.7.3", - "sha-1", + "sha-1 0.8.2", "slab", "url 2.1.1", ] @@ -5373,7 +5385,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", "redox_syscall", @@ -5388,7 +5400,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", "redox_syscall", @@ -5402,7 +5414,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.1.0", "instant", "libc", @@ -5520,7 +5532,7 @@ checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ "maplit", "pest", - "sha-1", + "sha-1 0.8.2", ] [[package]] @@ -5615,7 +5627,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0720e0b9ea9d52451cf29d3413ba8a9303f8815d9d9653ef70e03ff73e65566" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "log", "wepoll-sys-stjepang", @@ -5637,7 +5649,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9a50142b55ab3ed0e9f68dfb3709f1d90d29da24e91033f28b96330643107dc" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "universal-hash", ] @@ -5760,7 +5772,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d70cf4412832bcac9cffe27906f4a66e450d323525e977168c70d1b36120ae" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fnv", "lazy_static", "parking_lot 0.11.0", @@ -7130,7 +7142,7 @@ dependencies = [ "async-std", "async-trait", "bitflags", - "bs58", + "bs58 0.3.1", "bytes 0.5.6", "derive_more", "either", @@ -7822,6 +7834,19 @@ dependencies = [ "opaque-debug 0.2.3", ] +[[package]] +name = "sha-1" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha2" version = "0.8.2" @@ -7841,7 +7866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 0.1.10", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -7948,7 +7973,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.9", @@ -7967,7 +7992,7 @@ dependencies = [ "httparse", "log", "rand 0.7.3", - "sha-1", + "sha-1 0.8.2", ] [[package]] @@ -8987,7 +9012,7 @@ dependencies = [ name = "substrate-test-runtime" version = "2.0.0" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "frame-executive", "frame-support", "frame-system", @@ -9175,7 +9200,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand 0.7.3", "redox_syscall", @@ -9601,7 +9626,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "log", "pin-project-lite", "tracing-attributes", @@ -9844,12 +9869,6 @@ dependencies = [ "subtle 2.2.3", ] -[[package]] -name = "unsigned-varint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67332660eb59a6f1eb24ff1220c9e8d01738a8503c6002e30bcfe4bd9f2b4a9" - [[package]] name = "unsigned-varint" version = "0.4.0" @@ -9991,7 +10010,7 @@ version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "serde", "serde_json", "wasm-bindgen-macro", @@ -10018,7 +10037,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a369c5e1dfb7569e14d62af4da642a3cbc2f9a3652fe586e26ac22222aa4b04" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "js-sys", "wasm-bindgen", "web-sys", @@ -10148,7 +10167,7 @@ checksum = "1cd3c4f449382779ef6e0a7c3ec6752ae614e20a42e4100000c3efdc973100e2" dependencies = [ "anyhow", "backtrace", - "cfg-if", + "cfg-if 0.1.10", "lazy_static", "libc", "log", @@ -10190,7 +10209,7 @@ dependencies = [ "anyhow", "base64 0.12.3", "bincode", - "cfg-if", + "cfg-if 0.1.10", "cranelift-codegen", "cranelift-entity", "cranelift-frontend", @@ -10219,7 +10238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e914c013c7a9f15f4e429d5431f2830fb8adb56e40567661b69c5ec1d645be23" dependencies = [ "anyhow", - "cfg-if", + "cfg-if 0.1.10", "cranelift-codegen", "cranelift-entity", "cranelift-frontend", @@ -10262,7 +10281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e8d4d1af8dd5f7096cfcc89dd668d358e52980c38cce199643372ffd6590e27" dependencies = [ "anyhow", - "cfg-if", + "cfg-if 0.1.10", "gimli 0.21.0", "lazy_static", "libc", @@ -10282,7 +10301,7 @@ checksum = "3a25f140bbbaadb07c531cba99ce1a966dba216138dc1b2a0ddecec851a01a93" dependencies = [ "backtrace", "cc", - "cfg-if", + "cfg-if 0.1.10", "indexmap", "lazy_static", "libc", From 6fc89f99d5451b01589c809c3d90df0491f5691b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 12:34:40 +0100 Subject: [PATCH 060/222] doc --- client/logging/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index c632b8e8a4efe..a41ed893e9ec3 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -16,7 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! TODO doc +//! Substrate logging library. +//! +//! This crate uses tokio's [tracing](https://github.com/tokio-rs/tracing/) library for logging. #![warn(missing_docs)] From 2f9fcb00035205c71718b1bb9c6bf349a09fa413 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 12:57:44 +0100 Subject: [PATCH 061/222] Move sc-cli-proc-macro to sc-logging-proc-macro --- Cargo.lock | 24 +-- Cargo.toml | 2 +- client/cli/Cargo.toml | 2 - client/cli/src/lib.rs | 162 ------------------ client/logging/Cargo.toml | 4 + client/{cli => logging}/proc-macro/Cargo.toml | 2 +- client/{cli => logging}/proc-macro/src/lib.rs | 8 +- client/logging/src/lib.rs | 157 +++++++++++++++++ 8 files changed, 179 insertions(+), 182 deletions(-) rename client/{cli => logging}/proc-macro/Cargo.toml (94%) rename client/{cli => logging}/proc-macro/src/lib.rs (97%) diff --git a/Cargo.lock b/Cargo.lock index 769d5ea25e24f..389163159edd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6535,7 +6535,6 @@ dependencies = [ name = "sc-cli" version = "0.8.0" dependencies = [ - "ansi_term 0.12.1", "bip39", "chrono", "fdlimit", @@ -6548,7 +6547,6 @@ dependencies = [ "rand 0.7.3", "regex", "rpassword", - "sc-cli-proc-macro", "sc-client-api", "sc-keystore", "sc-logging", @@ -6573,16 +6571,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "sc-cli-proc-macro" -version = "2.0.0" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sc-client-api" version = "2.0.0" @@ -7124,7 +7112,9 @@ dependencies = [ "ansi_term 0.12.1", "atty", "lazy_static", + "log", "regex", + "sc-logging-proc-macro", "sc-telemetry", "sc-tracing", "tracing", @@ -7134,6 +7124,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "sc-logging-proc-macro" +version = "2.0.0" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sc-network" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index cf39650ce0092..0e33213c075e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ members = [ "client/chain-spec", "client/chain-spec/derive", "client/cli", - "client/cli/proc-macro", "client/consensus/aura", "client/consensus/babe", "client/consensus/babe/rpc", @@ -41,6 +40,7 @@ members = [ "client/informant", "client/light", "client/logging", + "client/logging/proc-macro", "client/tracing", "client/keystore", "client/network", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index ba579c4c9094f..7dfe445df5205 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -44,7 +44,6 @@ sc-tracing = { version = "2.0.0", path = "../tracing" } chrono = "0.4.10" serde = "1.0.111" tracing = "0.1.19" -sc-cli-proc-macro = { version = "2.0.0", path = "./proc-macro" } thiserror = "1.0.21" [target.'cfg(not(target_os = "unknown"))'.dependencies] @@ -52,7 +51,6 @@ rpassword = "4.0.1" [dev-dependencies] tempfile = "3.1.0" -ansi_term = "0.12.1" [features] wasmtime = [ diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index afe55406b0be9..2473f167110a3 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -36,7 +36,6 @@ pub use config::*; pub use error::*; pub use params::*; pub use runner::*; -pub use sc_cli_proc_macro::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; pub use sp_version::RuntimeVersion; @@ -271,164 +270,3 @@ pub fn init_logger( telemetries }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate as sc_cli; - use std::{env, process::Command}; - use tracing::{metadata::Kind, subscriber::Interest, Callsite, Level, Metadata}; - - #[test] - fn test_logger_filters() { - let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; - init_logger( - &test_pattern, - Default::default(), - Default::default(), - Default::default(), - ).unwrap(); - - tracing::dispatcher::get_default(|dispatcher| { - let test_filter = |target, level| { - struct DummyCallSite; - impl Callsite for DummyCallSite { - fn set_interest(&self, _: Interest) {} - fn metadata(&self) -> &Metadata<'_> { - unreachable!(); - } - } - - let metadata = tracing::metadata!( - name: "", - target: target, - level: level, - fields: &[], - callsite: &DummyCallSite, - kind: Kind::SPAN, - ); - - dispatcher.enabled(&metadata) - }; - - assert!(test_filter("afg", Level::INFO)); - assert!(test_filter("afg", Level::DEBUG)); - assert!(!test_filter("afg", Level::TRACE)); - - assert!(test_filter("sync", Level::TRACE)); - assert!(test_filter("client", Level::WARN)); - - assert!(test_filter("telemetry", Level::TRACE)); - assert!(test_filter("something-with-dash", Level::ERROR)); - }); - } - - const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; - - #[test] - fn dash_in_target_name_works() { - let executable = env::current_exe().unwrap(); - let output = Command::new(executable) - .env("ENABLE_LOGGING", "1") - .args(&["--nocapture", "log_something_with_dash_target_name"]) - .output() - .unwrap(); - - let output = String::from_utf8(output.stderr).unwrap(); - assert!(output.contains(EXPECTED_LOG_MESSAGE)); - } - - /// This is no actual test, it will be used by the `dash_in_target_name_works` test. - /// The given test will call the test executable to only execute this test that - /// will only print `EXPECTED_LOG_MESSAGE` through logging while using a target - /// name that contains a dash. This ensures that targets names with dashes work. - #[test] - fn log_something_with_dash_target_name() { - if env::var("ENABLE_LOGGING").is_ok() { - let test_pattern = "test-target=info"; - init_logger( - &test_pattern, - Default::default(), - Default::default(), - Default::default(), - ).unwrap(); - - log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE); - } - } - - const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; - - #[test] - fn prefix_in_log_lines() { - let re = regex::Regex::new(&format!( - r"^\d{{4}}-\d{{2}}-\d{{2}} \d{{2}}:\d{{2}}:\d{{2}} \[{}\] {}$", - EXPECTED_NODE_NAME, - EXPECTED_LOG_MESSAGE, - )).unwrap(); - let executable = env::current_exe().unwrap(); - let output = Command::new(executable) - .env("ENABLE_LOGGING", "1") - .args(&["--nocapture", "prefix_in_log_lines_entrypoint"]) - .output() - .unwrap(); - - let output = String::from_utf8(output.stderr).unwrap(); - assert!( - re.is_match(output.trim()), - format!("Expected:\n{}\nGot:\n{}", re, output), - ); - } - - /// This is no actual test, it will be used by the `prefix_in_log_lines` test. - /// The given test will call the test executable to only execute this test that - /// will only print a log line prefixed by the node name `EXPECTED_NODE_NAME`. - #[test] - fn prefix_in_log_lines_entrypoint() { - if env::var("ENABLE_LOGGING").is_ok() { - init_logger( - "", - Default::default(), - Default::default(), - Default::default(), - ).unwrap(); - prefix_in_log_lines_process(); - } - } - - #[crate::prefix_logs_with(EXPECTED_NODE_NAME)] - fn prefix_in_log_lines_process() { - log::info!("{}", EXPECTED_LOG_MESSAGE); - } - - /// This is no actual test, it will be used by the `do_not_write_with_colors_on_tty` test. - /// The given test will call the test executable to only execute this test that - /// will only print a log line with some colors in it. - #[test] - fn do_not_write_with_colors_on_tty_entrypoint() { - if env::var("ENABLE_LOGGING").is_ok() { - init_logger("", Default::default(), Default::default(), Default::default()).unwrap(); - log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE)); - } - } - - #[test] - fn do_not_write_with_colors_on_tty() { - let re = regex::Regex::new(&format!( - r"^\d{{4}}-\d{{2}}-\d{{2}} \d{{2}}:\d{{2}}:\d{{2}} {}$", - EXPECTED_LOG_MESSAGE, - )).unwrap(); - let executable = env::current_exe().unwrap(); - let output = Command::new(executable) - .env("ENABLE_LOGGING", "1") - .args(&["--nocapture", "do_not_write_with_colors_on_tty_entrypoint"]) - .output() - .unwrap(); - - let output = String::from_utf8(output.stderr).unwrap(); - assert!( - re.is_match(output.trim()), - format!("Expected:\n{}\nGot:\n{}", re, output), - ); - } -} diff --git a/client/logging/Cargo.toml b/client/logging/Cargo.toml index ae8f25dfdb13e..ed6cefa6ef03b 100644 --- a/client/logging/Cargo.toml +++ b/client/logging/Cargo.toml @@ -18,6 +18,7 @@ ansi_term = "0.12.1" atty = "0.2.13" lazy_static = "1.4.0" regex = "1.4.2" +sc-logging-proc-macro = { version = "2.0.0", path = "./proc-macro" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } sc-tracing = { version = "2.0.0", path = "../tracing" } tracing = "0.1.19" @@ -27,3 +28,6 @@ tracing-subscriber = "0.2.10" [target.'cfg(target_os = "unknown")'.dependencies] wasm-bindgen = "0.2.67" web-sys = { version = "0.3.44", features = ["console"] } + +[dev-dependencies] +log = "0.4.11" diff --git a/client/cli/proc-macro/Cargo.toml b/client/logging/proc-macro/Cargo.toml similarity index 94% rename from client/cli/proc-macro/Cargo.toml rename to client/logging/proc-macro/Cargo.toml index 9b9d134c5a836..d508a013eeb71 100644 --- a/client/cli/proc-macro/Cargo.toml +++ b/client/logging/proc-macro/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sc-cli-proc-macro" +name = "sc-logging-proc-macro" version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" diff --git a/client/cli/proc-macro/src/lib.rs b/client/logging/proc-macro/src/lib.rs similarity index 97% rename from client/cli/proc-macro/src/lib.rs rename to client/logging/proc-macro/src/lib.rs index 775d1eb96ea38..ff65e2834f791 100644 --- a/client/cli/proc-macro/src/lib.rs +++ b/client/logging/proc-macro/src/lib.rs @@ -120,16 +120,16 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { let crate_name = if std::env::var("CARGO_PKG_NAME") .expect("cargo env var always there when compiling; qed") - == "sc-cli" + == "sc-logging" { - Ident::new("sc_cli", Span::call_site().into()) + Ident::new("sc_logging", Span::call_site()) } else { - let crate_name = match crate_name("sc-cli") { + let crate_name = match crate_name("sc-logging") { Ok(x) => x, Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), }; - Ident::new(&crate_name, Span::call_site().into()) + Ident::new(&crate_name, Span::call_site()) }; let ItemFn { diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index a41ed893e9ec3..a724018c6c86d 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -25,6 +25,10 @@ mod event_format; mod layers; +pub use sc_logging_proc_macro::*; +#[doc(hidden)] +pub use tracing; + use tracing::Subscriber; use tracing_subscriber::{ filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, registry::LookupSpan, @@ -193,3 +197,156 @@ fn parse_directives(dirs: impl AsRef) -> Vec { dirs.split(',').filter_map(|s| s.parse().ok()).collect() } + +#[cfg(test)] +mod tests { + use super::*; + use crate as sc_logging; + use std::{env, process::Command}; + use tracing::{metadata::Kind, subscriber::Interest, Callsite, Level, Metadata}; + + fn init_logger(pattern: &str) { + let (subscriber, telemetries) = + get_default_subscriber_and_telemetries(pattern, None).unwrap(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + } + + #[test] + fn test_logger_filters() { + let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; + init_logger(&test_pattern); + + tracing::dispatcher::get_default(|dispatcher| { + let test_filter = |target, level| { + struct DummyCallSite; + impl Callsite for DummyCallSite { + fn set_interest(&self, _: Interest) {} + fn metadata(&self) -> &Metadata<'_> { + unreachable!(); + } + } + + let metadata = tracing::metadata!( + name: "", + target: target, + level: level, + fields: &[], + callsite: &DummyCallSite, + kind: Kind::SPAN, + ); + + dispatcher.enabled(&metadata) + }; + + assert!(test_filter("afg", Level::INFO)); + assert!(test_filter("afg", Level::DEBUG)); + assert!(!test_filter("afg", Level::TRACE)); + + assert!(test_filter("sync", Level::TRACE)); + assert!(test_filter("client", Level::WARN)); + + assert!(test_filter("telemetry", Level::TRACE)); + assert!(test_filter("something-with-dash", Level::ERROR)); + }); + } + + const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; + + #[test] + fn dash_in_target_name_works() { + let executable = env::current_exe().unwrap(); + let output = Command::new(executable) + .env("ENABLE_LOGGING", "1") + .args(&["--nocapture", "log_something_with_dash_target_name"]) + .output() + .unwrap(); + + let output = String::from_utf8(output.stderr).unwrap(); + assert!(output.contains(EXPECTED_LOG_MESSAGE)); + } + + /// This is no actual test, it will be used by the `dash_in_target_name_works` test. + /// The given test will call the test executable to only execute this test that + /// will only print `EXPECTED_LOG_MESSAGE` through logging while using a target + /// name that contains a dash. This ensures that targets names with dashes work. + #[test] + fn log_something_with_dash_target_name() { + if env::var("ENABLE_LOGGING").is_ok() { + let test_pattern = "test-target=info"; + init_logger(&test_pattern); + + log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE); + } + } + + const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; + + #[test] + fn prefix_in_log_lines() { + let re = regex::Regex::new(&format!( + r"^\d{{4}}-\d{{2}}-\d{{2}} \d{{2}}:\d{{2}}:\d{{2}} \[{}\] {}$", + EXPECTED_NODE_NAME, EXPECTED_LOG_MESSAGE, + )) + .unwrap(); + let executable = env::current_exe().unwrap(); + let output = Command::new(executable) + .env("ENABLE_LOGGING", "1") + .args(&["--nocapture", "prefix_in_log_lines_entrypoint"]) + .output() + .unwrap(); + + let output = String::from_utf8(output.stderr).unwrap(); + assert!( + re.is_match(output.trim()), + format!("Expected:\n{}\nGot:\n{}", re, output), + ); + } + + /// This is no actual test, it will be used by the `prefix_in_log_lines` test. + /// The given test will call the test executable to only execute this test that + /// will only print a log line prefixed by the node name `EXPECTED_NODE_NAME`. + #[test] + fn prefix_in_log_lines_entrypoint() { + if env::var("ENABLE_LOGGING").is_ok() { + init_logger(""); + prefix_in_log_lines_process(); + } + } + + #[crate::prefix_logs_with(EXPECTED_NODE_NAME)] + fn prefix_in_log_lines_process() { + log::info!("{}", EXPECTED_LOG_MESSAGE); + } + + /// This is no actual test, it will be used by the `do_not_write_with_colors_on_tty` test. + /// The given test will call the test executable to only execute this test that + /// will only print a log line with some colors in it. + #[test] + fn do_not_write_with_colors_on_tty_entrypoint() { + if env::var("ENABLE_LOGGING").is_ok() { + init_logger(""); + log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE)); + } + } + + #[test] + fn do_not_write_with_colors_on_tty() { + let re = regex::Regex::new(&format!( + r"^\d{{4}}-\d{{2}}-\d{{2}} \d{{2}}:\d{{2}}:\d{{2}} {}$", + EXPECTED_LOG_MESSAGE, + )) + .unwrap(); + let executable = env::current_exe().unwrap(); + let output = Command::new(executable) + .env("ENABLE_LOGGING", "1") + .args(&["--nocapture", "do_not_write_with_colors_on_tty_entrypoint"]) + .output() + .unwrap(); + + let output = String::from_utf8(output.stderr).unwrap(); + assert!( + re.is_match(output.trim()), + format!("Expected:\n{}\nGot:\n{}", re, output), + ); + } +} From bed3d310c70308a9dc62ba4683cf616681c10fcb Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 13:23:55 +0100 Subject: [PATCH 062/222] Make prefix_logs_with accessible also from sc-cli --- Cargo.lock | 1 + client/cli/Cargo.toml | 1 + client/cli/src/lib.rs | 4 +++- client/cli/tests/ui.rs | 23 ++++++++++++++++++++ client/cli/tests/ui/prefix_logs_with.rs | 28 +++++++++++++++++++++++++ client/logging/proc-macro/src/lib.rs | 8 +++++-- 6 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 client/cli/tests/ui.rs create mode 100644 client/cli/tests/ui/prefix_logs_with.rs diff --git a/Cargo.lock b/Cargo.lock index 389163159edd8..5ca03caebc088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6569,6 +6569,7 @@ dependencies = [ "thiserror", "tokio 0.2.22", "tracing", + "trybuild", ] [[package]] diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 7dfe445df5205..4c681c1ed9b5b 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -51,6 +51,7 @@ rpassword = "4.0.1" [dev-dependencies] tempfile = "3.1.0" +trybuild = "1.0.35" [features] wasmtime = [ diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 2473f167110a3..b5da5717b21c2 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -45,9 +45,11 @@ use structopt::{ clap::{self, AppSettings}, StructOpt, }; -pub use sc_logging::PREFIX_LOG_SPAN; +pub use sc_logging::{PREFIX_LOG_SPAN, prefix_logs_with}; #[doc(hidden)] pub use tracing; +#[cfg(test)] +use trybuild as _; /// Substrate client CLI /// diff --git a/client/cli/tests/ui.rs b/client/cli/tests/ui.rs new file mode 100644 index 0000000000000..d39ab6574a929 --- /dev/null +++ b/client/cli/tests/ui.rs @@ -0,0 +1,23 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#[test] +fn prefix_logs_with() { + let t = trybuild::TestCases::new(); + t.pass("tests/ui/prefix_logs_with.rs"); +} diff --git a/client/cli/tests/ui/prefix_logs_with.rs b/client/cli/tests/ui/prefix_logs_with.rs new file mode 100644 index 0000000000000..25133bc45dc61 --- /dev/null +++ b/client/cli/tests/ui/prefix_logs_with.rs @@ -0,0 +1,28 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +mod sc_logging {} + +/// This test ensures that prefix_logs_with is usable from sc_cli directly without importing +/// sc_logging. +#[sc_cli::prefix_logs_with("test")] +fn prefix_in_log_lines_process() { + unimplemented!(); +} + +fn main() {} diff --git a/client/logging/proc-macro/src/lib.rs b/client/logging/proc-macro/src/lib.rs index ff65e2834f791..35a3453c1a193 100644 --- a/client/logging/proc-macro/src/lib.rs +++ b/client/logging/proc-macro/src/lib.rs @@ -124,9 +124,13 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { { Ident::new("sc_logging", Span::call_site()) } else { - let crate_name = match crate_name("sc-logging") { + // NOTE: the macro can be found in sc-logging or in sc-cli + let crate_name = match crate_name("sc-cli") { Ok(x) => x, - Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), + Err(_) => match crate_name("sc-logging") { + Ok(x) => x, + Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), + }, }; Ident::new(&crate_name, Span::call_site()) From 64a7627f7507942c0bb1d94a802d6144815b9653 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 13:29:15 +0100 Subject: [PATCH 063/222] Doc --- client/logging/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index a724018c6c86d..a89ad4b7410b7 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -38,9 +38,9 @@ use tracing_subscriber::{ pub use event_format::*; pub use layers::*; -/// Initialize the global logger TODO update doc +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. /// -/// This sets various global logging and tracing instances and thus may only be called once. +/// When running in a browser, the `telemetry_external_transport` should be provided. pub fn get_default_subscriber_and_telemetries( pattern: &str, telemetry_external_transport: Option, @@ -57,9 +57,10 @@ pub fn get_default_subscriber_and_telemetries( ) } -/// Initialize the global logger TODO update doc +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with +/// profiling enabled. /// -/// This sets various global logging and tracing instances and thus may only be called once. +/// When running in a browser, the `telemetry_external_transport` should be provided. pub fn get_default_subscriber_and_telemetries_with_profiling( pattern: &str, telemetry_external_transport: Option, @@ -83,6 +84,8 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( Ok((subscriber.with(profiling), telemetries)) } +// Common implementation for `get_default_subscriber_and_telemetries` and +// `get_default_subscriber_and_telemetries_with_profiling`. fn get_default_subscriber_and_telemetries_internal( extra_directives: impl IntoIterator, telemetry_external_transport: Option, @@ -188,6 +191,7 @@ fn get_default_subscriber_and_telemetries_internal( Ok((subscriber, telemetries)) } +// Transform a string of comma separated logging directive into a `Vec`. fn parse_directives(dirs: impl AsRef) -> Vec { let dirs = dirs.as_ref(); From b5420e65e48d0c5c66ab391273e500494591ec74 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 13:53:03 +0100 Subject: [PATCH 064/222] doc --- client/telemetry/README.md | 47 +++++++++---------------------------- client/telemetry/src/lib.rs | 46 +++++++----------------------------- 2 files changed, 20 insertions(+), 73 deletions(-) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index ccc0b0463d880..41e5e9126d9e9 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -1,46 +1,21 @@ +# sc-telemetry + Telemetry utilities. -TODO update doc -Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. -After that, calling `slog_scope::with_logger` will return a logger that sends information to -the telemetry endpoints. The `telemetry!` macro is a short-cut for calling -`slog_scope::with_logger` followed with `slog_log!`. +`Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a +`Telemetries` instance. The difference between the two is that `Telemetries` will re-use +connections to the same server if possible and manages a collection of channel `Sender` for you +(see `Senders`). `Telemetries` should be used unless you need finer control. -Note that you are supposed to only ever use `telemetry!` and not `slog_scope::with_logger` at -the moment. Substrate may eventually be reworked to get proper `slog` support, including sending -information to the telemetry. +The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must +have been initialized. Creating a `Telemetry` will make all the following code execution use +this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is +dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) +will be used. The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a background thread/task) in order for the telemetry to properly function. Dropping the object will also deregister the global logger and replace it with a logger that discards messages. The `Stream` generates [`TelemetryEvent`]s. -> **Note**: Cloning the [`Telemetry`] and polling from multiple clones has an unspecified behaviour. - -# Example - -```rust -use futures::prelude::*; - -let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { - endpoints: sc_telemetry::TelemetryEndpoints::new(vec![ - // The `0` is the maximum verbosity level of messages to send to this endpoint. - ("wss://example.com".into(), 0) - ]).expect("Invalid URL or multiaddr provided"), - // Can be used to pass an external implementation of WebSockets. - wasm_external_transport: None, -}); - -// The `telemetry` object implements `Stream` and must be processed. -std::thread::spawn(move || { - futures::executor::block_on(telemetry.for_each(|_| future::ready(()))); -}); - -// Sends a message on the telemetry. -sc_telemetry::telemetry!(sc_telemetry::SUBSTRATE_INFO; "test"; - "foo" => "bar", -) -``` - - License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d323316027f76..6cc868d0e7f11 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -16,51 +16,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// TODO update doc //! Telemetry utilities. //! -//! Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. -//! After that, calling `slog_scope::with_logger` will return a logger that sends information to -//! the telemetry endpoints. The `telemetry!` macro is a short-cut for calling -//! `slog_scope::with_logger` followed with `slog_log!`. +//! `Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a +//! `Telemetries` instance. The difference between the two is that `Telemetries` will re-use +//! connections to the same server if possible and manages a collection of channel `Sender` for you +//! (see `Senders`). `Telemetries` should be used unless you need finer control. //! -//! Note that you are supposed to only ever use `telemetry!` and not `slog_scope::with_logger` at -//! the moment. Substrate may eventually be reworked to get proper `slog` support, including sending -//! information to the telemetry. +//! The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must +//! have been initialized. Creating a `Telemetry` will make all the following code execution use +//! this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is +//! dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) +//! will be used. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a //! background thread/task) in order for the telemetry to properly function. Dropping the object //! will also deregister the global logger and replace it with a logger that discards messages. //! The `Stream` generates [`TelemetryEvent`]s. -//! -//! > **Note**: Cloning the [`Telemetry`] and polling from multiple clones has an unspecified behaviour. -//! -//! # Example -//! -//! ```no_run -//! use futures::prelude::*; -//! -//! let (telemetry, _sender) = sc_telemetry::Telemetry::new( -//! sc_telemetry::TelemetryEndpoints::new(vec![ -//! // The `0` is the maximum verbosity level of messages to send to this endpoint. -//! ("wss://example.com".into(), 0) -//! ]).expect("Invalid URL or multiaddr provided"), -//! // Can be used to pass an external implementation of WebSockets. -//! None, -//! None, -//! ); -//! -//! // The `telemetry` object implements `Stream` and must be processed. -//! std::thread::spawn(move || { -//! futures::executor::block_on(telemetry.for_each(|_| future::ready(()))); -//! }); -//! -//! // Sends a message on the telemetry. -//! sc_telemetry::telemetry!(sc_telemetry::SUBSTRATE_INFO; "test"; -//! "foo" => "bar", -//! ) -//! ``` -//! use futures::{channel::mpsc, prelude::*}; use libp2p::{wasm_ext, Multiaddr}; From 388bafd28e238abda06ff7b900b6b264abda62b3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 13:53:56 +0100 Subject: [PATCH 065/222] README.md --- client/logging/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 client/logging/README.md diff --git a/client/logging/README.md b/client/logging/README.md new file mode 100644 index 0000000000000..11866af0e14fd --- /dev/null +++ b/client/logging/README.md @@ -0,0 +1,7 @@ +# sc-logging + +Substrate logging library. + +This crate uses tokio's [tracing](https://github.com/tokio-rs/tracing/) library for logging. + +License: GPL-3.0-or-later WITH Classpath-exception-2.0 From a177df44e8eca443e52178abcab652d31dae8d22 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 13:56:22 +0100 Subject: [PATCH 066/222] Removed some not working logs (not too important either) --- client/telemetry/src/layer.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 696bade3f93c1..e240f27fa3d59 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -66,29 +66,15 @@ where json: Some(json), .. } => { - eprintln!( - //target: "telemetry", - "###### sent message as {}: {}", id, json, - ); - if let Err(err) = sender.try_send(( + let _ = sender.try_send(( message_verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), json.clone(), - )) { - // TODO logs dont work here - log::warn!( - target: "telemetry", - "Ignored telemetry message because of error on channel: {:?}", - err, - ); - } + )); } _ => panic!("missing fields in telemetry log: {:?}", event), } - } else { - // TODO logs dont work here - log::trace!(target: "telemetry", "Telemetry not set"); } } } From 53f91baabd32bad793cc2e0a32d6ee93e76c73e3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:13:31 +0100 Subject: [PATCH 067/222] Use tracing Id instead of u64 --- client/telemetry/src/layer.rs | 16 ++++++++-------- client/telemetry/src/lib.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index e240f27fa3d59..42c673ae78055 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -21,7 +21,7 @@ use parking_lot::Mutex; use std::collections::HashMap; use std::convert::TryInto; use std::sync::Arc; -use tracing::{Event, Subscriber}; +use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; /// Span name used to report the telemetry. @@ -54,7 +54,7 @@ where .chain(parents) .find(|x| x.name() == TELEMETRY_LOG_SPAN) { - let id = span.id().into_u64(); + let id = span.id(); if let Some(sender) = (self.0).0.lock().get_mut(&id) { let mut attrs = TelemetryAttrs::new(id); let mut vis = TelemetryAttrsVisitor(&mut attrs); @@ -85,11 +85,11 @@ where struct TelemetryAttrs { message_verbosity: Option, json: Option, - id: u64, + id: Id, } impl TelemetryAttrs { - fn new(id: u64) -> Self { + fn new(id: Id) -> Self { Self { message_verbosity: None, json: None, @@ -115,7 +115,7 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { // NOTE: this is a hack to inject the span id into the json - let mut message = format!(r#"{{"id":{},"#, (*self.0).id); + let mut message = format!(r#"{{"id":{},"#, (*self.0).id.into_u64()); message.push_str(&value[1..]); (*self.0).json = Some(message) } @@ -128,12 +128,12 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { /// span's ID. #[derive(Default, Debug, Clone)] pub struct Senders( - Arc>>>>, + Arc>>>>, ); impl Senders { - /// TODO doc - pub fn insert(&self, id: u64, sender: mpsc::Sender<(u8, String)>) { + /// Insert a channel `Sender` to the collection using an id (`u64`) for its key. + pub fn insert(&self, id: Id, sender: mpsc::Sender<(u8, String)>) { self.0 .lock() .insert(id, std::panic::AssertUnwindSafe(sender)); diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6cc868d0e7f11..5edf02930b09f 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -283,7 +283,7 @@ impl Telemetries { self.wasm_external_transport.clone(), Some(&self.node_pool), ); - let id = telemetry.span.id().expect("the span is enabled; qed").into_u64(); + let id = telemetry.span.id().expect("the span is enabled; qed"); self.senders.insert(id, sender); From ad7063948097ef2bb678b96caf7c53173f403c5d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:17:18 +0100 Subject: [PATCH 068/222] Doc --- client/telemetry/src/worker.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 76e3e3e038c66..7a3a6c04e5b9a 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -79,12 +79,14 @@ pub type WsTrans = libp2p::core::transport::Boxed< >; impl TelemetryWorker { - // TODO update doc /// Builds a new `TelemetryWorker`. /// /// The endpoints must be a list of targets, plus a verbosity level. When you send a message /// to the telemetry, only the targets whose verbosity is higher than the verbosity of the /// message will receive it. + /// + /// It can re-use `Node` (connections) if a `NodePool` is provided. Otherwise new `Node` are + /// created. pub fn new( endpoints: impl IntoIterator, wasm_external_transport: impl Into>, @@ -165,11 +167,7 @@ impl TelemetryWorker { Poll::Pending } - // TODO update doc - /// Equivalent to `slog::Drain::log`, but takes `self` by `&mut` instead, which is more convenient. - /// - /// Keep in mind that you should call `TelemetryWorker::poll` in order to process the messages. - /// You should call this function right after calling `slog::Drain::log`. + /// Process telemetry message given its verbosity. pub fn log(&mut self, msg_verbosity: u8, json: &str) -> Result<(), ()> { // None of the nodes want that verbosity, so just return without doing any serialization. if self.nodes.iter().all(|(_, node_max_verbosity)| msg_verbosity > *node_max_verbosity) { From c83849d20d0cefa5d9a9176fa2ef0d4db21d0c1b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:23:15 +0100 Subject: [PATCH 069/222] Doc and rename init function --- bin/node/cli/src/browser.rs | 6 +++--- utils/browser/src/lib.rs | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index e1062f11c0f3a..d0d676897798b 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -21,7 +21,7 @@ use log::info; use wasm_bindgen::prelude::*; use browser_utils::{ Client, - browser_configuration, set_console_error_panic_hook, init_console_log, + browser_configuration, set_console_error_panic_hook, }; /// Starts the client. @@ -32,9 +32,9 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu .map_err(|err| JsValue::from_str(&err.to_string())) } -async fn start_inner(chain_spec: Option, log_level: String) -> Result> { +async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let (telemetries, transport) = init_console_log(log_level.as_str())?; + let (telemetries, transport) = browser_utils::init(log_directives.as_str())?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 8b02ce96a58fb..b6a8a7407bc58 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -33,9 +33,11 @@ use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; -/// TODO doc -// TODO should probably renamed to "init()"? -pub fn init_console_log(pattern: &str, /* level: log::Level, TODO not needed anymore I think */) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { +/// Initialize the logger and return a `Telemetries` and a wasm `ExtTransport`. +/// +/// The `Telemetries` object can be use to create `Telemetry` objects and the wasm `ExtTransport` +/// can be used for network transport. +pub fn init(pattern: &str) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( pattern, From af788424449f0544a060beb06dd5504b83ec044a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:25:09 +0100 Subject: [PATCH 070/222] Clean-up & better error code --- bin/node/cli/browser-demo/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh index 337c36db7f39f..8840106daeb5c 100755 --- a/bin/node/cli/browser-demo/build.sh +++ b/bin/node/cli/browser-demo/build.sh @@ -1,4 +1,5 @@ #!/usr/bin/env sh +set -e -x cargo +nightly build --release -p node-cli --target wasm32-unknown-unknown --no-default-features --features browser -Z features=itarget wasm-bindgen ../../../../target/wasm32-unknown-unknown/release/node_cli.wasm --out-dir pkg --target web -python -m http.server 8080 +python -m http.server 8000 From b110d3856627de8a6b6e704f44ec411f72f48b4c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:27:42 +0100 Subject: [PATCH 071/222] CLEANUP --- bin/node/cli/src/browser.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index d0d676897798b..a5516cee9ac7c 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -41,8 +41,7 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, telemetries, transport).await?; - config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_string(), 10)]).unwrap()); + let config = browser_configuration(chain_spec, telemetries, transport).await?; info!("Substrate browser node"); info!("✌️ version {}", config.impl_version); From f26db51e65cfa9b7ed5eeba47983f05a623a475f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 18 Nov 2020 14:47:57 +0100 Subject: [PATCH 072/222] Renamed invalid name for creating Telemetry --- client/service/src/builder.rs | 2 +- client/telemetry/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index d3be3dd4cec2a..b8eaa90ddf39c 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -671,7 +671,7 @@ fn init_telemetry(config: &Configuration) -> Option { // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) _ => return None, }; - Some(config.telemetries.get_or_create(endpoints)) + Some(config.telemetries.build_telemetry(endpoints)) } fn spawn_telemetry_worker>( diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5edf02930b09f..ed7064959a923 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -277,7 +277,7 @@ impl Telemetries { /// /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding /// verbosity level. - pub fn get_or_create(&self, endpoints: TelemetryEndpoints) -> Telemetry { + pub fn build_telemetry(&self, endpoints: TelemetryEndpoints) -> Telemetry { let (telemetry, sender) = Telemetry::new( endpoints.clone(), self.wasm_external_transport.clone(), From d791b48bd163c92b58c27e26edb27d46db18e467 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:21:08 +0100 Subject: [PATCH 073/222] Move stuff around --- client/logging/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index a89ad4b7410b7..10ab20cc5b0d1 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -209,6 +209,9 @@ mod tests { use std::{env, process::Command}; use tracing::{metadata::Kind, subscriber::Interest, Callsite, Level, Metadata}; + const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; + const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; + fn init_logger(pattern: &str) { let (subscriber, telemetries) = get_default_subscriber_and_telemetries(pattern, None).unwrap(); @@ -254,8 +257,6 @@ mod tests { }); } - const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; - #[test] fn dash_in_target_name_works() { let executable = env::current_exe().unwrap(); @@ -283,8 +284,6 @@ mod tests { } } - const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; - #[test] fn prefix_in_log_lines() { let re = regex::Regex::new(&format!( From 0fbf1a94a5597af1b59bb78784c82030bfeeed20 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:24:47 +0100 Subject: [PATCH 074/222] Comment --- client/logging/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index 10ab20cc5b0d1..a30b6d13d0250 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -257,6 +257,8 @@ mod tests { }); } + /// This test ensures that using dash (`-`) in the target name in logs and directives actually + /// work. #[test] fn dash_in_target_name_works() { let executable = env::current_exe().unwrap(); From 647b4a4cd0013f85dfd0d19b2dfe692084b8cb28 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:27:57 +0100 Subject: [PATCH 075/222] Doc --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ed7064959a923..c9a2376dd196e 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -27,7 +27,7 @@ //! have been initialized. Creating a `Telemetry` will make all the following code execution use //! this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is //! dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) -//! will be used. +//! will be used. If no `Telemetry` object can be found, nothing happens. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a //! background thread/task) in order for the telemetry to properly function. Dropping the object From 448c8a19ae52bb2be89901719ce776886b5a0674 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:29:31 +0100 Subject: [PATCH 076/222] Unneeded clone --- client/telemetry/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 42c673ae78055..4eefb601fb5a3 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -70,7 +70,7 @@ where message_verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), - json.clone(), + json, )); } _ => panic!("missing fields in telemetry log: {:?}", event), From aa5fdbe74f78cffc52e4066da8150c998b4f795c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:41:31 +0100 Subject: [PATCH 077/222] Renamed message_verbosity to verbosity --- client/telemetry/src/layer.rs | 12 ++++++------ client/telemetry/src/lib.rs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 4eefb601fb5a3..a5795e3782c95 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -62,12 +62,12 @@ where match attrs { TelemetryAttrs { - message_verbosity: Some(message_verbosity), + verbosity: Some(verbosity), json: Some(json), .. } => { let _ = sender.try_send(( - message_verbosity + verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), json, @@ -83,7 +83,7 @@ where #[derive(Debug)] struct TelemetryAttrs { - message_verbosity: Option, + verbosity: Option, json: Option, id: Id, } @@ -91,7 +91,7 @@ struct TelemetryAttrs { impl TelemetryAttrs { fn new(id: Id) -> Self { Self { - message_verbosity: None, + verbosity: None, json: None, id, } @@ -107,8 +107,8 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { } fn record_u64(&mut self, field: &tracing::field::Field, value: u64) { - if field.name() == "message_verbosity" { - (*self.0).message_verbosity = Some(value) + if field.name() == "verbosity" { + (*self.0).verbosity = Some(value) } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index c9a2376dd196e..f455042a798b5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -221,12 +221,12 @@ impl Stream for Telemetry { } if let Poll::Ready(Some(( - message_verbosity, + verbosity, json, ))) = Stream::poll_next(Pin::new(&mut self.inner.receiver), cx) { if let Some(worker) = self.inner.worker.as_mut() { - let _ = worker.log(message_verbosity, json.as_str()); + let _ = worker.log(verbosity, json.as_str()); } } else { break; @@ -302,14 +302,14 @@ impl Telemetries { #[macro_export(local_inner_macros)] macro_rules! telemetry { ( $a:expr; $b:expr; $( $t:tt )* ) => {{ - let message_verbosity: u8 = $a; + let verbosity: u8 = $a; let mut json = format_fields_to_json!($($t)*); // NOTE: the span id will be added later in the JSON for the greater good json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, - message_verbosity, + verbosity, json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed").as_str() ); From db42f20c610ec2fb440df3a68b9de81cb4da8a5b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:45:33 +0100 Subject: [PATCH 078/222] Change match to if let --- client/telemetry/src/layer.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index a5795e3782c95..c94dcd0069b86 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -60,20 +60,20 @@ where let mut vis = TelemetryAttrsVisitor(&mut attrs); event.record(&mut vis); - match attrs { - TelemetryAttrs { - verbosity: Some(verbosity), - json: Some(json), - .. - } => { - let _ = sender.try_send(( - verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )); - } - _ => panic!("missing fields in telemetry log: {:?}", event), + if let TelemetryAttrs { + verbosity: Some(verbosity), + json: Some(json), + .. + } = attrs + { + let _ = sender.try_send(( + verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )); + } else { + panic!("missing fields in telemetry log: {:?}", event); } } } From 98c791f8bc751654398b99822b1b2887bef8380f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:47:32 +0100 Subject: [PATCH 079/222] Unneeded clone --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f455042a798b5..af6351d9c0b80 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -279,7 +279,7 @@ impl Telemetries { /// verbosity level. pub fn build_telemetry(&self, endpoints: TelemetryEndpoints) -> Telemetry { let (telemetry, sender) = Telemetry::new( - endpoints.clone(), + endpoints, self.wasm_external_transport.clone(), Some(&self.node_pool), ); From 537d882fa7fa256d7711f3fed3e9fefa79ce68c1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:54:07 +0100 Subject: [PATCH 080/222] Fix doc --- client/telemetry/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index c94dcd0069b86..4bb3e3d579f21 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -132,7 +132,7 @@ pub struct Senders( ); impl Senders { - /// Insert a channel `Sender` to the collection using an id (`u64`) for its key. + /// Insert a channel `Sender` to the collection using an `Id` for its key. pub fn insert(&self, id: Id, sender: mpsc::Sender<(u8, String)>) { self.0 .lock() From 5ec5792efec8e14e253e1ac94e692c9d76675f5c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 10:56:24 +0100 Subject: [PATCH 081/222] Apply suggestions from code review Co-authored-by: David --- client/logging/src/lib.rs | 8 ++++---- client/service/src/builder.rs | 2 +- client/telemetry/README.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index a30b6d13d0250..079724936aae3 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -272,10 +272,10 @@ mod tests { assert!(output.contains(EXPECTED_LOG_MESSAGE)); } - /// This is no actual test, it will be used by the `dash_in_target_name_works` test. - /// The given test will call the test executable to only execute this test that - /// will only print `EXPECTED_LOG_MESSAGE` through logging while using a target - /// name that contains a dash. This ensures that targets names with dashes work. + /// This is not an actual test, it is used by the `dash_in_target_name_works` test. + /// The given test will call the test executable and only execute this one test that + /// only prints `EXPECTED_LOG_MESSAGE` through logging while using a target + /// name that contains a dash. This ensures that target names with dashes work. #[test] fn log_something_with_dash_target_name() { if env::var("ENABLE_LOGGING").is_ok() { diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index b8eaa90ddf39c..5fa2c968187f4 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -667,8 +667,8 @@ async fn transaction_notifications( fn init_telemetry(config: &Configuration) -> Option { let endpoints = match config.telemetry_endpoints.clone() { + // Don't initialise telemetry if `telemetry_endpoints` == Some([]) Some(endpoints) if !endpoints.is_empty() => endpoints, - // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) _ => return None, }; Some(config.telemetries.build_telemetry(endpoints)) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index 41e5e9126d9e9..fc7b4028f19e4 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -10,7 +10,7 @@ connections to the same server if possible and manages a collection of channel ` The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must have been initialized. Creating a `Telemetry` will make all the following code execution use this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is -dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) +dropped. If multiple `Telemetry` objects are created, the most recently created one (higher up in the stack) will be used. The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a From 2ce02f865371850f15bfb73e8ccd0d1aa36b59a4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 11:22:39 +0100 Subject: [PATCH 082/222] Unused variable in test --- client/logging/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index 079724936aae3..d7fff9529577f 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -213,7 +213,7 @@ mod tests { const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; fn init_logger(pattern: &str) { - let (subscriber, telemetries) = + let (subscriber, _telemetries) = get_default_subscriber_and_telemetries(pattern, None).unwrap(); tracing::subscriber::set_global_default(subscriber).unwrap(); } From 8e1a83ef0f30f9810cfe2236b7ddddea9fb6c8c5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 12:36:01 +0100 Subject: [PATCH 083/222] Renamed init_logger to init_logging_and_telemetry --- bin/node/cli/src/browser.rs | 4 ++-- client/cli/src/config.rs | 6 +++--- client/cli/src/lib.rs | 2 +- utils/browser/src/lib.rs | 4 +++- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index a5516cee9ac7c..0a27415867bbc 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -21,7 +21,7 @@ use log::info; use wasm_bindgen::prelude::*; use browser_utils::{ Client, - browser_configuration, set_console_error_panic_hook, + browser_configuration, init_logging_and_telemetry, set_console_error_panic_hook, }; /// Starts the client. @@ -34,7 +34,7 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let (telemetries, transport) = browser_utils::init(log_directives.as_str())?; + let (telemetries, transport) = init_logging_and_telemetry(log_directives.as_str())?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index d62b81b50f456..c16772cfb49e6 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -21,8 +21,8 @@ use crate::arg_enums::Database; use crate::error::Result; use crate::{ - init_logger, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams, - OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, + init_logging_and_telemetry, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, + NodeKeyParams, OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, }; use log::warn; use names::{Generator, Name}; @@ -555,7 +555,7 @@ pub trait CliConfiguration: Sized { sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let telemetries = init_logger( + let telemetries = init_logging_and_telemetry( &logger_pattern, tracing_receiver, tracing_targets.as_ref().map(|x| x.as_str()), diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index b5da5717b21c2..ae31f2888adc8 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -236,7 +236,7 @@ pub trait SubstrateCli: Sized { /// Initialize the global logger /// /// This sets various global logging and tracing instances and thus may only be called once. -pub fn init_logger( +pub fn init_logging_and_telemetry( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option<&str>, diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index b6a8a7407bc58..0ced30d4e1d80 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -37,7 +37,9 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// /// The `Telemetries` object can be use to create `Telemetry` objects and the wasm `ExtTransport` /// can be used for network transport. -pub fn init(pattern: &str) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { +pub fn init_logging_and_telemetry( + pattern: &str, +) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( pattern, From 75672d9f849712dccdf3c2c9c31240314dc0fa9d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 12:41:17 +0100 Subject: [PATCH 084/222] English fixes --- client/logging/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/logging/src/lib.rs b/client/logging/src/lib.rs index d7fff9529577f..e2334da0dd92b 100644 --- a/client/logging/src/lib.rs +++ b/client/logging/src/lib.rs @@ -307,9 +307,9 @@ mod tests { ); } - /// This is no actual test, it will be used by the `prefix_in_log_lines` test. - /// The given test will call the test executable to only execute this test that - /// will only print a log line prefixed by the node name `EXPECTED_NODE_NAME`. + /// This is not an actual test, it is used by the `prefix_in_log_lines` test. + /// The given test will call the test executable and only execute this one test that + /// only prints a log line prefixed by the node name `EXPECTED_NODE_NAME`. #[test] fn prefix_in_log_lines_entrypoint() { if env::var("ENABLE_LOGGING").is_ok() { @@ -323,9 +323,9 @@ mod tests { log::info!("{}", EXPECTED_LOG_MESSAGE); } - /// This is no actual test, it will be used by the `do_not_write_with_colors_on_tty` test. - /// The given test will call the test executable to only execute this test that - /// will only print a log line with some colors in it. + /// This is not an actual test, it is used by the `do_not_write_with_colors_on_tty` test. + /// The given test will call the test executable and only execute this one test that + /// only prints a log line with some colors in it. #[test] fn do_not_write_with_colors_on_tty_entrypoint() { if env::var("ENABLE_LOGGING").is_ok() { From 1fe185b1739afd7a1378cce0578f55756d598dc1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 19 Nov 2020 12:46:25 +0100 Subject: [PATCH 085/222] Improve error message --- client/telemetry/src/layer.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 4bb3e3d579f21..04c85771c5030 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -73,7 +73,12 @@ where json, )); } else { - panic!("missing fields in telemetry log: {:?}", event); + panic!( + "missing fields in telemetry log: {:?}. This can happen if \ + `tracing::info_span!` is (mis-)used with the telemetry target \ + directly; you should use the `telemetry!` macro.", + event, + ); } } } From efbbf9e1f8a59d056ffe471b690d12506830afcf Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 10:07:44 +0100 Subject: [PATCH 086/222] Removed unused_crate_dependencies --- client/cli/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index ae31f2888adc8..70a80e1b25be6 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -21,7 +21,6 @@ #![warn(missing_docs)] #![warn(unused_extern_crates)] #![warn(unused_imports)] -#![warn(unused_crate_dependencies)] pub mod arg_enums; mod commands; @@ -48,8 +47,6 @@ use structopt::{ pub use sc_logging::{PREFIX_LOG_SPAN, prefix_logs_with}; #[doc(hidden)] pub use tracing; -#[cfg(test)] -use trybuild as _; /// Substrate client CLI /// From de15a04bf2e9c1cfcd7080b7ea52c4bd5dd2d742 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:02:40 +0100 Subject: [PATCH 087/222] Move sc-logging to a tracing module --- Cargo.lock | 48 +++++++------------ Cargo.toml | 3 +- client/cli/Cargo.toml | 1 - client/cli/src/lib.rs | 9 ++-- client/logging/Cargo.toml | 33 ------------- client/logging/README.md | 7 --- client/tracing/Cargo.toml | 6 +++ .../proc-macro/Cargo.toml | 2 +- .../proc-macro/src/lib.rs | 22 ++++----- client/tracing/src/lib.rs | 5 ++ .../src/logging}/event_format.rs | 2 +- .../src/logging}/layers/console_log.rs | 0 .../src => tracing/src/logging}/layers/mod.rs | 0 .../src/logging}/layers/prefix_layer.rs | 0 .../src/lib.rs => tracing/src/logging/mod.rs} | 8 ++-- utils/browser/Cargo.toml | 2 +- utils/browser/src/lib.rs | 2 +- 17 files changed, 51 insertions(+), 99 deletions(-) delete mode 100644 client/logging/Cargo.toml delete mode 100644 client/logging/README.md rename client/{logging => tracing}/proc-macro/Cargo.toml (94%) rename client/{logging => tracing}/proc-macro/src/lib.rs (93%) rename client/{logging/src => tracing/src/logging}/event_format.rs (99%) rename client/{logging/src => tracing/src/logging}/layers/console_log.rs (100%) rename client/{logging/src => tracing/src/logging}/layers/mod.rs (100%) rename client/{logging/src => tracing/src/logging}/layers/prefix_layer.rs (100%) rename client/{logging/src/lib.rs => tracing/src/logging/mod.rs} (98%) diff --git a/Cargo.lock b/Cargo.lock index 4a9ce6571c53a..2ac924d5c3109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6481,7 +6481,6 @@ dependencies = [ "rpassword", "sc-client-api", "sc-keystore", - "sc-logging", "sc-network", "sc-service", "sc-telemetry", @@ -7039,35 +7038,6 @@ dependencies = [ "sp-state-machine", ] -[[package]] -name = "sc-logging" -version = "2.0.0" -dependencies = [ - "ansi_term 0.12.1", - "atty", - "lazy_static", - "log", - "regex", - "sc-logging-proc-macro", - "sc-telemetry", - "sc-tracing", - "tracing", - "tracing-log", - "tracing-subscriber", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "sc-logging-proc-macro" -version = "2.0.0" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sc-network" version = "0.8.0" @@ -7486,19 +7456,35 @@ dependencies = [ name = "sc-tracing" version = "2.0.0" dependencies = [ + "ansi_term 0.12.1", + "atty", "erased-serde", + "lazy_static", "log", "parking_lot 0.10.2", + "regex", "rustc-hash", "sc-telemetry", + "sc-tracing-proc-macro", "serde", "serde_json", "sp-tracing", "tracing", "tracing-core", + "tracing-log", "tracing-subscriber", ] +[[package]] +name = "sc-tracing-proc-macro" +version = "2.0.0" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sc-transaction-graph" version = "2.0.0" @@ -8828,10 +8814,10 @@ dependencies = [ "rand 0.7.3", "sc-chain-spec", "sc-informant", - "sc-logging", "sc-network", "sc-service", "sc-telemetry", + "sc-tracing", "sp-database", "tracing", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 0e33213c075e2..b960efd9ff9e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,9 +39,8 @@ members = [ "client/finality-grandpa", "client/informant", "client/light", - "client/logging", - "client/logging/proc-macro", "client/tracing", + "client/tracing/proc-macro", "client/keystore", "client/network", "client/network/test", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 3126644687f9e..118f0c79c69b3 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -36,7 +36,6 @@ sp-core = { version = "2.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.8.0", path = "../../primitives/keystore" } sc-service = { version = "0.8.0", default-features = false, path = "../service" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } -sc-logging = { version = "2.0.0", path = "../logging" } sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } names = "0.11.0" structopt = "0.3.8" diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 70a80e1b25be6..06c195ddba7d7 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -44,9 +44,10 @@ use structopt::{ clap::{self, AppSettings}, StructOpt, }; -pub use sc_logging::{PREFIX_LOG_SPAN, prefix_logs_with}; +use sc_tracing::logging; #[doc(hidden)] -pub use tracing; +pub use sc_tracing; +pub use sc_tracing::logging::prefix_logs_with; /// Substrate client CLI /// @@ -240,7 +241,7 @@ pub fn init_logging_and_telemetry( telemetry_external_transport: Option, ) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { - let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries_with_profiling( + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( pattern, telemetry_external_transport, tracing_receiver, @@ -255,7 +256,7 @@ pub fn init_logging_and_telemetry( telemetries } else { - let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( pattern, telemetry_external_transport, )?; diff --git a/client/logging/Cargo.toml b/client/logging/Cargo.toml deleted file mode 100644 index ed6cefa6ef03b..0000000000000 --- a/client/logging/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "sc-logging" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate CLI interface." -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -documentation = "https://docs.rs/sc-logging" -readme = "README.md" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -ansi_term = "0.12.1" -atty = "0.2.13" -lazy_static = "1.4.0" -regex = "1.4.2" -sc-logging-proc-macro = { version = "2.0.0", path = "./proc-macro" } -sc-telemetry = { version = "2.0.0", path = "../telemetry" } -sc-tracing = { version = "2.0.0", path = "../tracing" } -tracing = "0.1.19" -tracing-log = "0.1.1" -tracing-subscriber = "0.2.10" - -[target.'cfg(target_os = "unknown")'.dependencies] -wasm-bindgen = "0.2.67" -web-sys = { version = "0.3.44", features = ["console"] } - -[dev-dependencies] -log = "0.4.11" diff --git a/client/logging/README.md b/client/logging/README.md deleted file mode 100644 index 11866af0e14fd..0000000000000 --- a/client/logging/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# sc-logging - -Substrate logging library. - -This crate uses tokio's [tracing](https://github.com/tokio-rs/tracing/) library for logging. - -License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 03695cdc95a3a..f64dcc84b7b80 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -13,14 +13,20 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +ansi_term = "0.12.1" +atty = "0.2.13" erased-serde = "0.3.9" +lazy_static = "1.4.0" log = { version = "0.4.8" } parking_lot = "0.10.0" +regex = "1.4.2" rustc-hash = "1.1.0" serde = "1.0.101" serde_json = "1.0.41" tracing = "0.1.21" tracing-core = "0.1.17" +tracing-log = "0.1.1" tracing-subscriber = "0.2.13" sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sc-tracing-proc-macro = { version = "2.0.0", path = "./proc-macro" } diff --git a/client/logging/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml similarity index 94% rename from client/logging/proc-macro/Cargo.toml rename to client/tracing/proc-macro/Cargo.toml index d508a013eeb71..f85a815c5a8ad 100644 --- a/client/logging/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sc-logging-proc-macro" +name = "sc-tracing-proc-macro" version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" diff --git a/client/logging/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs similarity index 93% rename from client/logging/proc-macro/src/lib.rs rename to client/tracing/proc-macro/src/lib.rs index 35a3453c1a193..de366141f0c78 100644 --- a/client/logging/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -20,7 +20,7 @@ use proc_macro::TokenStream; use proc_macro2::Span; use proc_macro_crate::crate_name; use quote::quote; -use syn::{Error, Expr, Ident, ItemFn}; +use syn::{Error, Expr, Ident, ItemFn, Path}; /// Add a log prefix to the function. /// @@ -120,20 +120,18 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { let crate_name = if std::env::var("CARGO_PKG_NAME") .expect("cargo env var always there when compiling; qed") - == "sc-logging" + == "sc-tracing" { - Ident::new("sc_logging", Span::call_site()) + Path::from(Ident::new("sc_tracing", Span::call_site())) } else { - // NOTE: the macro can be found in sc-logging or in sc-cli - let crate_name = match crate_name("sc-cli") { - Ok(x) => x, - Err(_) => match crate_name("sc-logging") { - Ok(x) => x, + // NOTE: the macro can be found in sc-tracing or in sc-cli + match crate_name("sc-cli") { + Ok(x) => syn::parse_str::(&format!("{}::sc_tracing", x)).unwrap(), + Err(_) => match crate_name("sc-tracing") { + Ok(x) => Path::from(Ident::new(&x, Span::call_site())), Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), }, - }; - - Ident::new(&crate_name, Span::call_site()) + } }; let ItemFn { @@ -147,7 +145,7 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { #(#attrs)* #vis #sig { let span = #crate_name::tracing::info_span!( - #crate_name::PREFIX_LOG_SPAN, + #crate_name::logging::PREFIX_LOG_SPAN, name = #name, ); let _enter = span.enter(); diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 7422bca713854..f71918b06974c 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -24,6 +24,8 @@ //! //! Currently we provide `Log` (default), `Telemetry` variants for `Receiver` +pub mod logging; + use rustc_hash::FxHashMap; use std::fmt; use std::time::{Duration, Instant}; @@ -43,6 +45,9 @@ use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; const ZERO_DURATION: Duration = Duration::from_nanos(0); +#[doc(hidden)] +pub use tracing; + /// Responsible for assigning ids to new spans, which are not re-used. pub struct ProfilingLayer { targets: Vec<(String, Level)>, diff --git a/client/logging/src/event_format.rs b/client/tracing/src/logging/event_format.rs similarity index 99% rename from client/logging/src/event_format.rs rename to client/tracing/src/logging/event_format.rs index 7b694e7c739ca..34c08a3267d57 100644 --- a/client/logging/src/event_format.rs +++ b/client/tracing/src/logging/event_format.rs @@ -94,7 +94,7 @@ where let parents = span.parents(); for span in std::iter::once(span).chain(parents) { let exts = span.extensions(); - if let Some(prefix) = exts.get::() { + if let Some(prefix) = exts.get::() { write!(writer, "{}", prefix.as_str())?; break; } diff --git a/client/logging/src/layers/console_log.rs b/client/tracing/src/logging/layers/console_log.rs similarity index 100% rename from client/logging/src/layers/console_log.rs rename to client/tracing/src/logging/layers/console_log.rs diff --git a/client/logging/src/layers/mod.rs b/client/tracing/src/logging/layers/mod.rs similarity index 100% rename from client/logging/src/layers/mod.rs rename to client/tracing/src/logging/layers/mod.rs diff --git a/client/logging/src/layers/prefix_layer.rs b/client/tracing/src/logging/layers/prefix_layer.rs similarity index 100% rename from client/logging/src/layers/prefix_layer.rs rename to client/tracing/src/logging/layers/prefix_layer.rs diff --git a/client/logging/src/lib.rs b/client/tracing/src/logging/mod.rs similarity index 98% rename from client/logging/src/lib.rs rename to client/tracing/src/logging/mod.rs index e2334da0dd92b..d95029eb8a3bb 100644 --- a/client/logging/src/lib.rs +++ b/client/tracing/src/logging/mod.rs @@ -25,9 +25,7 @@ mod event_format; mod layers; -pub use sc_logging_proc_macro::*; -#[doc(hidden)] -pub use tracing; +pub use sc_tracing_proc_macro::*; use tracing::Subscriber; use tracing_subscriber::{ @@ -64,7 +62,7 @@ pub fn get_default_subscriber_and_telemetries( pub fn get_default_subscriber_and_telemetries_with_profiling( pattern: &str, telemetry_external_transport: Option, - tracing_receiver: sc_tracing::TracingReceiver, + tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< ( @@ -79,7 +77,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( .chain(parse_directives(profiling_targets).into_iter()), telemetry_external_transport, )?; - let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, profiling_targets); + let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); Ok((subscriber.with(profiling), telemetries)) } diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 2d4b856c8eb61..7d25e64a81412 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -29,7 +29,7 @@ sc-service = { version = "0.8.0", path = "../../client/service", default-feature sc-network = { path = "../../client/network", version = "0.8.0"} sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0"} sc-telemetry = { path = "../../client/telemetry", version = "2.0.0"} -sc-logging = { path = "../../client/logging", version = "2.0.0"} +sc-tracing = { path = "../../client/tracing", version = "2.0.0"} # Imported just for the `wasm-bindgen` feature rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 0ced30d4e1d80..fd9a758e66abb 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -41,7 +41,7 @@ pub fn init_logging_and_telemetry( pattern: &str, ) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); - let (subscriber, telemetries) = sc_logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, Some(transport.clone()), )?; From e1650bf6c8ed36c165bff410d38e1d7deb9ac975 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:08:05 +0100 Subject: [PATCH 088/222] Apply suggestion --- client/tracing/proc-macro/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/tracing/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs index de366141f0c78..d563e5e5271a4 100644 --- a/client/tracing/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -124,7 +124,6 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { { Path::from(Ident::new("sc_tracing", Span::call_site())) } else { - // NOTE: the macro can be found in sc-tracing or in sc-cli match crate_name("sc-cli") { Ok(x) => syn::parse_str::(&format!("{}::sc_tracing", x)).unwrap(), Err(_) => match crate_name("sc-tracing") { From 96730cae2ab7c0bc7b41c22db283e50e55bfa64c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:19:19 +0100 Subject: [PATCH 089/222] Apply suggestions --- client/telemetry/src/lib.rs | 2 ++ client/telemetry/src/worker.rs | 2 +- client/telemetry/src/worker/node_pool.rs | 2 ++ client/tracing/src/logging/layers/prefix_layer.rs | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index af6351d9c0b80..2508206164e1b 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -34,6 +34,8 @@ //! will also deregister the global logger and replace it with a logger that discards messages. //! The `Stream` generates [`TelemetryEvent`]s. +#![warn(missing_docs)] + use futures::{channel::mpsc, prelude::*}; use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 7a3a6c04e5b9a..c3130a6583902 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -42,7 +42,7 @@ use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; mod node; pub(crate) mod node_pool; -use node_pool::NodePool; +pub use node_pool::NodePool; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs index 61947a113430a..c3fb21216f6dd 100644 --- a/client/telemetry/src/worker/node_pool.rs +++ b/client/telemetry/src/worker/node_pool.rs @@ -23,11 +23,13 @@ use std::collections::{hash_map::Entry, HashMap}; use std::sync::Arc; #[derive(Debug, Default)] +/// A collection of nodes connecting to a telemetry server and identified by address. pub struct NodePool { nodes: Mutex>>>>, } impl NodePool { + /// Create a new `Node` if it doesn't exist for a given address. pub fn get_or_create( &self, transport: WsTrans, diff --git a/client/tracing/src/logging/layers/prefix_layer.rs b/client/tracing/src/logging/layers/prefix_layer.rs index feae8f85f22e0..843845bf6408e 100644 --- a/client/tracing/src/logging/layers/prefix_layer.rs +++ b/client/tracing/src/logging/layers/prefix_layer.rs @@ -19,7 +19,7 @@ use tracing::{span::Attributes, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; -/// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!` +/// Span name used for the logging prefix. See macro `sc_tracing::logging::prefix_logs_with!` pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix"; /// A `Layer` that captures the prefix span ([`PREFIX_LOG_SPAN`]) which is then used by From 86929c338cb8eb9e03aede232a69ff58c9e3917f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:26:12 +0100 Subject: [PATCH 090/222] Apply suggestion --- client/tracing/src/logging/mod.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index d95029eb8a3bb..e2a8cf1ce40fd 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -191,13 +191,7 @@ fn get_default_subscriber_and_telemetries_internal( // Transform a string of comma separated logging directive into a `Vec`. fn parse_directives(dirs: impl AsRef) -> Vec { - let dirs = dirs.as_ref(); - - if dirs.is_empty() { - return Default::default(); - } - - dirs.split(',').filter_map(|s| s.parse().ok()).collect() + dirs.as_ref().split(',').filter_map(|s| s.parse().ok()).collect() } #[cfg(test)] From e10fbc23f073d8e76ece40c615aba8e4add3815d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:31:18 +0100 Subject: [PATCH 091/222] Apply suggestion --- client/telemetry/src/worker.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index c3130a6583902..f3c35d2a559b4 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -85,8 +85,8 @@ impl TelemetryWorker { /// to the telemetry, only the targets whose verbosity is higher than the verbosity of the /// message will receive it. /// - /// It can re-use `Node` (connections) if a `NodePool` is provided. Otherwise new `Node` are - /// created. + /// It can re-use `Node` (connections) if a `NodePool` is provided and share the same address of + /// connection. Otherwise new `Node` are created. pub fn new( endpoints: impl IntoIterator, wasm_external_transport: impl Into>, From 162bf745930f29b8022a63ca0abc24946d641ccc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:33:19 +0100 Subject: [PATCH 092/222] Apply suggestion --- client/telemetry/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2508206164e1b..41c2438b6c1d7 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -130,9 +130,8 @@ pub const CONSENSUS_WARN: u8 = 4; pub const CONSENSUS_INFO: u8 = 1; /// Telemetry object. Implements `Future` and must be polled regularly. -/// Contains an `Arc` and can be cloned and pass around. Only one clone needs to be polled -/// regularly and should be polled regularly. -/// Dropping all the clones unregisters the telemetry. +/// +/// Dropping unregisters the telemetry. #[derive(Debug)] pub struct Telemetry { inner: TelemetryInner, From 7b1b5acddf3a00ab332693140ab876621d7aedc5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:42:09 +0100 Subject: [PATCH 093/222] More explanation --- client/telemetry/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 41c2438b6c1d7..ba6f3e8197bae 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -18,6 +18,9 @@ //! Telemetry utilities. //! +/// The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. +/// It is unregistered when the object is dropped. +/// //! `Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a //! `Telemetries` instance. The difference between the two is that `Telemetries` will re-use //! connections to the same server if possible and manages a collection of channel `Sender` for you From 5afe364b5f30343e7b59ba1114d83f76b4bb01a2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:43:06 +0100 Subject: [PATCH 094/222] Fix doc comment --- client/telemetry/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ba6f3e8197bae..1f3405f57ec10 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -18,9 +18,9 @@ //! Telemetry utilities. //! -/// The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. -/// It is unregistered when the object is dropped. -/// +//! The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. +//! It is unregistered when the object is dropped. +//! //! `Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a //! `Telemetries` instance. The difference between the two is that `Telemetries` will re-use //! connections to the same server if possible and manages a collection of channel `Sender` for you From f3c2786ed7461b82f4b3abbb03ff1e848c221a2f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 11:46:28 +0100 Subject: [PATCH 095/222] Fixes --- client/tracing/src/logging/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index e2a8cf1ce40fd..8b95ddafd5a8b 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -197,7 +197,7 @@ fn parse_directives(dirs: impl AsRef) -> Vec { #[cfg(test)] mod tests { use super::*; - use crate as sc_logging; + use crate as sc_tracing; use std::{env, process::Command}; use tracing::{metadata::Kind, subscriber::Interest, Callsite, Level, Metadata}; @@ -310,7 +310,7 @@ mod tests { } } - #[crate::prefix_logs_with(EXPECTED_NODE_NAME)] + #[crate::logging::prefix_logs_with(EXPECTED_NODE_NAME)] fn prefix_in_log_lines_process() { log::info!("{}", EXPECTED_LOG_MESSAGE); } From ca23c7ae1c17691a7d75ef997373f8a62da5c92f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 12:06:29 +0100 Subject: [PATCH 096/222] Fix test --- client/tracing/src/logging/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 8b95ddafd5a8b..8f3e4240b5e81 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -204,16 +204,16 @@ mod tests { const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; - fn init_logger(pattern: &str) { + fn init_logger(pattern: &str) -> tracing::subscriber::DefaultGuard { let (subscriber, _telemetries) = get_default_subscriber_and_telemetries(pattern, None).unwrap(); - tracing::subscriber::set_global_default(subscriber).unwrap(); + tracing::subscriber::set_default(subscriber) } #[test] fn test_logger_filters() { let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; - init_logger(&test_pattern); + let _guard = init_logger(&test_pattern); tracing::dispatcher::get_default(|dispatcher| { let test_filter = |target, level| { @@ -272,7 +272,7 @@ mod tests { fn log_something_with_dash_target_name() { if env::var("ENABLE_LOGGING").is_ok() { let test_pattern = "test-target=info"; - init_logger(&test_pattern); + let _guard = init_logger(&test_pattern); log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE); } @@ -305,7 +305,7 @@ mod tests { #[test] fn prefix_in_log_lines_entrypoint() { if env::var("ENABLE_LOGGING").is_ok() { - init_logger(""); + let _guard = init_logger(""); prefix_in_log_lines_process(); } } @@ -321,7 +321,7 @@ mod tests { #[test] fn do_not_write_with_colors_on_tty_entrypoint() { if env::var("ENABLE_LOGGING").is_ok() { - init_logger(""); + let _guard = init_logger(""); log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE)); } } From 717e2cd2b6f9cfdf958d40a8d7cafe8795374965 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 13:49:19 +0100 Subject: [PATCH 097/222] Missing dependency --- Cargo.lock | 2 ++ client/tracing/Cargo.toml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 2ac924d5c3109..652ca8d97db39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7473,6 +7473,8 @@ dependencies = [ "tracing-core", "tracing-log", "tracing-subscriber", + "wasm-bindgen", + "web-sys", ] [[package]] diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index f64dcc84b7b80..3bc6f0484b250 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -30,3 +30,7 @@ tracing-subscriber = "0.2.13" sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } sc-tracing-proc-macro = { version = "2.0.0", path = "./proc-macro" } + +[target.'cfg(target_os = "unknown")'.dependencies] +wasm-bindgen = "0.2.67" +web-sys = { version = "0.3.44", features = ["console"] } From 39306cada4117253504c40e0dc022a328bbe50a0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 14:03:47 +0100 Subject: [PATCH 098/222] Fix wrong path --- client/tracing/src/logging/layers/console_log.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tracing/src/logging/layers/console_log.rs b/client/tracing/src/logging/layers/console_log.rs index 0c28ef5dde4d7..abae3a1bf011a 100644 --- a/client/tracing/src/logging/layers/console_log.rs +++ b/client/tracing/src/logging/layers/console_log.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::event_format::{CustomFmtContext, EventFormat}; +use crate::logging::event_format::{CustomFmtContext, EventFormat}; use std::fmt; use tracing::{Event, Level, Subscriber}; use tracing_subscriber::{ From f87ed5560c6894eb9d4aa8108187845b36195317 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 25 Nov 2020 14:21:26 +0100 Subject: [PATCH 099/222] Write to stderr without panicking --- client/telemetry/src/layer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 04c85771c5030..ef0fd4c0c29dd 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -73,7 +73,8 @@ where json, )); } else { - panic!( + // NOTE: logging in this function doesn't work + eprintln!( "missing fields in telemetry log: {:?}. This can happen if \ `tracing::info_span!` is (mis-)used with the telemetry target \ directly; you should use the `telemetry!` macro.", From 02d196e516f7685dc540bb18fad2bc6b099618dc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 12:55:14 +0100 Subject: [PATCH 100/222] Fix another issue with arbitrary_precision --- bin/node/browser-testing/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/node/browser-testing/src/lib.rs b/bin/node/browser-testing/src/lib.rs index 777e5ea9f132e..83bb8c20d5189 100644 --- a/bin/node/browser-testing/src/lib.rs +++ b/bin/node/browser-testing/src/lib.rs @@ -47,10 +47,11 @@ fn rpc_call(method: &str) -> String { fn deserialize_rpc_result(js_value: JsValue) -> T { let string = js_value.as_string().unwrap(); - let value = serde_json::from_str::(&string).unwrap().result; + let value: serde_json::Value = serde_json::from_str(&string).unwrap(); + let result = serde_json::from_value::(value).unwrap().result; // We need to convert a `Value::Object` into a proper type. - let value_string = serde_json::to_string(&value).unwrap(); - serde_json::from_str(&value_string).unwrap() + let result_string = serde_json::to_string(&result).unwrap(); + serde_json::from_str(&result_string).unwrap() } #[wasm_bindgen_test] From 21c8e05b1dcc76eb048d8ca4b47f14b077fae101 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 13:46:43 +0100 Subject: [PATCH 101/222] Fixed test to use sc_cli --- client/cli/tests/ui/prefix_logs_with.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cli/tests/ui/prefix_logs_with.rs b/client/cli/tests/ui/prefix_logs_with.rs index 25133bc45dc61..ea504303162b4 100644 --- a/client/cli/tests/ui/prefix_logs_with.rs +++ b/client/cli/tests/ui/prefix_logs_with.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -mod sc_logging {} +mod sc_tracing {} /// This test ensures that prefix_logs_with is usable from sc_cli directly without importing /// sc_logging. From 22f72fa5bf50abe397119dba460cf272a2f13ad9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 13:50:20 +0100 Subject: [PATCH 102/222] Update README.md --- client/telemetry/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index fc7b4028f19e4..2309a0ac072da 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -2,6 +2,9 @@ Telemetry utilities. +The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. +It is unregistered when the object is dropped. + `Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a `Telemetries` instance. The difference between the two is that `Telemetries` will re-use connections to the same server if possible and manages a collection of channel `Sender` for you @@ -10,8 +13,8 @@ connections to the same server if possible and manages a collection of channel ` The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must have been initialized. Creating a `Telemetry` will make all the following code execution use this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is -dropped. If multiple `Telemetry` objects are created, the most recently created one (higher up in the stack) -will be used. +dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) +will be used. If no `Telemetry` object can be found, nothing happens. The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a background thread/task) in order for the telemetry to properly function. Dropping the object From f44dd199bba7a48e1479f18d5dae8e0d65fe0e6d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 13:44:59 +0100 Subject: [PATCH 103/222] Remove arbitrary_precision --- Cargo.lock | 1 - bin/node/browser-testing/src/lib.rs | 7 +++---- client/finality-grandpa/Cargo.toml | 1 - client/finality-grandpa/rpc/src/lib.rs | 7 ++----- client/rpc-api/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- frame/contracts/rpc/src/lib.rs | 3 +-- primitives/rpc/src/lib.rs | 3 +-- 8 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0a21058d0747..5db6dfea3363c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6923,7 +6923,6 @@ dependencies = [ "sc-network-gossip", "sc-network-test", "sc-telemetry", - "serde", "serde_json", "sp-api", "sp-application-crypto", diff --git a/bin/node/browser-testing/src/lib.rs b/bin/node/browser-testing/src/lib.rs index 83bb8c20d5189..777e5ea9f132e 100644 --- a/bin/node/browser-testing/src/lib.rs +++ b/bin/node/browser-testing/src/lib.rs @@ -47,11 +47,10 @@ fn rpc_call(method: &str) -> String { fn deserialize_rpc_result(js_value: JsValue) -> T { let string = js_value.as_string().unwrap(); - let value: serde_json::Value = serde_json::from_str(&string).unwrap(); - let result = serde_json::from_value::(value).unwrap().result; + let value = serde_json::from_str::(&string).unwrap().result; // We need to convert a `Value::Object` into a proper type. - let result_string = serde_json::to_string(&result).unwrap(); - serde_json::from_str(&result_string).unwrap() + let value_string = serde_json::to_string(&value).unwrap(); + serde_json::from_str(&value_string).unwrap() } #[wasm_bindgen_test] diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index c17eabd61f995..8966f5e8f657a 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -59,4 +59,3 @@ sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } tokio = { version = "0.2", features = ["rt-core"] } tempfile = "3.1.0" sp-api = { version = "2.0.0", path = "../../primitives/api" } -serde = "1.0.101" diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index c0619e16c4802..172473ad6518b 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -197,7 +197,6 @@ where #[cfg(test)] mod tests { use super::*; - use serde::Deserialize; use std::{collections::HashSet, convert::TryInto, sync::Arc}; use jsonrpc_core::{Notification, Output, types::Params}; @@ -386,8 +385,7 @@ mod tests { // Subscribe let sub_request = r#"{"jsonrpc":"2.0","method":"grandpa_subscribeJustifications","params":[],"id":1}"#; let resp = io.handle_request_sync(sub_request, meta.clone()); - let val: serde_json::Value = serde_json::from_str(&resp.unwrap()).unwrap(); - let resp = Output::deserialize(val).unwrap(); + let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); let sub_id = match resp { Output::Success(success) => success.result, @@ -419,8 +417,7 @@ mod tests { // Subscribe let sub_request = r#"{"jsonrpc":"2.0","method":"grandpa_subscribeJustifications","params":[],"id":1}"#; let resp = io.handle_request_sync(sub_request, meta.clone()); - let val: serde_json::Value = serde_json::from_str(&resp.unwrap()).unwrap(); - let resp = Output::deserialize(val).unwrap(); + let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); assert!(matches!(resp, Output::Success(_))); // Unsubscribe with wrong ID diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 156410c1d7a3d..0947dc47819cd 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "1.3.4" } derive_more = "0.99.2" futures = { version = "0.3.1", features = ["compat"] } -jsonrpc-core = { version = "15.1.0", features = ["arbitrary_precision"] } +jsonrpc-core = "15.1.0" jsonrpc-core-client = "15.1.0" jsonrpc-derive = "15.1.0" jsonrpc-pubsub = "15.1.0" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 050eb85857956..9ca15e2d78f9a 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -28,5 +28,5 @@ take_mut = "0.2.2" void = "1.0.2" tracing = "0.1.10" tracing-subscriber = "0.2.13" -serde_json = { version = "1.0.41", features = ["arbitrary_precision"] } +serde_json = "1.0.41" chrono = "0.4.13" diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 5011caf14465d..6d43ea75c035f 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -306,7 +306,7 @@ mod tests { #[test] fn call_request_should_serialize_deserialize_properly() { type Req = CallRequest; - let value: serde_json::Value = serde_json::from_str(r#" + let req: Req = serde_json::from_str(r#" { "origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", "dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom", @@ -315,7 +315,6 @@ mod tests { "inputData": "0x8c97db39" } "#).unwrap(); - let req = Req::deserialize(value).unwrap(); assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64)); } diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index 669ba764b2438..c479f0df8b60e 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -27,9 +27,8 @@ pub mod list; pub(crate) fn assert_deser(s: &str, expected: T) where T: std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned + PartialEq { - let val: serde_json::Value = serde_json::from_str(s).unwrap(); assert_eq!( - T::deserialize(val).unwrap(), + serde_json::from_str::(s).unwrap(), expected ); assert_eq!( From d208832cad8d9b0a2d4642246ae0fd21885a8273 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 15:49:46 +0100 Subject: [PATCH 104/222] Do not panic if serialization fail during runtime --- client/telemetry/src/lib.rs | 66 ++++++++++++++++++++++++++----------- client/tracing/src/lib.rs | 4 +-- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 1f3405f57ec10..d3bf506e842d1 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -307,16 +307,27 @@ impl Telemetries { macro_rules! telemetry { ( $a:expr; $b:expr; $( $t:tt )* ) => {{ let verbosity: u8 = $a; - let mut json = format_fields_to_json!($($t)*); - // NOTE: the span id will be added later in the JSON for the greater good - json.insert("level".into(), "INFO".into()); - json.insert("msg".into(), $b.into()); - json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); - $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, - verbosity, - json = $crate::serde_json::to_string(&json) - .expect("contains only string keys; qed").as_str() - ); + match format_fields_to_json!($($t)*) { + Err(err) => { + $crate::tracing::error!( + target: "telemetry", + "Could not serialize value for telemetry: {}", + err, + ); + }, + Ok(mut json) => { + // NOTE: the span id will be added later in the JSON for the greater good + json.insert("level".into(), "INFO".into()); + json.insert("msg".into(), $b.into()); + json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); + let serialized_json = $crate::serde_json::to_string(&json) + .expect("contains only string keys; qed"); + $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, + verbosity, + json = serialized_json.as_str(), + ); + }, + } }}; } @@ -324,21 +335,36 @@ macro_rules! telemetry { #[doc(hidden)] macro_rules! format_fields_to_json { ( $k:literal => $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ - let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), $crate::serde_json::to_value($v) - .expect("telemetry values must be serializable")); - $( - map.append(&mut format_fields_to_json!($($t)*)); - )* - map + $crate::serde_json::to_value(&$v) + .map(|value| { + let mut map = $crate::serde_json::Map::new(); + map.insert($k.into(), value); + map + }) + $( + .and_then(|mut prev_map| { + format_fields_to_json!($($t)*) + .map(move |mut other_map| { + prev_map.append(&mut other_map); + prev_map + }) + }) + )* }}; ( $k:literal => ? $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); - map.insert($k.into(), std::format!("{:?}", $v).into()); + map.insert($k.into(), std::format!("{:?}", &$v).into()); + let ok_map: Result<_, $crate::serde_json::Error> = Ok(map); + ok_map $( - map.append(&mut format_fields_to_json!($($t)*)); + .and_then(|mut prev_map| { + format_fields_to_json!($($t)*) + .map(move |mut other_map| { + prev_map.append(&mut other_map); + prev_map + }) + }) )* - map }}; } diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index f71918b06974c..ec9a6b20029f6 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -395,7 +395,7 @@ impl TraceHandler for TelemetryTraceHandler { "target" => span_datum.target, "time" => span_datum.overall_time.as_nanos(), "id" => span_datum.id.into_u64(), - "parent_id" => span_datum.parent_id.map(|i| i.into_u64()), + "parent_id" => span_datum.parent_id.as_ref().map(|i| i.into_u64()), "values" => span_datum.values ); } @@ -404,7 +404,7 @@ impl TraceHandler for TelemetryTraceHandler { telemetry!(SUBSTRATE_INFO; "tracing.event"; "name" => event.name, "target" => event.target, - "parent_id" => event.parent_id.map(|i| i.into_u64()), + "parent_id" => event.parent_id.as_ref().map(|i| i.into_u64()), "values" => event.values ); } From b99af5cac5f073bc8b056b80fa4a844af7ca092d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 26 Nov 2020 16:02:10 +0100 Subject: [PATCH 105/222] Fix for lack of arbitrary_precision in serde_json --- client/service/src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 29acfb7924703..e4f36475d0d8f 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -712,7 +712,7 @@ fn spawn_telemetry_worker>( "chain" => chain_name.clone(), "genesis_hash" => ?genesis_hash, "authority" => is_authority, - "startup_time" => startup_time, + "startup_time" => startup_time.to_string(), "network_id" => network_id.clone() ); From 5a0e055eafaed5dd8c0f74d6892d7b8ea2144bf2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 27 Nov 2020 08:55:01 +0100 Subject: [PATCH 106/222] Fix incorrect doc --- client/telemetry/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d3bf506e842d1..74cee95933abf 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -33,8 +33,7 @@ //! will be used. If no `Telemetry` object can be found, nothing happens. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a -//! background thread/task) in order for the telemetry to properly function. Dropping the object -//! will also deregister the global logger and replace it with a logger that discards messages. +//! background thread/task) in order for the telemetry to properly function. //! The `Stream` generates [`TelemetryEvent`]s. #![warn(missing_docs)] From 2bc432e874f55ebad4d4c5b83875904fa608e271 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 27 Nov 2020 09:06:40 +0100 Subject: [PATCH 107/222] Rework doc --- client/telemetry/src/lib.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 74cee95933abf..d4c10512a23a4 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -18,19 +18,20 @@ //! Telemetry utilities. //! -//! The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. -//! It is unregistered when the object is dropped. +//! You can collect telemetries for a substrate node by creating a `Telemetry` object. For every +//! substrate node there must be only one `Telemetry` object. This `Telemetry` object can connect to +//! multiple telemetry endpoints. The `Telemetry` object is a `Stream` that needs to be polled +//! regularly in order to function. //! -//! `Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a -//! `Telemetries` instance. The difference between the two is that `Telemetries` will re-use -//! connections to the same server if possible and manages a collection of channel `Sender` for you -//! (see `Senders`). `Telemetries` should be used unless you need finer control. +//! The macro `telemetry!` can be used to report telemetries from anywhere in the code but a +//! `Telemetry` must have been initialized. Creating a `Telemetry` will make all the following code +//! execution (including new created async background tasks) use this `Telemetry` when reporting +//! telemetries. If multiple `Telemetry` objects are created, the latest one (higher up in the +//! stack) will be used. If no `Telemetry` object can be found, nothing happens. //! -//! The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must -//! have been initialized. Creating a `Telemetry` will make all the following code execution use -//! this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is -//! dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) -//! will be used. If no `Telemetry` object can be found, nothing happens. +//! To re-use connections to the same server you need to use the `Telemetries` object to create a +//! `Telemetry`. `Telemetries` also manages a collection of channel `Sender` for you (see +//! `Senders`). `Telemetries` should be used unless you need finer control. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a //! background thread/task) in order for the telemetry to properly function. From b47aaf959bf994aa07d3ad334014786c295722ed Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 27 Nov 2020 09:11:59 +0100 Subject: [PATCH 108/222] Spelling and small change --- client/telemetry/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d4c10512a23a4..9a22d3ce402df 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -25,9 +25,9 @@ //! //! The macro `telemetry!` can be used to report telemetries from anywhere in the code but a //! `Telemetry` must have been initialized. Creating a `Telemetry` will make all the following code -//! execution (including new created async background tasks) use this `Telemetry` when reporting +//! execution (including newly created async background tasks) use this `Telemetry` when reporting //! telemetries. If multiple `Telemetry` objects are created, the latest one (higher up in the -//! stack) will be used. If no `Telemetry` object can be found, nothing happens. +//! stack) will be used. If no `Telemetry` object can be found, nothing is reported. //! //! To re-use connections to the same server you need to use the `Telemetries` object to create a //! `Telemetry`. `Telemetries` also manages a collection of channel `Sender` for you (see From 887a526759a85f61d638569d46810505910ef3d6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 27 Nov 2020 10:41:05 +0100 Subject: [PATCH 109/222] Improve doc again --- client/telemetry/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 9a22d3ce402df..d0a4cb0a96ad5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -29,8 +29,8 @@ //! telemetries. If multiple `Telemetry` objects are created, the latest one (higher up in the //! stack) will be used. If no `Telemetry` object can be found, nothing is reported. //! -//! To re-use connections to the same server you need to use the `Telemetries` object to create a -//! `Telemetry`. `Telemetries` also manages a collection of channel `Sender` for you (see +//! To re-use connections to the same server you need to use the `Telemetries` object to create +//! multiple `Telemetry`. `Telemetries` also manages a collection of channel `Sender` for you (see //! `Senders`). `Telemetries` should be used unless you need finer control. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a From b11d95e3a223ba2bc2794ca504582b414076c4d0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 27 Nov 2020 10:41:14 +0100 Subject: [PATCH 110/222] Drop unused "level" in payload --- client/telemetry/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d0a4cb0a96ad5..748710e213685 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -317,7 +317,6 @@ macro_rules! telemetry { }, Ok(mut json) => { // NOTE: the span id will be added later in the JSON for the greater good - json.insert("level".into(), "INFO".into()); json.insert("msg".into(), $b.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); let serialized_json = $crate::serde_json::to_string(&json) From e5c74e5b0bde441beb0d697a6ffafad0cef8e226 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 11:46:41 +0100 Subject: [PATCH 111/222] WIP Refactor to single worker --- client/cli/src/runner.rs | 5 ++++- client/telemetry/src/lib.rs | 28 ++++++++++++++++++++++++++-- client/tracing/src/logging/mod.rs | 2 +- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index a233dcacea3df..f2a0a5445717a 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -112,6 +112,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, + telemetries: sc_telemetry::Telemetries, phantom: PhantomData, } @@ -138,9 +139,10 @@ impl Runner { config: command.create_configuration( cli, task_executor.into(), - telemetries, + telemetries.clone(), )?, tokio_runtime, + telemetries, phantom: PhantomData, }) } @@ -186,6 +188,7 @@ impl Runner { ) -> Result<()> { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; + task_manager.spawn_handle().spawn("telemetries", self.telemetries.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); res.map_err(|e| e.to_string().into()) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 748710e213685..3fcc305631104 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -50,6 +50,7 @@ use std::{ time::Duration, }; use wasm_timer::Instant; +use tracing::Id; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; @@ -252,14 +253,29 @@ impl Stream for Telemetry { /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// /// [`Telemetry`] created through this object re-use connections if possible. -#[derive(Debug, Default, Clone)] +#[derive(Debug, Clone)] pub struct Telemetries { + receiver: Arc>, + sender: mpsc::Sender<(Id, u8, String)>, senders: Senders, node_pool: Arc, wasm_external_transport: Option, } impl Telemetries { + /// TODO + pub fn new() -> Self { + let (sender, receiver) = mpsc::channel(16); + + Self { + receiver: Arc::new(receiver), // TODO remove Arc + sender, + senders: Default::default(), + node_pool: Default::default(), + wasm_external_transport: None, + } + } + /// Create a [`Telemetries`] object using an `ExtTransport`. /// /// This is used in WASM contexts where we need some binding between the networking provided by @@ -273,7 +289,7 @@ impl Telemetries { pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Self { Self { wasm_external_transport: Some(wasm_external_transport), - ..Default::default() + ..Self::new() } } @@ -298,6 +314,14 @@ impl Telemetries { pub fn senders(&self) -> Senders { self.senders.clone() } + + /// TODO + pub async fn run(self) { + let mut receiver = Arc::try_unwrap(self.receiver).expect("todo, remove"); + + while let Some((id, priority, message)) = receiver.next().await { + } + } } /// Translates to `tracing::info!`, but contains an additional verbosity diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 8f3e4240b5e81..5f7232e9c3240 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -158,7 +158,7 @@ fn get_default_subscriber_and_telemetries_internal( let telemetries = if let Some(telemetry_external_transport) = telemetry_external_transport { sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) } else { - Default::default() + sc_telemetry::Telemetries::new() }; let senders = telemetries.senders(); let telemetry_layer = sc_telemetry::TelemetryLayer::new(senders); From f36606d243e1aa6497477b3df6357e4ff4c05180 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 13:17:47 +0100 Subject: [PATCH 112/222] WIP --- client/telemetry/src/lib.rs | 68 ++++++++++++++++++++++-- client/telemetry/src/worker.rs | 5 +- client/telemetry/src/worker/node_pool.rs | 8 ++- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 3fcc305631104..00aaaeb5e5a76 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -44,6 +44,7 @@ use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ + collections::HashMap, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -162,7 +163,7 @@ impl Telemetry { pub fn new( endpoints: TelemetryEndpoints, wasm_external_transport: Option, - node_pool: Option<&NodePool>, + node_pool: Option<()>, ) -> (Self, mpsc::Sender<(u8, String)>) { let endpoints = endpoints.0; @@ -171,7 +172,7 @@ impl Telemetry { let worker = match worker::TelemetryWorker::new( endpoints, wasm_external_transport, - node_pool, + None, ) { Ok(w) => Some(w), Err(err) => { @@ -257,6 +258,7 @@ impl Stream for Telemetry { pub struct Telemetries { receiver: Arc>, sender: mpsc::Sender<(Id, u8, String)>, + node_map: HashMap>, senders: Senders, node_pool: Arc, wasm_external_transport: Option, @@ -270,6 +272,7 @@ impl Telemetries { Self { receiver: Arc::new(receiver), // TODO remove Arc sender, + node_map: Default::default(), senders: Default::default(), node_pool: Default::default(), wasm_external_transport: None, @@ -301,7 +304,7 @@ impl Telemetries { let (telemetry, sender) = Telemetry::new( endpoints, self.wasm_external_transport.clone(), - Some(&self.node_pool), + None, // TODO ); let id = telemetry.span.id().expect("the span is enabled; qed"); @@ -317,9 +320,64 @@ impl Telemetries { /// TODO pub async fn run(self) { - let mut receiver = Arc::try_unwrap(self.receiver).expect("todo, remove"); + let Self { + receiver, + sender, + node_map, + senders, + node_pool, + wasm_external_transport, + } = self; + let mut receiver = Arc::try_unwrap(receiver).expect("todo, remove"); - while let Some((id, priority, message)) = receiver.next().await { + while let Some((id, verbosity, message)) = receiver.next().await { + let before = Instant::now(); + + let nodes = if let Some(nodes) = node_map.get(&id) { + nodes + } else { + log::error!( + target: "telemetry", + "Received telemetry log for unknown id ({:?}): {}", + id, + message, + ); + continue; + }; + + for (node_max_verbosity, addr) in nodes { + let node_pool = node_pool.lock(); + let node = if let Some(node) = node_pool.get(addr) { + node + } else { + log::error!( + target: "telemetry", + "Could not find telemetry server in the NodePool: {}", + addr, + ); + continue; + }; + let mut node = node.lock(); + + if verbosity > *node_max_verbosity { + log::trace!( + target: "telemetry", + "Skipping {} for log entry with verbosity {:?}", + addr, + verbosity); + continue; + } + + // `send_message` returns an error if we're not connected, which we silently ignore. + let _ = node.send_message(message.clone()); // TODO probably dont need to clone + } + + if before.elapsed() > Duration::from_millis(200) { + log::warn!( + target: "telemetry", + "Processing one telemetry message took more than 200ms", + ); + } } } } diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index f3c35d2a559b4..2a77e9fe2dc38 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -42,7 +42,7 @@ use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; mod node; pub(crate) mod node_pool; -pub use node_pool::NodePool; +pub(crate) use node_pool::NodePool; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. @@ -129,11 +129,14 @@ impl TelemetryWorker { let mut force_connected = false; let nodes = endpoints.into_iter().map(|(addr, verbosity)| { let node = if let Some(node_pool) = node_pool { + /* let (node, is_new) = node_pool.get_or_create(transport.clone(), addr); if !is_new { force_connected = true; } node + */ + todo!("remove") } else { Arc::new(Mutex::new(node::Node::new(transport.clone(), addr))) }; diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs index c3fb21216f6dd..822a82c38111b 100644 --- a/client/telemetry/src/worker/node_pool.rs +++ b/client/telemetry/src/worker/node_pool.rs @@ -18,14 +18,14 @@ use crate::worker::{node::Node, WsTrans}; use libp2p::Multiaddr; -use parking_lot::Mutex; +use parking_lot::{Mutex, MutexGuard}; use std::collections::{hash_map::Entry, HashMap}; use std::sync::Arc; #[derive(Debug, Default)] /// A collection of nodes connecting to a telemetry server and identified by address. pub struct NodePool { - nodes: Mutex>>>>, + nodes: Mutex>>>>, // TODO remove inner Arc> } impl NodePool { @@ -46,4 +46,8 @@ impl NodePool { new, ) } + + pub(crate) fn lock(&self) -> MutexGuard>>>> { + self.nodes.lock() + } } From fc9677977b2d90c3b11c101567aa8605adf76d95 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 14:35:39 +0100 Subject: [PATCH 113/222] WIP --- client/cli/src/runner.rs | 3 +- client/telemetry/src/lib.rs | 31 +++++++--- client/telemetry/src/worker.rs | 2 +- client/telemetry/src/worker/node.rs | 75 ++++++++++++++++++++++++ client/telemetry/src/worker/node_pool.rs | 9 ++- 5 files changed, 108 insertions(+), 12 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index f2a0a5445717a..e650ab23bdaec 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -139,7 +139,8 @@ impl Runner { config: command.create_configuration( cli, task_executor.into(), - telemetries.clone(), + //telemetries.clone(), + sc_telemetry::Telemetries::new(), // TODO )?, tokio_runtime, telemetries, diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 00aaaeb5e5a76..f478d1017c4a9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -44,7 +44,7 @@ use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -254,13 +254,14 @@ impl Stream for Telemetry { /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// /// [`Telemetry`] created through this object re-use connections if possible. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Telemetries { receiver: Arc>, sender: mpsc::Sender<(Id, u8, String)>, node_map: HashMap>, + connection_messages: HashMap, senders: Senders, - node_pool: Arc, + node_pool: HashMap>, // TODO mod wasm_external_transport: Option, } @@ -273,6 +274,7 @@ impl Telemetries { receiver: Arc::new(receiver), // TODO remove Arc sender, node_map: Default::default(), + connection_messages: Default::default(), senders: Default::default(), node_pool: Default::default(), wasm_external_transport: None, @@ -324,11 +326,17 @@ impl Telemetries { receiver, sender, node_map, + connection_messages, senders, - node_pool, + mut node_pool, wasm_external_transport, } = self; let mut receiver = Arc::try_unwrap(receiver).expect("todo, remove"); + let mut node_first_connect: HashSet<(Multiaddr, Id)> = node_map + .iter() + .map(|(id, addrs)| addrs.iter().map(move |(_, x)| (x.to_owned(), id.to_owned()))) + .flatten() + .collect(); while let Some((id, verbosity, message)) = receiver.next().await { let before = Instant::now(); @@ -346,8 +354,7 @@ impl Telemetries { }; for (node_max_verbosity, addr) in nodes { - let node_pool = node_pool.lock(); - let node = if let Some(node) = node_pool.get(addr) { + let mut node = if let Some(node) = node_pool.get_mut(addr) { node } else { log::error!( @@ -357,7 +364,6 @@ impl Telemetries { ); continue; }; - let mut node = node.lock(); if verbosity > *node_max_verbosity { log::trace!( @@ -368,6 +374,17 @@ impl Telemetries { continue; } + if !matches!(node.next().await, Some(crate::worker::node::NodeEvent::Connected)) { + node_first_connect.insert((addr.to_owned(), id.to_owned())); + continue; + } + + if node_first_connect.remove(&(addr.to_owned(), id.clone())) { + if let Some(message) = connection_messages.get(&id) { + let _ = node.send_message(message.clone()); // TODO probably dont need to clone + } + } + // `send_message` returns an error if we're not connected, which we silently ignore. let _ = node.send_message(message.clone()); // TODO probably dont need to clone } diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 2a77e9fe2dc38..fb22000285aaa 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -39,7 +39,7 @@ use log::{trace, error}; use parking_lot::Mutex; use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; -mod node; +pub(crate) mod node; pub(crate) mod node_pool; pub(crate) use node_pool::NodePool; diff --git a/client/telemetry/src/worker/node.rs b/client/telemetry/src/worker/node.rs index eef7ca7e81553..245b0745a5591 100644 --- a/client/telemetry/src/worker/node.rs +++ b/client/telemetry/src/worker/node.rs @@ -188,6 +188,81 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } }; + Poll::Pending + // TODO remove duplicated + } +} + +impl Stream for Node +where TTrans: Clone + Unpin, TTrans::Dial: Unpin, + TTrans::Output: Sink, Error = TSinkErr> + + Stream, TSinkErr>> + + Unpin, + TSinkErr: fmt::Debug +{ + type Item = NodeEvent; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); + self.socket = loop { + match socket { + NodeSocket::Connected(mut conn) => { + match NodeSocketConnected::poll(Pin::new(&mut conn), cx, &self.addr) { + Poll::Ready(Ok(v)) => match v {}, + Poll::Pending => { + break NodeSocket::Connected(conn) + }, + Poll::Ready(Err(err)) => { + warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); + let timeout = gen_rand_reconnect_delay(); + self.socket = NodeSocket::WaitingReconnect(timeout); + return Poll::Ready(Some(NodeEvent::Disconnected(err))) + } + } + } + NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { + Poll::Ready(Ok(sink)) => { + debug!(target: "telemetry", "✅ Connected to {}", self.addr); + let conn = NodeSocketConnected { + sink, + pending: VecDeque::new(), + need_flush: false, + timeout: None, + }; + self.socket = NodeSocket::Connected(conn); + return Poll::Ready(Some(NodeEvent::Connected)) + }, + Poll::Pending => break NodeSocket::Dialing(s), + Poll::Ready(Err(err)) => { + warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); + let timeout = gen_rand_reconnect_delay(); + socket = NodeSocket::WaitingReconnect(timeout); + } + } + NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { + Ok(d) => { + debug!(target: "telemetry", "Started dialing {}", self.addr); + socket = NodeSocket::Dialing(d); + } + Err(err) => { + warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); + let timeout = gen_rand_reconnect_delay(); + socket = NodeSocket::WaitingReconnect(timeout); + } + } + NodeSocket::WaitingReconnect(mut s) => + if let Poll::Ready(_) = Future::poll(Pin::new(&mut s), cx) { + socket = NodeSocket::ReconnectNow; + } else { + break NodeSocket::WaitingReconnect(s) + } + NodeSocket::Poisoned => { + error!(target: "telemetry", "‼️ Poisoned connection with {}", self.addr); + break NodeSocket::Poisoned + } + } + }; + Poll::Pending } } diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs index 822a82c38111b..698981e42eda8 100644 --- a/client/telemetry/src/worker/node_pool.rs +++ b/client/telemetry/src/worker/node_pool.rs @@ -25,7 +25,7 @@ use std::sync::Arc; #[derive(Debug, Default)] /// A collection of nodes connecting to a telemetry server and identified by address. pub struct NodePool { - nodes: Mutex>>>>, // TODO remove inner Arc> + nodes: HashMap>, // TODO remove inner Arc> } impl NodePool { @@ -35,6 +35,8 @@ impl NodePool { transport: WsTrans, addr: Multiaddr, ) -> (Arc>>, bool) { + todo!(); + /* let mut nodes = self.nodes.lock(); let entry = nodes.entry(addr.clone()); let new = matches!(entry, Entry::Vacant(..)); @@ -45,9 +47,10 @@ impl NodePool { .clone(), new, ) + */ } - pub(crate) fn lock(&self) -> MutexGuard>>>> { - self.nodes.lock() + pub(crate) fn lock(&mut self) -> &mut HashMap> { + &mut self.nodes } } From 89d6bd22d05d5e942f6f82c4d1fbc39dc78dedfd Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 14:54:50 +0100 Subject: [PATCH 114/222] WIP --- Cargo.lock | 1 + client/service/src/builder.rs | 11 +---------- client/service/src/lib.rs | 16 +--------------- client/telemetry/Cargo.toml | 1 + client/telemetry/src/lib.rs | 31 ++++++++++++++++++++++++++++++- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5db6dfea3363c..aad5bafd55848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7437,6 +7437,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_json", + "sp-utils", "take_mut", "tracing", "tracing-subscriber", diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index e4f36475d0d8f..bae84e83f7dcb 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -17,8 +17,7 @@ // along with this program. If not, see . use crate::{ - error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm, - TelemetryConnectionSinks, RpcHandlers, NetworkStatusSinks, + error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm, RpcHandlers, NetworkStatusSinks, start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle, metrics::MetricsService, client::{light, Client, ClientConfig}, @@ -460,8 +459,6 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { pub network_status_sinks: NetworkStatusSinks, /// A Sender for RPC requests. pub system_rpc_tx: TracingUnboundedSender>, - /// Shared Telemetry connection sinks, - pub telemetry_connection_sinks: TelemetryConnectionSinks, /// Telemetry object. pub telemetry: Option, } @@ -543,7 +540,6 @@ pub fn spawn_tasks( network, network_status_sinks, system_rpc_tx, - telemetry_connection_sinks, telemetry, } = params; @@ -559,7 +555,6 @@ pub fn spawn_tasks( spawn_telemetry_worker( telemetry, &mut config, - telemetry_connection_sinks.clone(), network.clone(), task_manager.spawn_handle(), client.clone(), @@ -677,7 +672,6 @@ fn init_telemetry(config: &Configuration) -> Option { fn spawn_telemetry_worker>( telemetry: sc_telemetry::Telemetry, config: &mut Configuration, - telemetry_connection_sinks: TelemetryConnectionSinks, network: Arc::Hash>>, spawn_handle: SpawnTaskHandle, client: Arc, @@ -716,9 +710,6 @@ fn spawn_telemetry_worker>( "network_id" => network_id.clone() ); - telemetry_connection_sinks.0.lock().retain(|sink| { - sink.unbounded_send(()).is_ok() - }); ready(()) }) ); diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index bf6b280d34c75..a4a3b883a6c93 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -39,7 +39,6 @@ use std::net::SocketAddr; use std::collections::HashMap; use std::time::Duration; use std::task::Poll; -use parking_lot::Mutex; use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*}; use sc_network::{NetworkStatus, network_state::NetworkState, PeerId}; @@ -48,7 +47,7 @@ use codec::{Encode, Decode}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use parity_util_mem::MallocSizeOf; -use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; +use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver}}; pub use self::error::Error; pub use self::builder::{ @@ -160,19 +159,6 @@ impl NetworkStatusSinks { } -/// Sinks to propagate telemetry connection established events. -#[derive(Default, Clone)] -pub struct TelemetryConnectionSinks(Arc>>>); - -impl TelemetryConnectionSinks { - /// Get event stream for telemetry connection established events. - pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { - let (sink, stream) =tracing_unbounded("mpsc_telemetry_on_connect"); - self.0.lock().push(sink); - stream - } -} - /// An imcomplete set of chain components, but enough to run the chain ops subcommands. pub struct PartialComponents { /// A shared client instance. diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 9ca15e2d78f9a..c238314201d91 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -30,3 +30,4 @@ tracing = "0.1.10" tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" +sp-utils = { version = "2.0.0", path = "../../primitives/utils" } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f478d1017c4a9..e0da442ac233c 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -52,6 +52,8 @@ use std::{ }; use wasm_timer::Instant; use tracing::Id; +use parking_lot::Mutex; +use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; @@ -260,6 +262,7 @@ pub struct Telemetries { sender: mpsc::Sender<(Id, u8, String)>, node_map: HashMap>, connection_messages: HashMap, + connection_sinks: HashMap, senders: Senders, node_pool: HashMap>, // TODO mod wasm_external_transport: Option, @@ -275,6 +278,7 @@ impl Telemetries { sender, node_map: Default::default(), connection_messages: Default::default(), + connection_sinks: Default::default(), senders: Default::default(), node_pool: Default::default(), wasm_external_transport: None, @@ -327,6 +331,7 @@ impl Telemetries { sender, node_map, connection_messages, + connection_sinks, senders, mut node_pool, wasm_external_transport, @@ -354,7 +359,7 @@ impl Telemetries { }; for (node_max_verbosity, addr) in nodes { - let mut node = if let Some(node) = node_pool.get_mut(addr) { + let node = if let Some(node) = node_pool.get_mut(addr) { node } else { log::error!( @@ -374,12 +379,17 @@ impl Telemetries { continue; } + // Disconnection if !matches!(node.next().await, Some(crate::worker::node::NodeEvent::Connected)) { node_first_connect.insert((addr.to_owned(), id.to_owned())); continue; } + // Reconnection handling if node_first_connect.remove(&(addr.to_owned(), id.clone())) { + if let Some(connection_sink) = connection_sinks.get(&id) { + connection_sink.fire(); + } if let Some(message) = connection_messages.get(&id) { let _ = node.send_message(message.clone()); // TODO probably dont need to clone } @@ -399,6 +409,25 @@ impl Telemetries { } } +/// Sinks to propagate telemetry connection established events. +#[derive(Default, Clone, Debug)] +pub struct TelemetryConnectionSinks(Arc>>>); + +impl TelemetryConnectionSinks { + /// Get event stream for telemetry connection established events. + pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { + let (sink, stream) =tracing_unbounded("mpsc_telemetry_on_connect"); + self.0.lock().push(sink); + stream + } + + pub(crate) fn fire(&self) { + self.0.lock().retain(|sink| { + sink.unbounded_send(()).is_ok() + }); + } +} + /// Translates to `tracing::info!`, but contains an additional verbosity /// parameter which the log record is tagged with. Additionally the verbosity /// parameter is added to the record as a key-value pair. From ee6397434e9135419c9c670b27fdd97971a966fc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 15:36:17 +0100 Subject: [PATCH 115/222] WIP --- client/cli/src/runner.rs | 11 +++++++++-- client/telemetry/src/lib.rs | 9 ++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index e650ab23bdaec..ccac6a3923a9c 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -27,6 +27,7 @@ use log::info; use sc_service::{Configuration, TaskType, TaskManager}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; +use std::sync::Arc; #[cfg(target_family = "unix")] async fn main(func: F) -> std::result::Result<(), Box> @@ -112,7 +113,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetries: sc_telemetry::Telemetries, + telemetries: Arc, phantom: PhantomData, } @@ -134,6 +135,7 @@ impl Runner { .map(drop), } }; + let telemetries = Arc::new(telemetries); Ok(Runner { config: command.create_configuration( @@ -189,7 +191,12 @@ impl Runner { ) -> Result<()> { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; - task_manager.spawn_handle().spawn("telemetries", self.telemetries.run()); + let telemetries = Arc::try_unwrap(self.telemetries) + .map_err(|_| String::from( + "Could not initialize telemetries! \ + Maybe some node Configuration are pending?" + ))?; + task_manager.spawn_handle().spawn("telemetries", telemetries.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); res.map_err(|e| e.to_string().into()) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index e0da442ac233c..033a873498806 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -258,12 +258,12 @@ impl Stream for Telemetry { /// [`Telemetry`] created through this object re-use connections if possible. #[derive(Debug)] pub struct Telemetries { - receiver: Arc>, + receiver: mpsc::Receiver<(Id, u8, String)>, sender: mpsc::Sender<(Id, u8, String)>, node_map: HashMap>, connection_messages: HashMap, connection_sinks: HashMap, - senders: Senders, + senders: Senders, // TODO remove node_pool: HashMap>, // TODO mod wasm_external_transport: Option, } @@ -274,7 +274,7 @@ impl Telemetries { let (sender, receiver) = mpsc::channel(16); Self { - receiver: Arc::new(receiver), // TODO remove Arc + receiver, sender, node_map: Default::default(), connection_messages: Default::default(), @@ -327,7 +327,7 @@ impl Telemetries { /// TODO pub async fn run(self) { let Self { - receiver, + mut receiver, sender, node_map, connection_messages, @@ -336,7 +336,6 @@ impl Telemetries { mut node_pool, wasm_external_transport, } = self; - let mut receiver = Arc::try_unwrap(receiver).expect("todo, remove"); let mut node_first_connect: HashSet<(Multiaddr, Id)> = node_map .iter() .map(|(id, addrs)| addrs.iter().map(move |(_, x)| (x.to_owned(), id.to_owned()))) From df1778d5a6fbda48d142afac4bda02c91b33e9c7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 15:47:43 +0100 Subject: [PATCH 116/222] WIP --- client/telemetry/src/layer.rs | 57 +++++++++++++++---------------- client/telemetry/src/lib.rs | 12 +++---- client/tracing/src/logging/mod.rs | 4 +-- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index ef0fd4c0c29dd..f089fd97ccb07 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -29,12 +29,12 @@ pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; /// `Layer` that handles the logs for telemetries. #[derive(Debug)] -pub struct TelemetryLayer(Senders); +pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. - pub fn new(senders: Senders) -> Self { - Self(senders) + pub fn new(sender: mpsc::Sender<(Id, u8, String)>) -> Self { + Self(Mutex::new(sender)) } } @@ -55,32 +55,31 @@ where .find(|x| x.name() == TELEMETRY_LOG_SPAN) { let id = span.id(); - if let Some(sender) = (self.0).0.lock().get_mut(&id) { - let mut attrs = TelemetryAttrs::new(id); - let mut vis = TelemetryAttrsVisitor(&mut attrs); - event.record(&mut vis); - - if let TelemetryAttrs { - verbosity: Some(verbosity), - json: Some(json), - .. - } = attrs - { - let _ = sender.try_send(( - verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )); - } else { - // NOTE: logging in this function doesn't work - eprintln!( - "missing fields in telemetry log: {:?}. This can happen if \ - `tracing::info_span!` is (mis-)used with the telemetry target \ - directly; you should use the `telemetry!` macro.", - event, - ); - } + let mut attrs = TelemetryAttrs::new(id.clone()); + let mut vis = TelemetryAttrsVisitor(&mut attrs); + event.record(&mut vis); + + if let TelemetryAttrs { + verbosity: Some(verbosity), + json: Some(json), + .. + } = attrs + { + let _ = self.0.lock().try_send(( + id, + verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )); + } else { + // NOTE: logging in this function doesn't work + eprintln!( + "missing fields in telemetry log: {:?}. This can happen if \ + `tracing::info_span!` is (mis-)used with the telemetry target \ + directly; you should use the `telemetry!` macro.", + event, + ); } } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 033a873498806..25c85840daeb9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -263,7 +263,6 @@ pub struct Telemetries { node_map: HashMap>, connection_messages: HashMap, connection_sinks: HashMap, - senders: Senders, // TODO remove node_pool: HashMap>, // TODO mod wasm_external_transport: Option, } @@ -279,7 +278,6 @@ impl Telemetries { node_map: Default::default(), connection_messages: Default::default(), connection_sinks: Default::default(), - senders: Default::default(), node_pool: Default::default(), wasm_external_transport: None, } @@ -314,14 +312,15 @@ impl Telemetries { ); let id = telemetry.span.id().expect("the span is enabled; qed"); - self.senders.insert(id, sender); + //self.senders.insert(id, sender); + // TODO telemetry } - /// Get a clone of the channel's [`Senders`]. - pub fn senders(&self) -> Senders { - self.senders.clone() + /// TODO + pub fn sender(&self) -> mpsc::Sender<(Id, u8, String)> { + self.sender.clone() } /// TODO @@ -332,7 +331,6 @@ impl Telemetries { node_map, connection_messages, connection_sinks, - senders, mut node_pool, wasm_external_transport, } = self; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 5f7232e9c3240..ee7668f19df9f 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -160,8 +160,8 @@ fn get_default_subscriber_and_telemetries_internal( } else { sc_telemetry::Telemetries::new() }; - let senders = telemetries.senders(); - let telemetry_layer = sc_telemetry::TelemetryLayer::new(senders); + let sender = telemetries.sender(); + let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); let event_format = EventFormat { timer, display_target: !simple, From b67ff7dac0135e74fed37da3f8329b1a68599d5e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 16:49:14 +0100 Subject: [PATCH 117/222] WIP --- client/service/src/builder.rs | 82 +++++++++++--------------------- client/telemetry/src/lib.rs | 85 ++++++++++++++++++++++++++++------ client/telemetry/src/worker.rs | 4 +- 3 files changed, 100 insertions(+), 71 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index bae84e83f7dcb..726ba16a97fbf 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -50,7 +50,7 @@ use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, TelemetryConnectionSinks, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; @@ -177,7 +177,6 @@ type TFullParts = ( Arc>, KeystoreContainer, TaskManager, - Option, ); type TLightParts = ( @@ -186,7 +185,6 @@ type TLightParts = ( KeystoreContainer, TaskManager, Arc>, - Option, ); /// Light client backend type with a specific hash type. @@ -273,7 +271,6 @@ pub fn new_full_parts( TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - let telemetry = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { @@ -332,7 +329,6 @@ pub fn new_full_parts( backend, keystore_container, task_manager, - telemetry, )) } @@ -343,7 +339,6 @@ pub fn new_light_parts( TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, { - let telemetry = init_telemetry(&config); let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); @@ -384,7 +379,7 @@ pub fn new_light_parts( config.prometheus_config.as_ref().map(|config| config.registry.clone()), )?); - Ok((client, backend, keystore_container, task_manager, on_demand, telemetry)) + Ok((client, backend, keystore_container, task_manager, on_demand)) } /// Create an instance of db-backed client. @@ -459,8 +454,6 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { pub network_status_sinks: NetworkStatusSinks, /// A Sender for RPC requests. pub system_rpc_tx: TracingUnboundedSender>, - /// Telemetry object. - pub telemetry: Option, } /// Build a shared offchain workers instance. @@ -507,7 +500,7 @@ pub fn build_offchain_workers( /// Spawn the tasks that are required to run a node. pub fn spawn_tasks( params: SpawnTasksParams, -) -> Result +) -> Result<(RpcHandlers, Option), Error> where TCl: ProvideRuntimeApi + HeaderMetadata + Chain + BlockBackend + BlockIdTo + ProofProvider + @@ -540,7 +533,6 @@ pub fn spawn_tasks( network, network_status_sinks, system_rpc_tx, - telemetry, } = params; let chain_info = client.usage_info().chain; @@ -551,15 +543,11 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - if let Some(telemetry) = telemetry { - spawn_telemetry_worker( - telemetry, - &mut config, - network.clone(), - task_manager.spawn_handle(), - client.clone(), - ); - } + let telemetry_connection_sinks = init_telemetry( + &mut config, + network.clone(), + client.clone(), + )?; info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( @@ -635,7 +623,7 @@ pub fn spawn_tasks( task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone())); - Ok(rpc_handlers) + Ok((rpc_handlers, telemetry_connection_sinks)) } async fn transaction_notifications( @@ -660,22 +648,17 @@ async fn transaction_notifications( .await; } -fn init_telemetry(config: &Configuration) -> Option { +fn init_telemetry>( + config: &mut Configuration, + network: Arc::Hash>>, + client: Arc, +) -> Result, std::io::Error> { let endpoints = match config.telemetry_endpoints.clone() { // Don't initialise telemetry if `telemetry_endpoints` == Some([]) Some(endpoints) if !endpoints.is_empty() => endpoints, - _ => return None, + _ => return Ok(None), }; - Some(config.telemetries.build_telemetry(endpoints)) -} -fn spawn_telemetry_worker>( - telemetry: sc_telemetry::Telemetry, - config: &mut Configuration, - network: Arc::Hash>>, - spawn_handle: SpawnTaskHandle, - client: Arc, -) { let genesis_hash = match client.block_hash(Zero::zero()) { Ok(Some(hash)) => hash, _ => Default::default(), @@ -691,28 +674,19 @@ fn spawn_telemetry_worker>( .map(|dur| dur.as_millis()) .unwrap_or(0); - spawn_handle.spawn( - "telemetry-worker", - telemetry - .for_each(move |event| { - // Safe-guard in case we add more events in the future. - let sc_telemetry::TelemetryEvent::Connected = event; - - telemetry!(SUBSTRATE_INFO; "system.connected"; - "name" => name.clone(), - "implementation" => impl_name.clone(), - "version" => impl_version.clone(), - "config" => "", - "chain" => chain_name.clone(), - "genesis_hash" => ?genesis_hash, - "authority" => is_authority, - "startup_time" => startup_time.to_string(), - "network_id" => network_id.clone() - ); - - ready(()) - }) - ); + let json = serde_json::json! {{ + "name": name.clone(), + "implementation": impl_name.clone(), + "version": impl_version.clone(), + "config": "", + "chain": chain_name.clone(), + "genesis_hash": format!("{:?}", genesis_hash), + "authority": is_authority, + "startup_time": startup_time.to_string(), + "network_id": network_id.clone() + }}; + + Some(config.telemetries.start_telemetry(endpoints, json)).transpose() } fn gen_handler( diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 25c85840daeb9..4916542d86e70 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -40,11 +40,15 @@ #![warn(missing_docs)] use futures::{channel::mpsc, prelude::*}; -use libp2p::{wasm_ext, Multiaddr}; +use libp2p::{ + core::transport::{OptionalTransport, timeout::TransportTimeout}, + wasm_ext, Multiaddr, Transport, +}; use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ collections::{HashMap, HashSet}, + io, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -65,6 +69,7 @@ pub mod worker; pub use layer::*; use worker::node_pool::*; +use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod /// List of telemetry servers we want to talk to. Contains the URL of the server, and the /// maximum verbosity level. @@ -261,7 +266,7 @@ pub struct Telemetries { receiver: mpsc::Receiver<(Id, u8, String)>, sender: mpsc::Sender<(Id, u8, String)>, node_map: HashMap>, - connection_messages: HashMap, + connection_messages: HashMap, connection_sinks: HashMap, node_pool: HashMap>, // TODO mod wasm_external_transport: Option, @@ -303,19 +308,65 @@ impl Telemetries { /// Create a new [`Telemetry`] for the endpoints provided in argument. /// /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding - /// verbosity level. - pub fn build_telemetry(&self, endpoints: TelemetryEndpoints) -> Telemetry { - let (telemetry, sender) = Telemetry::new( - endpoints, - self.wasm_external_transport.clone(), - None, // TODO - ); - let id = telemetry.span.id().expect("the span is enabled; qed"); + /// verbosity level. TODO doc + pub fn start_telemetry( + &mut self, + endpoints: TelemetryEndpoints, + connection_message: serde_json::Value, + ) -> Result { + let endpoints = endpoints.0; + + let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let id = span.id().expect("the span is enabled; qed"); + { + let id = id.clone(); + tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)); + } + let transport = match self.wasm_external_transport.clone() { + Some(t) => OptionalTransport::some(t), + None => OptionalTransport::none() + }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); + + // The main transport is the `wasm_external_transport`, but if we're on desktop we add + // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass + // an external transport on desktop and the fallback is used all the time. + #[cfg(not(target_os = "unknown"))] + let transport = transport.or_transport({ + let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; + libp2p::websocket::framed::WsConfig::new(inner) + .and_then(|connec, _| { + let connec = connec + .with(|item| { + let item = libp2p::websocket::framed::OutgoingData::Binary(item); + future::ready(Ok::<_, io::Error>(item)) + }) + .try_filter(|item| future::ready(item.is_data())) + .map_ok(|data| data.into_bytes()); + future::ready(Ok::<_, io::Error>(connec)) + }) + }); + + let transport = TransportTimeout::new( + transport.map(|out, _| { + let out = out + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); + Box::pin(out) as Pin> + }), + CONNECT_TIMEOUT + ).boxed(); + + for (addr, verbosity) in endpoints { + let node = crate::worker::node::Node::new(transport.clone(), addr.clone()); + self.node_pool.insert(addr.clone(), node); + self.node_map.entry(id.clone()).or_insert_with(Vec::new) + .push((verbosity, addr)); + } - //self.senders.insert(id, sender); - // TODO + let connection_sink = TelemetryConnectionSinks::default(); + self.connection_sinks.insert(id.clone(), connection_sink.clone()); - telemetry + Ok(connection_sink) } /// TODO @@ -387,8 +438,12 @@ impl Telemetries { if let Some(connection_sink) = connection_sinks.get(&id) { connection_sink.fire(); } - if let Some(message) = connection_messages.get(&id) { - let _ = node.send_message(message.clone()); // TODO probably dont need to clone + if let Some(json) = connection_messages.get(&id) { + let mut json = json.clone(); + let obj = json.as_object_mut().expect("todo"); + obj.insert("msg".into(), "system.connected".into()); + obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); + let _ = node.send_message(serde_json::to_string(obj).expect("todo")); } } diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index fb22000285aaa..4fe01d179ff81 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -46,7 +46,7 @@ pub(crate) use node_pool::NodePool; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. -const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); +pub(crate) const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); /// Event generated when polling the worker. #[derive(Debug)] @@ -205,7 +205,7 @@ impl TelemetryWorker { /// For some context, we put this object around the `wasm_ext::ExtTransport` in order to make sure /// that each telemetry message maps to one single call to `write` in the WASM FFI. #[pin_project::pin_project] -struct StreamSink(#[pin] T, Option>); +pub(crate) struct StreamSink(#[pin] T, Option>); impl From for StreamSink { fn from(inner: T) -> StreamSink { From 3f6f8eb76402ffb65aa0d3a632c1bebb068a3eed Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 2 Dec 2020 17:04:07 +0100 Subject: [PATCH 118/222] WIP --- Cargo.lock | 1 + bin/node-template/node/src/service.rs | 15 ++++----------- bin/node/cli/src/browser.rs | 2 +- bin/node/cli/src/service.rs | 24 +++++++++--------------- client/service/src/lib.rs | 2 -- client/service/test/Cargo.toml | 1 + client/service/test/src/lib.rs | 2 +- 7 files changed, 17 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aad5bafd55848..8df94f7ee29db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7374,6 +7374,7 @@ dependencies = [ "sc-light", "sc-network", "sc-service", + "sc-telemetry", "sp-api", "sp-blockchain", "sp-consensus", diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 4cbecd7dab7ae..f7c596ef0b11f 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -39,7 +39,7 @@ pub fn new_partial(config: &Configuration) -> Result, ServiceError> { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager, telemetry) = + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -80,7 +80,6 @@ pub fn new_partial(config: &Configuration) -> Result Result { select_chain, transaction_pool, inherent_data_providers, - telemetry, other: (block_import, grandpa_link), } = new_partial(&config)?; @@ -123,7 +121,6 @@ pub fn new_full(config: Configuration) -> Result { let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { let client = client.clone(); @@ -140,13 +137,12 @@ pub fn new_full(config: Configuration) -> Result { }) }; - sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let (_rpc_handlers, telemetry_connection_sinks) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), - telemetry_connection_sinks: telemetry_connection_sinks.clone(), rpc_extensions_builder, on_demand: None, remote_blockchain: None, @@ -154,7 +150,6 @@ pub fn new_full(config: Configuration) -> Result { network_status_sinks, system_rpc_tx, config, - telemetry, })?; if role.is_authority() { @@ -216,7 +211,7 @@ pub fn new_full(config: Configuration) -> Result { config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), + telemetry_on_connect: telemetry_connection_sinks.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), @@ -238,7 +233,7 @@ pub fn new_full(config: Configuration) -> Result { /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand, telemetry) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -296,7 +291,6 @@ pub fn new_light(config: Configuration) -> Result { task_manager: &mut task_manager, on_demand: Some(on_demand), rpc_extensions_builder: Box::new(|_, _| ()), - telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, keystore: keystore_container.sync_keystore(), @@ -304,7 +298,6 @@ pub fn new_light(config: Configuration) -> Result { network, network_status_sinks, system_rpc_tx, - telemetry, })?; network_starter.start_network(); diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 0a27415867bbc..c8bf2e2ab8c92 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -53,7 +53,7 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu // Create the service. This is the most heavy initialization step. let (task_manager, rpc_handlers) = crate::service::new_light_base(config) - .map(|(components, rpc_handlers, _, _, _)| (components, rpc_handlers)) + .map(|(components, rpc_handlers, _, _, _, _)| (components, rpc_handlers)) .map_err(|e| format!("{:?}", e))?; Ok(browser_utils::start_client(task_manager, rpc_handlers)) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 5013050589eea..178d85b495b8b 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -34,6 +34,7 @@ use sp_runtime::traits::Block as BlockT; use futures::prelude::*; use sc_client_api::{ExecutorProvider, RemoteBackend}; use node_executor::Executor; +use sc_telemetry::TelemetryConnectionSinks; type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; @@ -59,7 +60,7 @@ pub fn new_partial(config: &Configuration) -> Result, ServiceError> { - let (client, backend, keystore_container, task_manager, telemetry) = + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -155,7 +156,6 @@ pub fn new_partial(config: &Configuration) -> Result Result<( - TaskManager, RpcHandlers, Arc, + TaskManager, RpcHandlers, TelemetryConnectionSinks, Arc, Arc::Hash>>, Arc>> ), ServiceError> { - let (client, backend, keystore_container, mut task_manager, on_demand, telemetry) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -425,7 +421,7 @@ pub fn new_light_base(config: Configuration) -> Result<( let rpc_extensions = node_rpc::create_light(light_deps); - let rpc_handlers = + let (rpc_handlers, telemetry_connection_sinks) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { on_demand: Some(on_demand), remote_blockchain: Some(backend.remote_blockchain()), @@ -435,17 +431,15 @@ pub fn new_light_base(config: Configuration) -> Result<( keystore: keystore_container.sync_keystore(), config, backend, network_status_sinks, system_rpc_tx, network: network.clone(), - telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), task_manager: &mut task_manager, - telemetry, })?; - Ok((task_manager, rpc_handlers, client, network, transaction_pool)) + Ok((task_manager, rpc_handlers, telemetry_connection_sinks.unwrap_or_default(), client, network, transaction_pool)) } /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - new_light_base(config).map(|(task_manager, _, _, _, _)| { + new_light_base(config).map(|(task_manager, _, _, _, _, _)| { task_manager }) } diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index a4a3b883a6c93..23204b7b62cb1 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -177,8 +177,6 @@ pub struct PartialComponents, /// A registry of all providers of `InherentData`. pub inherent_data_providers: sp_inherents::InherentDataProviders, - /// Telemetry object. - pub telemetry: Option, /// Everything else that needs to be passed into the main build function. pub other: Other, } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 84ac84e630d00..cfb8d72240e5b 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -29,6 +29,7 @@ sp-storage = { version = "2.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.8.0", default-features = false, path = "../../db" } futures = { version = "0.3.1", features = ["compat"] } sc-service = { version = "0.8.0", default-features = false, features = ["test-helpers"], path = "../../service" } +sc-telemetry = { version = "2.0.0", default-features = false, path = "../../telemetry" } sc-network = { version = "0.8.0", path = "../../network" } sp-consensus = { version = "0.8.0", path = "../../../primitives/consensus/common" } sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 370ccac62e9be..bd2d1e965c139 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,7 +263,7 @@ fn node_config Date: Thu, 3 Dec 2020 12:03:43 +0100 Subject: [PATCH 119/222] WIP --- client/telemetry/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 4916542d86e70..f6de3b96a29b3 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -320,6 +320,7 @@ impl Telemetries { let id = span.id().expect("the span is enabled; qed"); { let id = id.clone(); + // TODO where to drop span? tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)); } let transport = match self.wasm_external_transport.clone() { From 5cf613f5e6ddcf43f1ecb6fdd2fb64bd64d13feb Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 12:04:31 +0100 Subject: [PATCH 120/222] Using Arc> --- Cargo.lock | 2 ++ client/cli/Cargo.toml | 1 + client/cli/src/config.rs | 4 +++- client/cli/src/lib.rs | 4 +++- client/cli/src/runner.rs | 16 +++++++++------- client/service/src/builder.rs | 2 +- client/service/src/config.rs | 3 ++- client/service/test/src/lib.rs | 2 +- client/telemetry/src/lib.rs | 3 ++- utils/browser/Cargo.toml | 1 + utils/browser/src/lib.rs | 8 +++++--- 11 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8df94f7ee29db..3220fda3fa15a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6472,6 +6472,7 @@ dependencies = [ "log", "names", "parity-scale-codec", + "parking_lot 0.10.2", "rand 0.7.3", "regex", "rpassword", @@ -8796,6 +8797,7 @@ dependencies = [ "kvdb-web", "libp2p-wasm-ext", "log", + "parking_lot 0.10.2", "rand 0.6.5", "rand 0.7.3", "sc-chain-spec", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index fd5a5e1f0c9b2..34a86d8a20ec7 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -44,6 +44,7 @@ chrono = "0.4.10" serde = "1.0.111" tracing = "0.1.22" thiserror = "1.0.21" +parking_lot = "0.10.0" [target.'cfg(not(target_os = "unknown"))'.dependencies] rpassword = "5.0.0" diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index c16772cfb49e6..5847b24c7595d 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -26,6 +26,7 @@ use crate::{ }; use log::warn; use names::{Generator, Name}; +use parking_lot::Mutex; use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::config::{ BasePath, Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration, @@ -35,6 +36,7 @@ use sc_service::config::{ use sc_service::{ChainSpec, TracingReceiver}; use std::net::SocketAddr; use std::path::PathBuf; +use std::sync::Arc; /// The maximum number of characters for a node name. pub(crate) const NODE_NAME_MAX_LENGTH: usize = 64; @@ -455,7 +457,7 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, - telemetries: sc_telemetry::Telemetries, + telemetries: Arc>, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 06c195ddba7d7..d5bd714f0d231 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -38,6 +38,8 @@ pub use runner::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; pub use sp_version::RuntimeVersion; +use parking_lot::Mutex; +use std::sync::Arc; use std::io::Write; pub use structopt; use structopt::{ @@ -215,7 +217,7 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, - telemetries: sc_telemetry::Telemetries, + telemetries: Arc>, ) -> error::Result { command.create_configuration(self, task_executor, telemetries) } diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index ccac6a3923a9c..d4b1ae51810a1 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -24,6 +24,7 @@ use futures::pin_mut; use futures::select; use futures::{future, future::FutureExt, Future}; use log::info; +use parking_lot::Mutex; use sc_service::{Configuration, TaskType, TaskManager}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; @@ -113,7 +114,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetries: Arc, + telemetries: Arc>, phantom: PhantomData, } @@ -135,14 +136,13 @@ impl Runner { .map(drop), } }; - let telemetries = Arc::new(telemetries); + let telemetries = Arc::new(Mutex::new(telemetries)); Ok(Runner { config: command.create_configuration( cli, task_executor.into(), - //telemetries.clone(), - sc_telemetry::Telemetries::new(), // TODO + telemetries.clone(), )?, tokio_runtime, telemetries, @@ -192,10 +192,12 @@ impl Runner { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; let telemetries = Arc::try_unwrap(self.telemetries) - .map_err(|_| String::from( - "Could not initialize telemetries! \ - Maybe some node Configuration are pending?" + .map_err(|arc| format!( + "Could not initialize telemetries! There are still {} node Configuration pending. \ + You must run them or drop them.", + Arc::strong_count(&arc), ))?; + let telemetries = telemetries.into_inner(); task_manager.spawn_handle().spawn("telemetries", telemetries.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 726ba16a97fbf..a70c03316b24c 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -686,7 +686,7 @@ fn init_telemetry>( "network_id": network_id.clone() }}; - Some(config.telemetries.start_telemetry(endpoints, json)).transpose() + Some(config.telemetries.lock().start_telemetry(endpoints, json)).transpose() } fn gen_handler( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 62dd71d90ed9f..3f4de9906dfb1 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -32,6 +32,7 @@ pub use sc_telemetry::TelemetryEndpoints; use prometheus_endpoint::Registry; #[cfg(not(target_os = "unknown"))] use tempfile::TempDir; +use parking_lot::Mutex; /// Service configuration. #[derive(Debug)] @@ -88,7 +89,7 @@ pub struct Configuration { /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, /// All the telemetries. - pub telemetries: sc_telemetry::Telemetries, + pub telemetries: Arc>, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index bd2d1e965c139..7e51b432577ee 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,7 +263,7 @@ fn node_config>()), message, ); continue; diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 719db06493c37..e948fc64244c3 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -30,6 +30,7 @@ sc-network = { path = "../../client/network", version = "0.8.0"} sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0"} sc-telemetry = { path = "../../client/telemetry", version = "2.0.0"} sc-tracing = { path = "../../client/tracing", version = "2.0.0"} +parking_lot = "0.10.0" # Imported just for the `wasm-bindgen` feature rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index fd9a758e66abb..5f89ba9721f86 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -28,8 +28,10 @@ use futures::{ prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select} }; use std::pin::Pin; +use std::sync::Arc; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; +use parking_lot::Mutex; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; @@ -39,7 +41,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { +) -> Result<(Arc>, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, @@ -49,7 +51,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok((telemetries, transport)) + Ok((Arc::new(Mutex::new(telemetries)), transport)) } /// Create a service configuration from a chain spec. @@ -57,7 +59,7 @@ pub fn init_logging_and_telemetry( /// This configuration contains good defaults for a browser light client. pub async fn browser_configuration( chain_spec: GenericChainSpec, - telemetries: sc_telemetry::Telemetries, + telemetries: Arc>, transport: ExtTransport, ) -> Result> where From 8addedd56f2d87f1056da8196a2c127731182e66 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 12:04:48 +0100 Subject: [PATCH 121/222] Revert "Using Arc>" This reverts commit 5cf613f5e6ddcf43f1ecb6fdd2fb64bd64d13feb. --- Cargo.lock | 2 -- client/cli/Cargo.toml | 1 - client/cli/src/config.rs | 4 +--- client/cli/src/lib.rs | 4 +--- client/cli/src/runner.rs | 16 +++++++--------- client/service/src/builder.rs | 2 +- client/service/src/config.rs | 3 +-- client/service/test/src/lib.rs | 2 +- client/telemetry/src/lib.rs | 3 +-- utils/browser/Cargo.toml | 1 - utils/browser/src/lib.rs | 8 +++----- 11 files changed, 16 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3220fda3fa15a..8df94f7ee29db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6472,7 +6472,6 @@ dependencies = [ "log", "names", "parity-scale-codec", - "parking_lot 0.10.2", "rand 0.7.3", "regex", "rpassword", @@ -8797,7 +8796,6 @@ dependencies = [ "kvdb-web", "libp2p-wasm-ext", "log", - "parking_lot 0.10.2", "rand 0.6.5", "rand 0.7.3", "sc-chain-spec", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 34a86d8a20ec7..fd5a5e1f0c9b2 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -44,7 +44,6 @@ chrono = "0.4.10" serde = "1.0.111" tracing = "0.1.22" thiserror = "1.0.21" -parking_lot = "0.10.0" [target.'cfg(not(target_os = "unknown"))'.dependencies] rpassword = "5.0.0" diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 5847b24c7595d..c16772cfb49e6 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -26,7 +26,6 @@ use crate::{ }; use log::warn; use names::{Generator, Name}; -use parking_lot::Mutex; use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::config::{ BasePath, Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration, @@ -36,7 +35,6 @@ use sc_service::config::{ use sc_service::{ChainSpec, TracingReceiver}; use std::net::SocketAddr; use std::path::PathBuf; -use std::sync::Arc; /// The maximum number of characters for a node name. pub(crate) const NODE_NAME_MAX_LENGTH: usize = 64; @@ -457,7 +455,7 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, - telemetries: Arc>, + telemetries: sc_telemetry::Telemetries, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index d5bd714f0d231..06c195ddba7d7 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -38,8 +38,6 @@ pub use runner::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; pub use sp_version::RuntimeVersion; -use parking_lot::Mutex; -use std::sync::Arc; use std::io::Write; pub use structopt; use structopt::{ @@ -217,7 +215,7 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, - telemetries: Arc>, + telemetries: sc_telemetry::Telemetries, ) -> error::Result { command.create_configuration(self, task_executor, telemetries) } diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index d4b1ae51810a1..ccac6a3923a9c 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -24,7 +24,6 @@ use futures::pin_mut; use futures::select; use futures::{future, future::FutureExt, Future}; use log::info; -use parking_lot::Mutex; use sc_service::{Configuration, TaskType, TaskManager}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; @@ -114,7 +113,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetries: Arc>, + telemetries: Arc, phantom: PhantomData, } @@ -136,13 +135,14 @@ impl Runner { .map(drop), } }; - let telemetries = Arc::new(Mutex::new(telemetries)); + let telemetries = Arc::new(telemetries); Ok(Runner { config: command.create_configuration( cli, task_executor.into(), - telemetries.clone(), + //telemetries.clone(), + sc_telemetry::Telemetries::new(), // TODO )?, tokio_runtime, telemetries, @@ -192,12 +192,10 @@ impl Runner { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; let telemetries = Arc::try_unwrap(self.telemetries) - .map_err(|arc| format!( - "Could not initialize telemetries! There are still {} node Configuration pending. \ - You must run them or drop them.", - Arc::strong_count(&arc), + .map_err(|_| String::from( + "Could not initialize telemetries! \ + Maybe some node Configuration are pending?" ))?; - let telemetries = telemetries.into_inner(); task_manager.spawn_handle().spawn("telemetries", telemetries.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index a70c03316b24c..726ba16a97fbf 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -686,7 +686,7 @@ fn init_telemetry>( "network_id": network_id.clone() }}; - Some(config.telemetries.lock().start_telemetry(endpoints, json)).transpose() + Some(config.telemetries.start_telemetry(endpoints, json)).transpose() } fn gen_handler( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 3f4de9906dfb1..62dd71d90ed9f 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -32,7 +32,6 @@ pub use sc_telemetry::TelemetryEndpoints; use prometheus_endpoint::Registry; #[cfg(not(target_os = "unknown"))] use tempfile::TempDir; -use parking_lot::Mutex; /// Service configuration. #[derive(Debug)] @@ -89,7 +88,7 @@ pub struct Configuration { /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, /// All the telemetries. - pub telemetries: Arc>, + pub telemetries: sc_telemetry::Telemetries, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 7e51b432577ee..bd2d1e965c139 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,7 +263,7 @@ fn node_config>()), + id, message, ); continue; diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index e948fc64244c3..719db06493c37 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -30,7 +30,6 @@ sc-network = { path = "../../client/network", version = "0.8.0"} sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0"} sc-telemetry = { path = "../../client/telemetry", version = "2.0.0"} sc-tracing = { path = "../../client/tracing", version = "2.0.0"} -parking_lot = "0.10.0" # Imported just for the `wasm-bindgen` feature rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 5f89ba9721f86..fd9a758e66abb 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -28,10 +28,8 @@ use futures::{ prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select} }; use std::pin::Pin; -use std::sync::Arc; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; -use parking_lot::Mutex; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; @@ -41,7 +39,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result<(Arc>, ExtTransport), String> { +) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, @@ -51,7 +49,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok((Arc::new(Mutex::new(telemetries)), transport)) + Ok((telemetries, transport)) } /// Create a service configuration from a chain spec. @@ -59,7 +57,7 @@ pub fn init_logging_and_telemetry( /// This configuration contains good defaults for a browser light client. pub async fn browser_configuration( chain_spec: GenericChainSpec, - telemetries: Arc>, + telemetries: sc_telemetry::Telemetries, transport: ExtTransport, ) -> Result> where From 1b4762ac6ad77852b6e50d46ee3817e244b0b926 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 15:04:00 +0100 Subject: [PATCH 122/222] WIP --- bin/node/cli/src/browser.rs | 2 +- client/cli/src/config.rs | 4 +- client/cli/src/lib.rs | 4 +- client/cli/src/runner.rs | 3 +- client/service/src/builder.rs | 14 ++- client/service/src/config.rs | 4 +- client/service/test/src/lib.rs | 2 +- client/telemetry/src/layer.rs | 1 + client/telemetry/src/lib.rs | 161 +++++++++++++++++++----------- client/tracing/src/logging/mod.rs | 2 +- utils/browser/src/lib.rs | 4 +- 11 files changed, 123 insertions(+), 78 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index c8bf2e2ab8c92..a5c06587af694 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -41,7 +41,7 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu None => crate::chain_spec::development_config(), }; - let config = browser_configuration(chain_spec, telemetries, transport).await?; + let config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; info!("Substrate browser node"); info!("✌️ version {}", config.impl_version); diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index c16772cfb49e6..b9d32cdc97962 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -455,7 +455,7 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, - telemetries: sc_telemetry::Telemetries, + telemetry_handle: Option, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; @@ -526,7 +526,7 @@ pub trait CliConfiguration: Sized { role, base_path: Some(base_path), informant_output_format: Default::default(), - telemetries, + telemetry_handle, }) } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 06c195ddba7d7..766ed57c4b357 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -215,9 +215,9 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, - telemetries: sc_telemetry::Telemetries, + telemetry_handle: Option, ) -> error::Result { - command.create_configuration(self, task_executor, telemetries) + command.create_configuration(self, task_executor, telemetry_handle) } /// Create a runner for the command provided in argument. This will create a Configuration and diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index ccac6a3923a9c..0e8360e2c2877 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -141,8 +141,7 @@ impl Runner { config: command.create_configuration( cli, task_executor.into(), - //telemetries.clone(), - sc_telemetry::Telemetries::new(), // TODO + Some(telemetries.handle()), )?, tokio_runtime, telemetries, diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 726ba16a97fbf..513d0a6ded1a4 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -547,7 +547,7 @@ pub fn spawn_tasks( &mut config, network.clone(), client.clone(), - )?; + ); info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( @@ -652,11 +652,17 @@ fn init_telemetry>( config: &mut Configuration, network: Arc::Hash>>, client: Arc, -) -> Result, std::io::Error> { +) -> Option { + let telemetry_handle = if let Some(handle) = config.telemetry_handle.as_mut() { + handle + } else { + return None; + }; + let endpoints = match config.telemetry_endpoints.clone() { // Don't initialise telemetry if `telemetry_endpoints` == Some([]) Some(endpoints) if !endpoints.is_empty() => endpoints, - _ => return Ok(None), + _ => return None, }; let genesis_hash = match client.block_hash(Zero::zero()) { @@ -686,7 +692,7 @@ fn init_telemetry>( "network_id": network_id.clone() }}; - Some(config.telemetries.start_telemetry(endpoints, json)).transpose() + Some(telemetry_handle.start_telemetry(endpoints, json)) } fn gen_handler( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 62dd71d90ed9f..fa88324c5cbbc 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -87,8 +87,8 @@ pub struct Configuration { /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, - /// All the telemetries. - pub telemetries: sc_telemetry::Telemetries, + /// Telemetry handle. + pub telemetry_handle: Option, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index bd2d1e965c139..1950310daf7f5 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -263,7 +263,7 @@ fn node_config tracing::field::Visit for TelemetryAttrsVisitor<'a> { /// /// This is used by [`TelemetryLayer`] to route the log events to the correct channel based on the /// span's ID. +// TODO remove #[derive(Default, Debug, Clone)] pub struct Senders( Arc>>>>, diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f6de3b96a29b3..7bbb93ddf87d9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -48,6 +48,7 @@ use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ collections::{HashMap, HashSet}, + fmt, io, pin::Pin, sync::Arc, @@ -258,6 +259,8 @@ impl Stream for Telemetry { } } +pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionSinks); + /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// /// [`Telemetry`] created through this object re-use connections if possible. @@ -265,27 +268,24 @@ impl Stream for Telemetry { pub struct Telemetries { receiver: mpsc::Receiver<(Id, u8, String)>, sender: mpsc::Sender<(Id, u8, String)>, - node_map: HashMap>, - connection_messages: HashMap, - connection_sinks: HashMap, - node_pool: HashMap>, // TODO mod - wasm_external_transport: Option, + init_receiver: mpsc::UnboundedReceiver, + init_sender: mpsc::UnboundedSender, + transport: crate::worker::WsTrans, } impl Telemetries { /// TODO - pub fn new() -> Self { + pub fn new() -> Result { let (sender, receiver) = mpsc::channel(16); + let (init_sender, init_receiver) = mpsc::unbounded(); - Self { + Ok(Self { receiver, sender, - node_map: Default::default(), - connection_messages: Default::default(), - connection_sinks: Default::default(), - node_pool: Default::default(), - wasm_external_transport: None, - } + init_receiver, + init_sender, + transport: Self::initialize_transport(None)?, + }) } /// Create a [`Telemetries`] object using an `ExtTransport`. @@ -298,32 +298,23 @@ impl Telemetries { /// > **Important**: Each individual call to `write` corresponds to one message. There is no /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. - pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Self { - Self { - wasm_external_transport: Some(wasm_external_transport), - ..Self::new() - } - } + pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Result { + let (sender, receiver) = mpsc::channel(16); + let (init_sender, init_receiver) = mpsc::unbounded(); - /// Create a new [`Telemetry`] for the endpoints provided in argument. - /// - /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding - /// verbosity level. TODO doc - pub fn start_telemetry( - &mut self, - endpoints: TelemetryEndpoints, - connection_message: serde_json::Value, - ) -> Result { - let endpoints = endpoints.0; + Ok(Self { + receiver, + sender, + init_receiver, + init_sender, + transport: Self::initialize_transport(Some(wasm_external_transport))?, + }) + } - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let id = span.id().expect("the span is enabled; qed"); - { - let id = id.clone(); - // TODO where to drop span? - tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)); - } - let transport = match self.wasm_external_transport.clone() { + fn initialize_transport( + wasm_external_transport: Option, + ) -> Result { + let transport = match wasm_external_transport.clone() { Some(t) => OptionalTransport::some(t), None => OptionalTransport::none() }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); @@ -347,7 +338,7 @@ impl Telemetries { }) }); - let transport = TransportTimeout::new( + Ok(TransportTimeout::new( transport.map(|out, _| { let out = out .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) @@ -355,19 +346,12 @@ impl Telemetries { Box::pin(out) as Pin> }), CONNECT_TIMEOUT - ).boxed(); - - for (addr, verbosity) in endpoints { - let node = crate::worker::node::Node::new(transport.clone(), addr.clone()); - self.node_pool.insert(addr.clone(), node); - self.node_map.entry(id.clone()).or_insert_with(Vec::new) - .push((verbosity, addr)); - } - - let connection_sink = TelemetryConnectionSinks::default(); - self.connection_sinks.insert(id.clone(), connection_sink.clone()); + ).boxed()) + } - Ok(connection_sink) + /// TODO + pub fn handle(&self) -> TelemetryHandle { + TelemetryHandle(self.init_sender.clone()) } /// TODO @@ -379,19 +363,38 @@ impl Telemetries { pub async fn run(self) { let Self { mut receiver, - sender, - node_map, - connection_messages, - connection_sinks, - mut node_pool, - wasm_external_transport, + sender: _sender, + mut init_receiver, + init_sender, + transport, } = self; - let mut node_first_connect: HashSet<(Multiaddr, Id)> = node_map - .iter() - .map(|(id, addrs)| addrs.iter().map(move |(_, x)| (x.to_owned(), id.to_owned()))) - .flatten() - .collect(); + let mut node_map: HashMap> = HashMap::new(); + let mut connection_messages: HashMap = HashMap::new(); + let mut connection_sinks: HashMap = HashMap::new(); + let mut node_pool: HashMap> = HashMap::new(); // TODO mod + + let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); + + // initialize the telemetry nodes + init_sender.close_channel(); + while let Some((id, endpoints, connection_message, connection_sink)) = init_receiver.next().await + { + let endpoints = endpoints.0; + + for (addr, verbosity) in endpoints { + let node = crate::worker::node::Node::new(transport.clone(), addr.clone()); + node_pool.insert(addr.clone(), node); + node_map.entry(id.clone()).or_insert_with(Vec::new) + .push((verbosity, addr.clone())); + node_first_connect.insert((addr, id.clone())); + } + + let connection_sink = TelemetryConnectionSinks::default(); + connection_sinks.insert(id.clone(), connection_sink.clone()); + } + + // loop indefinitely over telemetry messages while let Some((id, verbosity, message)) = receiver.next().await { let before = Instant::now(); @@ -462,6 +465,42 @@ impl Telemetries { } } +/// TODO +#[derive(Clone, Debug)] +pub struct TelemetryHandle(mpsc::UnboundedSender); + +impl TelemetryHandle { + /// Create a new [`Telemetry`] for the endpoints provided in argument. + /// + /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding + /// verbosity level. TODO doc + pub fn start_telemetry( + &mut self, + endpoints: TelemetryEndpoints, + connection_message: serde_json::Value, + ) -> TelemetryConnectionSinks { + let connection_sink = TelemetryConnectionSinks::default(); + + let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let id = span.id().expect("the span is enabled; qed"); + { + let id = id.clone(); + // TODO where to drop span? + tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)); + } + + if let Err(err) = self.0.unbounded_send((id, endpoints, connection_message, connection_sink.clone())) { + error!( + target: "telemetry", + "Could not initialize telemetry: {}", + err, + ); + } + + connection_sink + } +} + /// Sinks to propagate telemetry connection established events. #[derive(Default, Clone, Debug)] pub struct TelemetryConnectionSinks(Arc>>>); diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index ee7668f19df9f..587e02e7592df 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -159,7 +159,7 @@ fn get_default_subscriber_and_telemetries_internal( sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) } else { sc_telemetry::Telemetries::new() - }; + }.map_err(|err| format!("Could not initialize telemetry: {}", err))?; let sender = telemetries.sender(); let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); let event_format = EventFormat { diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index fd9a758e66abb..f3495b94c1111 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -57,7 +57,7 @@ pub fn init_logging_and_telemetry( /// This configuration contains good defaults for a browser light client. pub async fn browser_configuration( chain_spec: GenericChainSpec, - telemetries: sc_telemetry::Telemetries, + telemetry_handle: Option, transport: ExtTransport, ) -> Result> where @@ -88,7 +88,7 @@ where async {} }).into(), telemetry_external_transport: Some(transport), - telemetries, + telemetry_handle, role: Role::Light, database: { info!("Opening Indexed DB database '{}'...", name); From bec2d67acf4041436f22ef20948dca3c3824e8b1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 16:53:12 +0100 Subject: [PATCH 123/222] WIP --- client/telemetry/src/lib.rs | 42 ++++++++++++++++++----------- client/telemetry/src/worker/node.rs | 20 +++++++++++++- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 7bbb93ddf87d9..d247892ec97b2 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -370,10 +370,10 @@ impl Telemetries { } = self; let mut node_map: HashMap> = HashMap::new(); + let mut node_map_inv: HashMap> = HashMap::new(); let mut connection_messages: HashMap = HashMap::new(); let mut connection_sinks: HashMap = HashMap::new(); let mut node_pool: HashMap> = HashMap::new(); // TODO mod - let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); // initialize the telemetry nodes @@ -387,11 +387,13 @@ impl Telemetries { node_pool.insert(addr.clone(), node); node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); + node_map_inv.entry(addr.clone()).or_insert_with(Vec::new).push(id.clone()); node_first_connect.insert((addr, id.clone())); } let connection_sink = TelemetryConnectionSinks::default(); connection_sinks.insert(id.clone(), connection_sink.clone()); + connection_messages.insert(id.clone(), connection_message); } // loop indefinitely over telemetry messages @@ -431,23 +433,33 @@ impl Telemetries { continue; } - // Disconnection - if !matches!(node.next().await, Some(crate::worker::node::NodeEvent::Connected)) { - node_first_connect.insert((addr.to_owned(), id.to_owned())); - continue; + // Detect re-connection + let node_status = node.next().await; + if matches!(node_status, Some(crate::worker::node::NodeEvent::Connected)) { + // All the instances must re-send the connection message + node_first_connect.extend( + node_map_inv.get(addr) + .iter() + .map(|x| x.iter()) + .flatten() + .map(|id| (addr.clone(), id.to_owned())), + ); } // Reconnection handling - if node_first_connect.remove(&(addr.to_owned(), id.clone())) { - if let Some(connection_sink) = connection_sinks.get(&id) { - connection_sink.fire(); - } - if let Some(json) = connection_messages.get(&id) { - let mut json = json.clone(); - let obj = json.as_object_mut().expect("todo"); - obj.insert("msg".into(), "system.connected".into()); - obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); - let _ = node.send_message(serde_json::to_string(obj).expect("todo")); + if matches!(node_status, Some(crate::worker::node::NodeEvent::Connected) | None) { + if node_first_connect.remove(&(addr.to_owned(), id.clone())) { + if let Some(connection_sink) = connection_sinks.get(&id) { + connection_sink.fire(); + } + if let Some(json) = connection_messages.get(&id) { + let mut json = json.clone(); + let obj = json.as_object_mut().expect("todo"); + obj.insert("msg".into(), "system.connected".into()); + obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); + obj.insert("id".into(), id.into_u64().into()); + let _ = node.send_message(serde_json::to_string(obj).expect("todo")); + } } } diff --git a/client/telemetry/src/worker/node.rs b/client/telemetry/src/worker/node.rs index 245b0745a5591..4d113565c219b 100644 --- a/client/telemetry/src/worker/node.rs +++ b/client/telemetry/src/worker/node.rs @@ -52,6 +52,21 @@ enum NodeSocket { Poisoned, } +impl fmt::Debug for NodeSocket { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use NodeSocket::*; + f.write_str( + match self { + Connected(_) => "Connected", + Dialing(_) => "Dialing", + ReconnectNow => "ReconnectNow", + WaitingReconnect(_) => "WaitingReconnect", + Poisoned => "Poisoned", + }, + ) + } +} + struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, @@ -210,7 +225,10 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, match NodeSocketConnected::poll(Pin::new(&mut conn), cx, &self.addr) { Poll::Ready(Ok(v)) => match v {}, Poll::Pending => { - break NodeSocket::Connected(conn) + self.socket = NodeSocket::Connected(conn); + // NOTE: return None means nothing special is happening but we are + // connected + return Poll::Ready(None); }, Poll::Ready(Err(err)) => { warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); From 2b49cab4794f7af46fd582e949c500ac006f4130 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 17:08:01 +0100 Subject: [PATCH 124/222] CLEANUP --- client/telemetry/src/lib.rs | 126 ++----------------- client/telemetry/src/{worker => }/node.rs | 66 ---------- client/telemetry/src/worker.rs | 143 ---------------------- client/telemetry/src/worker/node_pool.rs | 56 --------- 4 files changed, 10 insertions(+), 381 deletions(-) rename client/telemetry/src/{worker => }/node.rs (81%) delete mode 100644 client/telemetry/src/worker/node_pool.rs diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d247892ec97b2..2ffadcc1d96d0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Telemetry utilities. +//! Telemetry utilities. TODO update doc //! //! You can collect telemetries for a substrate node by creating a `Telemetry` object. For every //! substrate node there must be only one `Telemetry` object. This `Telemetry` object can connect to @@ -66,10 +66,11 @@ pub use serde_json; pub use tracing; mod layer; +mod node; pub mod worker; pub use layer::*; -use worker::node_pool::*; +use node::{Node, NodeEvent}; use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod /// List of telemetry servers we want to talk to. Contains the URL of the server, and the @@ -142,122 +143,15 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -/// Telemetry object. Implements `Future` and must be polled regularly. -/// -/// Dropping unregisters the telemetry. -#[derive(Debug)] -pub struct Telemetry { - inner: TelemetryInner, - span: tracing::Span, -} - +/* + * TODO impl Drop for Telemetry { fn drop(&mut self) { let span_id = self.span.id().expect("the span is enabled; qed"); tracing::dispatcher::get_default(move |dispatch| dispatch.exit(&span_id)); } } - -#[derive(Debug)] -struct TelemetryInner { - /// Worker for the telemetry. `None` if it failed to initialize. - worker: Option, - /// Receives log entries for them to be dispatched to the worker. - receiver: mpsc::Receiver<(u8, String)>, -} - -impl Telemetry { - /// Initializes the telemetry. See the crate root documentation for more information. - pub fn new( - endpoints: TelemetryEndpoints, - wasm_external_transport: Option, - node_pool: Option<()>, - ) -> (Self, mpsc::Sender<(u8, String)>) { - let endpoints = endpoints.0; - - let (sender, receiver) = mpsc::channel(16); - - let worker = match worker::TelemetryWorker::new( - endpoints, - wasm_external_transport, - None, - ) { - Ok(w) => Some(w), - Err(err) => { - error!(target: "telemetry", "Failed to initialize telemetry worker: {:?}", err); - None - } - }; - - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let span_id = span.id().expect("the span is enabled; qed"); - tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&span_id)); - - ( - Self { - inner: TelemetryInner { - worker, - receiver, - }, - span, - }, - sender, - ) - } -} - -/// Event generated when polling the worker. -#[derive(Debug)] -pub enum TelemetryEvent { - /// We have established a connection to one of the telemetry endpoint, either for the first - /// time or after having been disconnected earlier. - Connected, -} - -impl Stream for Telemetry { - type Item = TelemetryEvent; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let before = Instant::now(); - - let mut has_connected = false; - - // The polling pattern is: poll the worker so that it processes its queue, then add one - // message from the receiver (if possible), then poll the worker again, and so on. - loop { - if let Some(worker) = self.inner.worker.as_mut() { - while let Poll::Ready(event) = worker.poll(cx) { - // Right now we only have one possible event. This line is here in order to not - // forget to handle any possible new event type. - let worker::TelemetryWorkerEvent::Connected = event; - has_connected = true; - } - } - - if let Poll::Ready(Some(( - verbosity, - json, - ))) = Stream::poll_next(Pin::new(&mut self.inner.receiver), cx) - { - if let Some(worker) = self.inner.worker.as_mut() { - let _ = worker.log(verbosity, json.as_str()); - } - } else { - break; - } - } - - if before.elapsed() > Duration::from_millis(200) { - warn!(target: "telemetry", "Polling the telemetry took more than 200ms"); - } - - if has_connected { - Poll::Ready(Some(TelemetryEvent::Connected)) - } else { - Poll::Pending - } - } -} +*/ pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionSinks); @@ -373,7 +267,7 @@ impl Telemetries { let mut node_map_inv: HashMap> = HashMap::new(); let mut connection_messages: HashMap = HashMap::new(); let mut connection_sinks: HashMap = HashMap::new(); - let mut node_pool: HashMap> = HashMap::new(); // TODO mod + let mut node_pool: HashMap> = HashMap::new(); // TODO mod let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); // initialize the telemetry nodes @@ -383,7 +277,7 @@ impl Telemetries { let endpoints = endpoints.0; for (addr, verbosity) in endpoints { - let node = crate::worker::node::Node::new(transport.clone(), addr.clone()); + let node = Node::new(transport.clone(), addr.clone()); node_pool.insert(addr.clone(), node); node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); @@ -435,7 +329,7 @@ impl Telemetries { // Detect re-connection let node_status = node.next().await; - if matches!(node_status, Some(crate::worker::node::NodeEvent::Connected)) { + if matches!(node_status, Some(NodeEvent::Connected)) { // All the instances must re-send the connection message node_first_connect.extend( node_map_inv.get(addr) @@ -447,7 +341,7 @@ impl Telemetries { } // Reconnection handling - if matches!(node_status, Some(crate::worker::node::NodeEvent::Connected) | None) { + if matches!(node_status, Some(NodeEvent::Connected) | None) { if node_first_connect.remove(&(addr.to_owned(), id.clone())) { if let Some(connection_sink) = connection_sinks.get(&id) { connection_sink.fire(); diff --git a/client/telemetry/src/worker/node.rs b/client/telemetry/src/node.rs similarity index 81% rename from client/telemetry/src/worker/node.rs rename to client/telemetry/src/node.rs index 4d113565c219b..e7fbbd13d22d1 100644 --- a/client/telemetry/src/worker/node.rs +++ b/client/telemetry/src/node.rs @@ -140,72 +140,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Err(()) } } - - /// Polls the node for updates. Must be performed regularly. - pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); - self.socket = loop { - match socket { - NodeSocket::Connected(mut conn) => { - match NodeSocketConnected::poll(Pin::new(&mut conn), cx, &self.addr) { - Poll::Ready(Ok(v)) => match v {}, - Poll::Pending => { - break NodeSocket::Connected(conn) - }, - Poll::Ready(Err(err)) => { - warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - self.socket = NodeSocket::WaitingReconnect(timeout); - return Poll::Ready(NodeEvent::Disconnected(err)) - } - } - } - NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { - Poll::Ready(Ok(sink)) => { - debug!(target: "telemetry", "✅ Connected to {}", self.addr); - let conn = NodeSocketConnected { - sink, - pending: VecDeque::new(), - need_flush: false, - timeout: None, - }; - self.socket = NodeSocket::Connected(conn); - return Poll::Ready(NodeEvent::Connected) - }, - Poll::Pending => break NodeSocket::Dialing(s), - Poll::Ready(Err(err)) => { - warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); - } - } - NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { - Ok(d) => { - debug!(target: "telemetry", "Started dialing {}", self.addr); - socket = NodeSocket::Dialing(d); - } - Err(err) => { - warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); - } - } - NodeSocket::WaitingReconnect(mut s) => - if let Poll::Ready(_) = Future::poll(Pin::new(&mut s), cx) { - socket = NodeSocket::ReconnectNow; - } else { - break NodeSocket::WaitingReconnect(s) - } - NodeSocket::Poisoned => { - error!(target: "telemetry", "‼️ Poisoned connection with {}", self.addr); - break NodeSocket::Poisoned - } - } - }; - - Poll::Pending - // TODO remove duplicated - } } impl Stream for Node diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 4fe01d179ff81..a376646cf4ba0 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -39,32 +39,10 @@ use log::{trace, error}; use parking_lot::Mutex; use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; -pub(crate) mod node; -pub(crate) mod node_pool; - -pub(crate) use node_pool::NodePool; - /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. pub(crate) const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); -/// Event generated when polling the worker. -#[derive(Debug)] -pub enum TelemetryWorkerEvent { - /// We have established a connection to one of the telemetry endpoint, either for the first - /// time or after having been disconnected earlier. - Connected, -} - -/// Telemetry processing machine. -#[derive(Debug)] -pub struct TelemetryWorker { - /// List of nodes with their maximum verbosity level. - nodes: Vec<(Arc>>, u8)>, - /// Force `poll()` to return `Connected`. - force_connected: bool, -} - /// A trait that implements `Stream` and `Sink`. pub trait StreamAndSink: Stream + Sink {} impl, I> StreamAndSink for T {} @@ -78,127 +56,6 @@ pub type WsTrans = libp2p::core::transport::Boxed< > + Send>> >; -impl TelemetryWorker { - /// Builds a new `TelemetryWorker`. - /// - /// The endpoints must be a list of targets, plus a verbosity level. When you send a message - /// to the telemetry, only the targets whose verbosity is higher than the verbosity of the - /// message will receive it. - /// - /// It can re-use `Node` (connections) if a `NodePool` is provided and share the same address of - /// connection. Otherwise new `Node` are created. - pub fn new( - endpoints: impl IntoIterator, - wasm_external_transport: impl Into>, - node_pool: Option<&NodePool>, - ) -> Result { - let transport = match wasm_external_transport.into() { - Some(t) => OptionalTransport::some(t), - None => OptionalTransport::none() - }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); - - // The main transport is the `wasm_external_transport`, but if we're on desktop we add - // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass - // an external transport on desktop and the fallback is used all the time. - #[cfg(not(target_os = "unknown"))] - let transport = transport.or_transport({ - let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; - libp2p::websocket::framed::WsConfig::new(inner) - .and_then(|connec, _| { - let connec = connec - .with(|item| { - let item = libp2p::websocket::framed::OutgoingData::Binary(item); - future::ready(Ok::<_, io::Error>(item)) - }) - .try_filter(|item| future::ready(item.is_data())) - .map_ok(|data| data.into_bytes()); - future::ready(Ok::<_, io::Error>(connec)) - }) - }); - - let transport = TransportTimeout::new( - transport.map(|out, _| { - let out = out - .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) - .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); - Box::pin(out) as Pin> - }), - CONNECT_TIMEOUT - ).boxed(); - - let mut force_connected = false; - let nodes = endpoints.into_iter().map(|(addr, verbosity)| { - let node = if let Some(node_pool) = node_pool { - /* - let (node, is_new) = node_pool.get_or_create(transport.clone(), addr); - if !is_new { - force_connected = true; - } - node - */ - todo!("remove") - } else { - Arc::new(Mutex::new(node::Node::new(transport.clone(), addr))) - }; - (node, verbosity) - }).collect(); - - Ok(TelemetryWorker { - nodes, - force_connected, - }) - } - - /// Polls the worker for events that happened. - pub fn poll(&mut self, cx: &mut Context) -> Poll { - if self.force_connected { - self.force_connected = false; - return Poll::Ready(TelemetryWorkerEvent::Connected); - } - - for (node, _) in &mut self.nodes { - loop { - match node::Node::poll(Pin::new(&mut node.lock()), cx) { - Poll::Ready(node::NodeEvent::Connected) => - return Poll::Ready(TelemetryWorkerEvent::Connected), - Poll::Ready(node::NodeEvent::Disconnected(_)) => continue, - Poll::Pending => break, - } - } - } - - Poll::Pending - } - - /// Process telemetry message given its verbosity. - pub fn log(&mut self, msg_verbosity: u8, json: &str) -> Result<(), ()> { - // None of the nodes want that verbosity, so just return without doing any serialization. - if self.nodes.iter().all(|(_, node_max_verbosity)| msg_verbosity > *node_max_verbosity) { - trace!( - target: "telemetry", - "Skipping log entry because verbosity {:?} is too high for all endpoints", - msg_verbosity - ); - return Ok(()) - } - - for (node, node_max_verbosity) in &mut self.nodes { - let mut node = node.lock(); - - if msg_verbosity > *node_max_verbosity { - trace!(target: "telemetry", "Skipping {:?} for log entry with verbosity {:?}", - node.addr(), msg_verbosity); - continue; - } - - // `send_message` returns an error if we're not connected, which we silently ignore. - let _ = node.send_message(json); - } - - Ok(()) - } -} - /// Wraps around an `AsyncWrite` and implements `Sink`. Guarantees that each item being sent maps /// to one call of `write`. /// diff --git a/client/telemetry/src/worker/node_pool.rs b/client/telemetry/src/worker/node_pool.rs deleted file mode 100644 index 698981e42eda8..0000000000000 --- a/client/telemetry/src/worker/node_pool.rs +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use crate::worker::{node::Node, WsTrans}; -use libp2p::Multiaddr; -use parking_lot::{Mutex, MutexGuard}; -use std::collections::{hash_map::Entry, HashMap}; -use std::sync::Arc; - -#[derive(Debug, Default)] -/// A collection of nodes connecting to a telemetry server and identified by address. -pub struct NodePool { - nodes: HashMap>, // TODO remove inner Arc> -} - -impl NodePool { - /// Create a new `Node` if it doesn't exist for a given address. - pub fn get_or_create( - &self, - transport: WsTrans, - addr: Multiaddr, - ) -> (Arc>>, bool) { - todo!(); - /* - let mut nodes = self.nodes.lock(); - let entry = nodes.entry(addr.clone()); - let new = matches!(entry, Entry::Vacant(..)); - - ( - entry - .or_insert_with(|| Arc::new(Node::new(transport, addr).into())) - .clone(), - new, - ) - */ - } - - pub(crate) fn lock(&mut self) -> &mut HashMap> { - &mut self.nodes - } -} From 64b5a6e77adf9ece8bd8abf4cc3b6cf94168abaa Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 3 Dec 2020 17:16:19 +0100 Subject: [PATCH 125/222] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- bin/node/cli/src/browser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index a5c06587af694..feb19e49911cc 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,7 +34,7 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let (telemetries, transport) = init_logging_and_telemetry(log_directives.as_str())?; + let (telemetries, transport) = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, From ca3da6d30de2923fd0142c3bbb53d4f4a638bd29 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 4 Dec 2020 10:25:17 +0100 Subject: [PATCH 126/222] WIP --- client/cli/src/lib.rs | 82 +++++++++++++++++++++---------- client/tracing/src/logging/mod.rs | 70 +++++++++++++++++++------- 2 files changed, 109 insertions(+), 43 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index cae15b78a6044..0f1501f19702f 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -242,34 +242,64 @@ pub fn init_logging_and_telemetry( disable_log_reloading: bool, ) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( - pattern, - telemetry_external_transport, - tracing_receiver, - profiling_targets, - disable_log_reloading, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) + if disable_log_reloading { + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( + pattern, + telemetry_external_transport, + tracing_receiver, + profiling_targets, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetries + } else { + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( + pattern, + telemetry_external_transport, + tracing_receiver, + profiling_targets, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetries } - - telemetries } else { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( - pattern, - telemetry_external_transport, - disable_log_reloading, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) + if disable_log_reloading { + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( + pattern, + telemetry_external_transport, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetries + } else { + let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_log_reloading( + pattern, + telemetry_external_transport, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetries } - - telemetries }) } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index aa5bc498960a3..25ca58f8efd5c 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -49,10 +49,27 @@ macro_rules! disable_log_reloading { /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. /// /// When running in a browser, the `telemetry_external_transport` should be provided. +pub fn get_default_subscriber_and_telemetries_with_log_reloading( + pattern: &str, + telemetry_external_transport: Option, +) -> std::result::Result< + ( + impl Subscriber + for<'a> LookupSpan<'a>, + sc_telemetry::Telemetries, + ), + String, +> { + get_default_subscriber_and_telemetries_internal( + parse_directives(pattern), + telemetry_external_transport, + |builder| disable_log_reloading!(builder), + ) +} + +/// TODO pub fn get_default_subscriber_and_telemetries( pattern: &str, telemetry_external_transport: Option, - disable_log_reloading: bool, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -60,19 +77,11 @@ pub fn get_default_subscriber_and_telemetries( ), String, > { - if disable_log_reloading { - get_default_subscriber_and_telemetries_internal( - parse_directives(pattern), - telemetry_external_transport, - Box::new(|builder| disable_log_reloading!(builder)), - ) - } else { - get_default_subscriber_and_telemetries_internal( - parse_directives(pattern), - telemetry_external_transport, - Box::new(|builder| builder), - ) - } + get_default_subscriber_and_telemetries_internal( + parse_directives(pattern), + telemetry_external_transport, + |builder| builder, + ) } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with @@ -84,7 +93,6 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, - disable_log_reloading: bool, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -97,7 +105,35 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( .into_iter() .chain(parse_directives(profiling_targets).into_iter()), telemetry_external_transport, - Box::new(|builder| builder), + |builder| builder, + )?; + let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); + + Ok((subscriber.with(profiling), telemetries)) +} + +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with +/// profiling enabled. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. +pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( + pattern: &str, + telemetry_external_transport: Option, + tracing_receiver: crate::TracingReceiver, + profiling_targets: &str, +) -> std::result::Result< + ( + impl Subscriber + for<'a> LookupSpan<'a>, + sc_telemetry::Telemetries, + ), + String, +> { + let (subscriber, telemetries) = get_default_subscriber_and_telemetries_internal( + parse_directives(pattern) + .into_iter() + .chain(parse_directives(profiling_targets).into_iter()), + telemetry_external_transport, + |builder| disable_log_reloading!(builder), )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); @@ -109,7 +145,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( fn get_default_subscriber_and_telemetries_internal( extra_directives: impl IntoIterator, telemetry_external_transport: Option, - builder_hook: Box, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder>, + builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, From 0a8d616bc7dc362295dd7868829c2ef45b1dc779 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 4 Dec 2020 12:24:07 +0100 Subject: [PATCH 127/222] WIP --- bin/node/cli/src/browser.rs | 2 ++ client/tracing/src/logging/mod.rs | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index feb19e49911cc..21dec6cf055ec 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -56,5 +56,7 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu .map(|(components, rpc_handlers, _, _, _, _)| (components, rpc_handlers)) .map_err(|e| format!("{:?}", e))?; + task_manager.spawn_handle().spawn("telemetry", telemetries.run()); + Ok(browser_utils::start_client(task_manager, rpc_handlers)) } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 25ca58f8efd5c..b44e7e9528907 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -46,10 +46,8 @@ macro_rules! disable_log_reloading { }}; } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. -pub fn get_default_subscriber_and_telemetries_with_log_reloading( +/// TODO +pub fn get_default_subscriber_and_telemetries( pattern: &str, telemetry_external_transport: Option, ) -> std::result::Result< @@ -62,12 +60,15 @@ pub fn get_default_subscriber_and_telemetries_with_log_reloading( get_default_subscriber_and_telemetries_internal( parse_directives(pattern), telemetry_external_transport, - |builder| disable_log_reloading!(builder), + |builder| builder, ) } -/// TODO -pub fn get_default_subscriber_and_telemetries( +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. +#[cfg(not(target_os = "unknown"))] +pub fn get_default_subscriber_and_telemetries_with_log_reloading( pattern: &str, telemetry_external_transport: Option, ) -> std::result::Result< @@ -80,7 +81,7 @@ pub fn get_default_subscriber_and_telemetries( get_default_subscriber_and_telemetries_internal( parse_directives(pattern), telemetry_external_transport, - |builder| builder, + |builder| disable_log_reloading!(builder), ) } @@ -116,6 +117,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( /// profiling enabled. /// /// When running in a browser, the `telemetry_external_transport` should be provided. +#[cfg(not(target_os = "unknown"))] pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( pattern: &str, telemetry_external_transport: Option, @@ -246,12 +248,13 @@ where #[cfg(target_os = "unknown")] let builder = builder .with_writer( - std::io::sink as _, + std::io::sink, ); #[cfg(not(target_os = "unknown"))] let builder = builder.event_format(event_format); + #[cfg(not(target_os = "unknown"))] let builder = builder_hook(builder); let subscriber = builder.finish().with(PrefixLayer).with(telemetry_layer); From 68be85800cd28228b856b69fe7b68d9d69b02d48 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 4 Dec 2020 15:39:40 +0100 Subject: [PATCH 128/222] Debug --- bin/node/cli/browser-demo/build.sh | 2 +- bin/node/cli/src/browser.rs | 3 ++- client/telemetry/src/lib.rs | 2 +- client/telemetry/src/node.rs | 20 ++++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh index 8840106daeb5c..544b16333aeb2 100755 --- a/bin/node/cli/browser-demo/build.sh +++ b/bin/node/cli/browser-demo/build.sh @@ -2,4 +2,4 @@ set -e -x cargo +nightly build --release -p node-cli --target wasm32-unknown-unknown --no-default-features --features browser -Z features=itarget wasm-bindgen ../../../../target/wasm32-unknown-unknown/release/node_cli.wasm --out-dir pkg --target web -python -m http.server 8000 +python -m http.server 8080 diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 21dec6cf055ec..9d579d511188e 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -41,7 +41,8 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu None => crate::chain_spec::development_config(), }; - let config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; + let mut config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; + config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); info!("✌️ version {}", config.impl_version); diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2ffadcc1d96d0..f78a2cbdc0c5e 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -358,7 +358,7 @@ impl Telemetries { } // `send_message` returns an error if we're not connected, which we silently ignore. - let _ = node.send_message(message.clone()); // TODO probably dont need to clone + let res = node.send_message(message.clone()); // TODO probably dont need to clone } if before.elapsed() > Duration::from_millis(200) { diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index e7fbbd13d22d1..0e0908aa7aafb 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -132,8 +132,10 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, pending.push_back(payload.into()); Ok(()) } else { + /* warn!(target: "telemetry", "⚠️ Rejected log entry because queue is full for {:?}", self.addr); + */ Err(()) } } else { @@ -241,6 +243,7 @@ where TTrans::Output: Sink, Error = TSinkErr> cx: &mut Context, my_addr: &Multiaddr, ) -> Poll>> { + let nothing_pending = self.pending.len(); while let Some(item) = self.pending.pop_front() { if let Poll::Ready(result) = Sink::poll_ready(Pin::new(&mut self.sink), cx) { @@ -249,9 +252,12 @@ where TTrans::Output: Sink, Error = TSinkErr> } let item_len = item.len(); + //log::error!(target: "telemetry", "##### sending"); if let Err(err) = Sink::start_send(Pin::new(&mut self.sink), item) { + //log::error!(target: "telemetry", "##### fail"); return Poll::Ready(Err(ConnectionError::Sink(err))) } + //log::error!(target: "telemetry", "##### success"); trace!( target: "telemetry", "Successfully sent {:?} bytes message to {}", item_len, my_addr @@ -272,23 +278,37 @@ where TTrans::Output: Sink, Error = TSinkErr> Poll::Pending => { if self.timeout.is_none() { self.timeout = Some(Delay::new(Duration::from_secs(10))); + log::error!(target: "telemetry", "##### reset timeout"); + } else { + // TODO browser always go here + //log::error!(target: "telemetry", "##### kept timeout"); } }, Poll::Ready(Err(err)) => { self.timeout = None; + log::error!(target: "telemetry", "##### remove timeout"); return Poll::Ready(Err(ConnectionError::Sink(err))) }, Poll::Ready(Ok(())) => { + log::error!(target: "telemetry", "##### remove timeout"); + // TODO native always go there self.timeout = None; self.need_flush = false; }, } } + if nothing_pending == 0 { + log::error!(target: "telemetry", "##### reset timeout"); + self.timeout = None; + } + //log::error!(target: "telemetry", "##### no reset timeout: {}", nothing_pending); + if let Some(timeout) = self.timeout.as_mut() { match Future::poll(Pin::new(timeout), cx) { Poll::Pending => {}, Poll::Ready(()) => { + log::error!(target: "telemetry", "##### timeout!"); self.timeout = None; return Poll::Ready(Err(ConnectionError::Timeout)) } From 07d8ae50bd881eadb33471d3b0b25f6e70443965 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 9 Dec 2020 18:25:36 +0100 Subject: [PATCH 129/222] WIP --- client/telemetry/src/lib.rs | 107 ++++++++++++++++++++++------------- client/telemetry/src/node.rs | 67 ++++++++++++++++++---- 2 files changed, 124 insertions(+), 50 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f78a2cbdc0c5e..02fc75288d571 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -269,6 +269,7 @@ impl Telemetries { let mut connection_sinks: HashMap = HashMap::new(); let mut node_pool: HashMap> = HashMap::new(); // TODO mod let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); + let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes init_sender.close_channel(); @@ -282,7 +283,8 @@ impl Telemetries { node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); node_map_inv.entry(addr.clone()).or_insert_with(Vec::new).push(id.clone()); - node_first_connect.insert((addr, id.clone())); + node_first_connect.insert((addr.clone(), id.clone())); + existing_nodes.insert(addr.clone()); } let connection_sink = TelemetryConnectionSinks::default(); @@ -290,43 +292,77 @@ impl Telemetries { connection_messages.insert(id.clone(), connection_message); } - // loop indefinitely over telemetry messages - while let Some((id, verbosity, message)) = receiver.next().await { - let before = Instant::now(); - - let nodes = if let Some(nodes) = node_map.get(&id) { - nodes - } else { - log::error!( - target: "telemetry", - "Received telemetry log for unknown id ({:?}): {}", - id, - message, - ); - continue; - }; - - for (node_max_verbosity, addr) in nodes { - let node = if let Some(node) = node_pool.get_mut(addr) { - node + let mut messages = receiver + .filter_map(|(id, verbosity, message)| { + if let Some(nodes) = node_map.get(&id) { + future::ready(Some((id, verbosity, message, nodes))) } else { log::error!( target: "telemetry", - "Could not find telemetry server in the NodePool: {}", - addr, + "Received telemetry log for unknown id ({:?}): {}", + id, + message, ); - continue; - }; + future::ready(None) + } + }) + .flat_map(|(id, verbosity, message, nodes)| { + let mut to_send = Vec::with_capacity(nodes.len()); + let before = Instant::now(); + + for (node_max_verbosity, addr) in nodes { + if !existing_nodes.contains(addr) { + log::error!( + target: "telemetry", + "Could not find telemetry server in the NodePool: {}", + addr, + ); + continue; + }; + + if verbosity > *node_max_verbosity { + log::trace!( + target: "telemetry", + "Skipping {} for log entry with verbosity {:?}", + addr, + verbosity); + continue; + } + + to_send.push((addr, message.clone())); + } - if verbosity > *node_max_verbosity { - log::trace!( + if before.elapsed() > Duration::from_millis(200) { + log::warn!( target: "telemetry", - "Skipping {} for log entry with verbosity {:?}", - addr, - verbosity); - continue; + "Processing one telemetry message took more than 200ms", + ); } + stream::iter(to_send) + }); + // TODO make it forward to a sink that will dispatch? + + while let Some((addr, message)) = messages.next().await { + let mut node = node_pool.get_mut(&addr).unwrap(); + log::trace!(target: "telemetry", "#### Sending to {}: {}", addr, message); + let _ = node.send(message).await; + } + + /* + let futures = stream::unfold(messages, |messages| async move { + let (addr, message) = messages.next().await?; + if let Some(node) = node_pool.get(addr) { + Some((node.send(message), messages)) + } else { + todo!() + } + }); + */ + + // loop indefinitely over telemetry messages + /* + while let Some() = receiver.next().await { // Detect re-connection let node_status = node.next().await; if matches!(node_status, Some(NodeEvent::Connected)) { @@ -357,17 +393,8 @@ impl Telemetries { } } - // `send_message` returns an error if we're not connected, which we silently ignore. - let res = node.send_message(message.clone()); // TODO probably dont need to clone - } - - if before.elapsed() > Duration::from_millis(200) { - log::warn!( - target: "telemetry", - "Processing one telemetry message took more than 200ms", - ); - } } + */ } } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 0e0908aa7aafb..6b1807ac219a9 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -70,7 +70,7 @@ impl fmt::Debug for NodeSocket { struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, - /// Queue of packets to send. + /// Queue of packets to send. TODO remove caching (can be done with SinkExt.buffer()) pending: VecDeque>, /// If true, we need to flush the sink. need_flush: bool, @@ -115,6 +115,7 @@ impl Node { } } +/* impl Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TTrans::Output: Sink, Error = TSinkErr> @@ -132,10 +133,8 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, pending.push_back(payload.into()); Ok(()) } else { - /* warn!(target: "telemetry", "⚠️ Rejected log entry because queue is full for {:?}", self.addr); - */ Err(()) } } else { @@ -143,35 +142,56 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } } +*/ -impl Stream for Node +impl Sink for Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TTrans::Output: Sink, Error = TSinkErr> + Stream, TSinkErr>> + Unpin, TSinkErr: fmt::Debug { - type Item = NodeEvent; + //type Item = NodeEvent; + type Error = TSinkErr; - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); self.socket = loop { match socket { NodeSocket::Connected(mut conn) => { - match NodeSocketConnected::poll(Pin::new(&mut conn), cx, &self.addr) { + match Sink::poll_ready(Pin::new(&mut conn.sink), cx) { + Poll::Ready(Ok(())) => { + self.socket = NodeSocket::Connected(conn); + return Poll::Ready(Ok(())); + }, + Poll::Ready(Err(err)) => { + warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); + let timeout = gen_rand_reconnect_delay(); + self.socket = NodeSocket::WaitingReconnect(timeout); + //return Poll::Ready(Some(NodeEvent::Disconnected(err))) + return Poll::Pending; + }, + Poll::Pending => { + self.socket = NodeSocket::Connected(conn); + return Poll::Pending; + }, + /* Poll::Ready(Ok(v)) => match v {}, Poll::Pending => { self.socket = NodeSocket::Connected(conn); // NOTE: return None means nothing special is happening but we are // connected - return Poll::Ready(None); + //return Poll::Ready(None); + return Poll::Ready(Ok(())); }, Poll::Ready(Err(err)) => { warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); let timeout = gen_rand_reconnect_delay(); self.socket = NodeSocket::WaitingReconnect(timeout); - return Poll::Ready(Some(NodeEvent::Disconnected(err))) + //return Poll::Ready(Some(NodeEvent::Disconnected(err))) + return Poll::Pending; } + */ } } NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { @@ -184,7 +204,8 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, timeout: None, }; self.socket = NodeSocket::Connected(conn); - return Poll::Ready(Some(NodeEvent::Connected)) + //return Poll::Ready(Some(NodeEvent::Connected)) + return Poll::Ready(Ok(())); }, Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { @@ -219,6 +240,30 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Pending } + + fn start_send(mut self: Pin<&mut Self>, item: String) -> Result<(), Self::Error> { + match &mut self.socket { + NodeSocket::Connected(conn) => { + let _ = Sink::start_send(Pin::new(&mut conn.sink), item.into()); + }, + _ => {}, + } + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut self.socket { + NodeSocket::Connected(conn) => Sink::poll_flush(Pin::new(&mut conn.sink), cx).map(|_| Ok(())), + _ => Poll::Pending, + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut self.socket { + NodeSocket::Connected(conn) => Sink::poll_close(Pin::new(&mut conn.sink), cx).map(|_| Ok(())), + _ => Poll::Pending, + } + } } /// Generates a `Delay` object with a random timeout. @@ -230,6 +275,7 @@ fn gen_rand_reconnect_delay() -> Delay { Delay::new(Duration::from_secs(random_delay)) } +/* impl NodeSocketConnected where TTrans::Output: Sink, Error = TSinkErr> + Stream, TSinkErr>> @@ -333,6 +379,7 @@ where TTrans::Output: Sink, Error = TSinkErr> Poll::Pending } } +*/ impl fmt::Debug for Node { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { From 42e0d9a7ee5b0e510a3919497fa2b06a973b2b7a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 10 Dec 2020 16:53:15 +0100 Subject: [PATCH 130/222] WIP --- client/telemetry/src/lib.rs | 41 ++++++---- client/telemetry/src/node.rs | 120 ++++++++++++++++++++++++------ client/tracing/src/logging/mod.rs | 4 + 3 files changed, 131 insertions(+), 34 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 02fc75288d571..27c8f86e7b8c5 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -264,11 +264,10 @@ impl Telemetries { } = self; let mut node_map: HashMap> = HashMap::new(); - let mut node_map_inv: HashMap> = HashMap::new(); - let mut connection_messages: HashMap = HashMap::new(); - let mut connection_sinks: HashMap = HashMap::new(); - let mut node_pool: HashMap> = HashMap::new(); // TODO mod - let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); + let mut node_map_inv: HashMap> = HashMap::new(); // TODO remove? + let mut connection_messages: HashMap> = HashMap::new(); + let mut connection_sinks: HashMap> = HashMap::new(); + let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); // TODO remove? let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes @@ -278,22 +277,38 @@ impl Telemetries { let endpoints = endpoints.0; for (addr, verbosity) in endpoints { - let node = Node::new(transport.clone(), addr.clone()); - node_pool.insert(addr.clone(), node); node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); node_map_inv.entry(addr.clone()).or_insert_with(Vec::new).push(id.clone()); node_first_connect.insert((addr.clone(), id.clone())); existing_nodes.insert(addr.clone()); + let mut json = connection_message.clone(); + let obj = json.as_object_mut().expect("todo"); + obj.insert("msg".into(), "system.connected".into()); + obj.insert("id".into(), id.into_u64().into()); + connection_messages.entry(addr.clone()).or_insert_with(Vec::new) + .push(json); + connection_sinks.entry(addr.clone()).or_insert_with(Vec::new) + .push(connection_sink.clone()); } - - let connection_sink = TelemetryConnectionSinks::default(); - connection_sinks.insert(id.clone(), connection_sink.clone()); - connection_messages.insert(id.clone(), connection_message); } + let mut node_pool: HashMap> = + existing_nodes + .iter() + .map(|addr| { + let connection_messages = connection_messages.remove(addr) + .expect("there is a node for every connection message; qed"); + let connection_sinks = connection_sinks.remove(addr) + .expect("there is a node for every connection sink; qed"); + let node = Node::new(transport.clone(), addr.clone(), connection_messages, connection_sinks); + (addr.clone(), node) + }) + .collect(); + let mut messages = receiver .filter_map(|(id, verbosity, message)| { + // TODO probably wont need anymore if let Some(nodes) = node_map.get(&id) { future::ready(Some((id, verbosity, message, nodes))) } else { @@ -346,7 +361,7 @@ impl Telemetries { while let Some((addr, message)) = messages.next().await { let mut node = node_pool.get_mut(&addr).unwrap(); log::trace!(target: "telemetry", "#### Sending to {}: {}", addr, message); - let _ = node.send(message).await; + node.send(message).await.expect("never error"); } /* @@ -415,7 +430,7 @@ impl TelemetryHandle { let connection_sink = TelemetryConnectionSinks::default(); let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let id = span.id().expect("the span is enabled; qed"); + let id = span.id().expect("the span is enabled; qed"); // TODO: this error happen if the log is disabled by the command line { let id = id.clone(); // TODO where to drop span? diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 6b1807ac219a9..28a3f61a679de 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -25,11 +25,13 @@ use libp2p::core::transport::Transport; use log::{trace, debug, warn, error}; use rand::Rng as _; use std::{collections::VecDeque, fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; +use crate::TelemetryConnectionSinks; /// Maximum number of pending telemetry messages. const MAX_PENDING: usize = 10; /// Handler for a single telemetry node. +/// TODO: probably dont need to be pub + explain 2 properties of this Sink pub struct Node { /// Address of the node. addr: Multiaddr, @@ -37,6 +39,9 @@ pub struct Node { socket: NodeSocket, /// Transport used to establish new connections. transport: TTrans, + connection_messages: Vec, + buf: Option>>, + connection_sinks: Vec, } enum NodeSocket { @@ -71,7 +76,7 @@ struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, /// Queue of packets to send. TODO remove caching (can be done with SinkExt.buffer()) - pending: VecDeque>, + pending: Vec>, /// If true, we need to flush the sink. need_flush: bool, /// A timeout for the socket to write data. @@ -101,11 +106,19 @@ pub enum ConnectionError { impl Node { /// Builds a new node handler. - pub fn new(transport: TTrans, addr: Multiaddr) -> Self { + pub fn new( + transport: TTrans, + addr: Multiaddr, + connection_messages: Vec, + connection_sinks: Vec, + ) -> Self { Node { addr, socket: NodeSocket::ReconnectNow, transport, + buf: None, + connection_messages, + connection_sinks, } } @@ -115,7 +128,6 @@ impl Node { } } -/* impl Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TTrans::Output: Sink, Error = TSinkErr> @@ -123,6 +135,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, + Unpin, TSinkErr: fmt::Debug { +/* /// Sends a WebSocket frame to the node. Returns an error if we are not connected to the node. /// /// After calling this method, you should call `poll` in order for it to be properly processed. @@ -141,9 +154,35 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Err(()) } } -} */ + // NOTE: this code has been inspired from `Buffer` (`futures_util::sink::Buffer`). + // https://docs.rs/futures-util/0.3.8/src/futures_util/sink/buffer.rs.html#32 + fn try_send_connection_messages( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut conn: &mut NodeSocketConnected, + needs_poll: bool, + ) -> Poll> { + if needs_poll { + futures::ready!(conn.sink.poll_ready_unpin(cx))?; + } + if let Some(buf) = self.buf.as_mut() { + while let Some(item) = buf.pop() { + if let Err(e) = conn.sink.start_send_unpin(item) { + return Poll::Ready(Err(e)); + } + if !buf.is_empty() { + futures::ready!(conn.sink.poll_ready_unpin(cx))?; + } + } + conn.sink.poll_ready_unpin(cx) + } else { + Poll::Ready(Ok(())) + } + } +} + impl Sink for Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TTrans::Output: Sink, Error = TSinkErr> @@ -159,19 +198,28 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, self.socket = loop { match socket { NodeSocket::Connected(mut conn) => { - match Sink::poll_ready(Pin::new(&mut conn.sink), cx) { + match conn.sink.poll_ready_unpin(cx) { Poll::Ready(Ok(())) => { - self.socket = NodeSocket::Connected(conn); - return Poll::Ready(Ok(())); + match self.as_mut().try_send_connection_messages(cx, &mut conn, false) { + Poll::Ready(Err(e)) => { + let timeout = gen_rand_reconnect_delay(); + socket = NodeSocket::WaitingReconnect(timeout); + }, + other => { + self.socket = NodeSocket::Connected(conn); + return other; + }, + } }, Poll::Ready(Err(err)) => { warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); let timeout = gen_rand_reconnect_delay(); - self.socket = NodeSocket::WaitingReconnect(timeout); + socket = NodeSocket::WaitingReconnect(timeout); //return Poll::Ready(Some(NodeEvent::Disconnected(err))) - return Poll::Pending; + //return Poll::Pending; }, Poll::Pending => { + dbg!("pending"); self.socket = NodeSocket::Connected(conn); return Poll::Pending; }, @@ -195,17 +243,38 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { - Poll::Ready(Ok(sink)) => { + Poll::Ready(Ok(mut sink)) => { debug!(target: "telemetry", "✅ Connected to {}", self.addr); - let conn = NodeSocketConnected { + + let mut conn = NodeSocketConnected { sink, - pending: VecDeque::new(), + pending: Vec::new(), need_flush: false, timeout: None, }; - self.socket = NodeSocket::Connected(conn); - //return Poll::Ready(Some(NodeEvent::Connected)) - return Poll::Ready(Ok(())); + + for connection_sink in self.connection_sinks.iter() { + connection_sink.fire(); + } + + let mut buf = Vec::new(); + for mut json in self.connection_messages.iter().cloned() { + let obj = json.as_object_mut().expect("todo"); + obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); + buf.push(serde_json::to_vec(obj).expect("todo")); + } + self.buf.replace(buf); + + match self.as_mut().try_send_connection_messages(cx, &mut conn, true) { + Poll::Ready(Err(e)) => { + let timeout = gen_rand_reconnect_delay(); + socket = NodeSocket::WaitingReconnect(timeout); + }, + other => { + self.socket = NodeSocket::Connected(conn); + return other; + }, + } }, Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { @@ -244,24 +313,33 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, fn start_send(mut self: Pin<&mut Self>, item: String) -> Result<(), Self::Error> { match &mut self.socket { NodeSocket::Connected(conn) => { - let _ = Sink::start_send(Pin::new(&mut conn.sink), item.into()); + dbg!(&item); + let _ = conn.sink.start_send_unpin(item.into()); + }, + _ => { + error!( + target: "telemetry", + "Trying to send something but the connection is not ready. This is a bug. \ + Message sent: {}", + item, + ); + todo!("should never happen"); }, - _ => {}, } Ok(()) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match &mut self.socket { - NodeSocket::Connected(conn) => Sink::poll_flush(Pin::new(&mut conn.sink), cx).map(|_| Ok(())), - _ => Poll::Pending, + NodeSocket::Connected(conn) => conn.sink.poll_flush_unpin(cx).map(|_| Ok(())), + _ => Poll::Ready(Ok(())), } } fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match &mut self.socket { - NodeSocket::Connected(conn) => Sink::poll_close(Pin::new(&mut conn.sink), cx).map(|_| Ok(())), - _ => Poll::Pending, + NodeSocket::Connected(conn) => conn.sink.poll_close_unpin(cx).map(|_| Ok(())), + _ => Poll::Ready(Ok(())), } } } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index b44e7e9528907..1a6ee051880df 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -214,6 +214,10 @@ where env_filter = env_filter.add_directive( parse_default_directive("sc_tracing=trace").expect("provided directive is valid") ); + env_filter = env_filter.add_directive( + // TODO + parse_default_directive("telemetry-logger=trace").expect("provided directive is valid") + ); let enable_color = atty::is(atty::Stream::Stderr); let timer = ChronoLocal::with_format(if simple { From 5fe0fe2ccad96b5bb9fd66aa2900fa62d111b180 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 09:51:59 +0100 Subject: [PATCH 131/222] WIP --- client/telemetry/src/lib.rs | 2 +- client/telemetry/src/node.rs | 109 +++++++++++++++-------------------- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 27c8f86e7b8c5..21b846e613bea 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -361,7 +361,7 @@ impl Telemetries { while let Some((addr, message)) = messages.next().await { let mut node = node_pool.get_mut(&addr).unwrap(); log::trace!(target: "telemetry", "#### Sending to {}: {}", addr, message); - node.send(message).await.expect("never error"); + let _ = node.send(message).await; } /* diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 28a3f61a679de..8e00b74bff03c 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -40,7 +40,7 @@ pub struct Node { /// Transport used to establish new connections. transport: TTrans, connection_messages: Vec, - buf: Option>>, + buf: Vec>, connection_sinks: Vec, } @@ -72,6 +72,14 @@ impl fmt::Debug for NodeSocket { } } +impl NodeSocket { + fn wait_reconnect() -> NodeSocket { + let random_delay = rand::thread_rng().gen_range(5, 10); + let delay = Delay::new(Duration::from_secs(random_delay)); + NodeSocket::WaitingReconnect(delay) + } +} + struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, @@ -116,7 +124,7 @@ impl Node { addr, socket: NodeSocket::ReconnectNow, transport, - buf: None, + buf: Vec::new(), connection_messages, connection_sinks, } @@ -167,22 +175,19 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, if needs_poll { futures::ready!(conn.sink.poll_ready_unpin(cx))?; } - if let Some(buf) = self.buf.as_mut() { - while let Some(item) = buf.pop() { - if let Err(e) = conn.sink.start_send_unpin(item) { - return Poll::Ready(Err(e)); - } - if !buf.is_empty() { - futures::ready!(conn.sink.poll_ready_unpin(cx))?; - } + while let Some(item) = self.buf.pop() { + if let Err(e) = conn.sink.start_send_unpin(item) { + return Poll::Ready(Err(e)); } - conn.sink.poll_ready_unpin(cx) - } else { - Poll::Ready(Ok(())) + futures::ready!(conn.sink.poll_ready_unpin(cx))?; } + Poll::Ready(Ok(())) } } +// TODO not pub +pub enum Infallible {} + impl Sink for Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TTrans::Output: Sink, Error = TSinkErr> @@ -191,7 +196,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, TSinkErr: fmt::Debug { //type Item = NodeEvent; - type Error = TSinkErr; + type Error = Infallible; fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); @@ -202,44 +207,26 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Ready(Ok(())) => { match self.as_mut().try_send_connection_messages(cx, &mut conn, false) { Poll::Ready(Err(e)) => { - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); + socket = NodeSocket::wait_reconnect(); }, - other => { + Poll::Ready(Ok(())) => { self.socket = NodeSocket::Connected(conn); - return other; + return Poll::Ready(Ok(())); + }, + Poll::Pending => { + self.socket = NodeSocket::Connected(conn); + return Poll::Pending; }, } }, Poll::Ready(Err(err)) => { warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); - //return Poll::Ready(Some(NodeEvent::Disconnected(err))) - //return Poll::Pending; + socket = NodeSocket::wait_reconnect(); }, Poll::Pending => { - dbg!("pending"); self.socket = NodeSocket::Connected(conn); return Poll::Pending; }, - /* - Poll::Ready(Ok(v)) => match v {}, - Poll::Pending => { - self.socket = NodeSocket::Connected(conn); - // NOTE: return None means nothing special is happening but we are - // connected - //return Poll::Ready(None); - return Poll::Ready(Ok(())); - }, - Poll::Ready(Err(err)) => { - warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - self.socket = NodeSocket::WaitingReconnect(timeout); - //return Poll::Ready(Some(NodeEvent::Disconnected(err))) - return Poll::Pending; - } - */ } } NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { @@ -257,30 +244,20 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, connection_sink.fire(); } - let mut buf = Vec::new(); + let mut buf = Vec::with_capacity(self.connection_messages.len()); for mut json in self.connection_messages.iter().cloned() { let obj = json.as_object_mut().expect("todo"); obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); buf.push(serde_json::to_vec(obj).expect("todo")); } - self.buf.replace(buf); - - match self.as_mut().try_send_connection_messages(cx, &mut conn, true) { - Poll::Ready(Err(e)) => { - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); - }, - other => { - self.socket = NodeSocket::Connected(conn); - return other; - }, - } + let _ = mem::replace(&mut self.buf, buf); + + socket = NodeSocket::Connected(conn); }, Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); + socket = NodeSocket::wait_reconnect(); } } NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { @@ -290,8 +267,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } Err(err) => { warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); - let timeout = gen_rand_reconnect_delay(); - socket = NodeSocket::WaitingReconnect(timeout); + socket = NodeSocket::wait_reconnect(); } } NodeSocket::WaitingReconnect(mut s) => @@ -313,14 +289,14 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, fn start_send(mut self: Pin<&mut Self>, item: String) -> Result<(), Self::Error> { match &mut self.socket { NodeSocket::Connected(conn) => { - dbg!(&item); - let _ = conn.sink.start_send_unpin(item.into()); + let _ = conn.sink.start_send_unpin(item.into()).expect("boo"); }, - _ => { + socket => { error!( target: "telemetry", - "Trying to send something but the connection is not ready. This is a bug. \ - Message sent: {}", + "Trying to send something but the connection is not ready ({:?}). + This is a bug. Message sent: {}", + socket, item, ); todo!("should never happen"); @@ -331,7 +307,14 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match &mut self.socket { - NodeSocket::Connected(conn) => conn.sink.poll_flush_unpin(cx).map(|_| Ok(())), + NodeSocket::Connected(conn) => match conn.sink.poll_flush_unpin(cx) { + Poll::Ready(Err(_)) => { + self.socket = NodeSocket::wait_reconnect(); + Poll::Ready(Ok(())) + }, + Poll::Ready(Ok(())) => Poll::Ready(Ok(())), + Poll::Pending => Poll::Pending, + }, _ => Poll::Ready(Ok(())), } } From 2ec34b0523f1de0a7bb6fd2db2e0cb7705994a22 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 09:52:21 +0100 Subject: [PATCH 132/222] CLEANUP --- client/telemetry/src/node.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 8e00b74bff03c..bd519848c41b2 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -170,11 +170,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, mut self: Pin<&mut Self>, cx: &mut Context<'_>, mut conn: &mut NodeSocketConnected, - needs_poll: bool, ) -> Poll> { - if needs_poll { - futures::ready!(conn.sink.poll_ready_unpin(cx))?; - } while let Some(item) = self.buf.pop() { if let Err(e) = conn.sink.start_send_unpin(item) { return Poll::Ready(Err(e)); @@ -195,7 +191,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, + Unpin, TSinkErr: fmt::Debug { - //type Item = NodeEvent; type Error = Infallible; fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { @@ -205,7 +200,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, NodeSocket::Connected(mut conn) => { match conn.sink.poll_ready_unpin(cx) { Poll::Ready(Ok(())) => { - match self.as_mut().try_send_connection_messages(cx, &mut conn, false) { + match self.as_mut().try_send_connection_messages(cx, &mut conn) { Poll::Ready(Err(e)) => { socket = NodeSocket::wait_reconnect(); }, From 7f19841daae70234755304ceb5db3ef3749528c6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 10:16:55 +0100 Subject: [PATCH 133/222] CLEANUP --- client/telemetry/src/lib.rs | 2 +- client/telemetry/src/node.rs | 201 ++++------------------------------- 2 files changed, 19 insertions(+), 184 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 21b846e613bea..ba53da64a217f 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -70,7 +70,7 @@ mod node; pub mod worker; pub use layer::*; -use node::{Node, NodeEvent}; +use node::*; use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod /// List of telemetry servers we want to talk to. Contains the URL of the server, and the diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index bd519848c41b2..2672d80da492c 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -22,17 +22,14 @@ use futures::prelude::*; use futures_timer::Delay; use libp2p::Multiaddr; use libp2p::core::transport::Transport; -use log::{trace, debug, warn, error}; use rand::Rng as _; -use std::{collections::VecDeque, fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; +use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; use crate::TelemetryConnectionSinks; /// Maximum number of pending telemetry messages. -const MAX_PENDING: usize = 10; - /// Handler for a single telemetry node. -/// TODO: probably dont need to be pub + explain 2 properties of this Sink -pub struct Node { +/// TODO: explain 2 properties of this Sink +pub(crate) struct Node { /// Address of the node. addr: Multiaddr, /// State of the connection. @@ -85,36 +82,11 @@ struct NodeSocketConnected { sink: TTrans::Output, /// Queue of packets to send. TODO remove caching (can be done with SinkExt.buffer()) pending: Vec>, - /// If true, we need to flush the sink. - need_flush: bool, - /// A timeout for the socket to write data. - timeout: Option, -} - -/// Event that can happen with this node. -#[derive(Debug)] -pub enum NodeEvent { - /// We are now connected to this node. - Connected, - /// We are now disconnected from this node. - Disconnected(ConnectionError), -} - -/// Reason for disconnecting from a node. -#[derive(Debug)] -pub enum ConnectionError { - /// The connection timed-out. - Timeout, - /// Reading from the socket returned and end-of-file, indicating that the socket has been - /// closed. - Closed, - /// The sink errored. - Sink(TSinkErr), } impl Node { /// Builds a new node handler. - pub fn new( + pub(crate) fn new( transport: TTrans, addr: Multiaddr, connection_messages: Vec, @@ -131,7 +103,7 @@ impl Node { } /// Returns the address that was passed to `new`. - pub fn addr(&self) -> &Multiaddr { + pub(crate) fn addr(&self) -> &Multiaddr { &self.addr } } @@ -143,33 +115,12 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, + Unpin, TSinkErr: fmt::Debug { -/* - /// Sends a WebSocket frame to the node. Returns an error if we are not connected to the node. - /// - /// After calling this method, you should call `poll` in order for it to be properly processed. - pub fn send_message(&mut self, payload: impl Into>) -> Result<(), ()> { - if let NodeSocket::Connected(NodeSocketConnected { pending, .. }) = &mut self.socket { - if pending.len() <= MAX_PENDING { - trace!(target: "telemetry", "Adding log entry to queue for {:?}", self.addr); - pending.push_back(payload.into()); - Ok(()) - } else { - warn!(target: "telemetry", "⚠️ Rejected log entry because queue is full for {:?}", - self.addr); - Err(()) - } - } else { - Err(()) - } - } -*/ - // NOTE: this code has been inspired from `Buffer` (`futures_util::sink::Buffer`). // https://docs.rs/futures-util/0.3.8/src/futures_util/sink/buffer.rs.html#32 fn try_send_connection_messages( mut self: Pin<&mut Self>, cx: &mut Context<'_>, - mut conn: &mut NodeSocketConnected, + conn: &mut NodeSocketConnected, ) -> Poll> { while let Some(item) = self.buf.pop() { if let Err(e) = conn.sink.start_send_unpin(item) { @@ -182,7 +133,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } // TODO not pub -pub enum Infallible {} +pub(crate) enum Infallible {} impl Sink for Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, @@ -201,7 +152,8 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, match conn.sink.poll_ready_unpin(cx) { Poll::Ready(Ok(())) => { match self.as_mut().try_send_connection_messages(cx, &mut conn) { - Poll::Ready(Err(e)) => { + Poll::Ready(Err(err)) => { + log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); }, Poll::Ready(Ok(())) => { @@ -215,7 +167,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } }, Poll::Ready(Err(err)) => { - warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); + log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); }, Poll::Pending => { @@ -225,14 +177,12 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { - Poll::Ready(Ok(mut sink)) => { - debug!(target: "telemetry", "✅ Connected to {}", self.addr); + Poll::Ready(Ok(sink)) => { + log::debug!(target: "telemetry", "✅ Connected to {}", self.addr); - let mut conn = NodeSocketConnected { + let conn = NodeSocketConnected { sink, pending: Vec::new(), - need_flush: false, - timeout: None, }; for connection_sink in self.connection_sinks.iter() { @@ -251,17 +201,17 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, }, Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { - warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); + log::warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); } } NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { Ok(d) => { - debug!(target: "telemetry", "Started dialing {}", self.addr); + log::debug!(target: "telemetry", "Started dialing {}", self.addr); socket = NodeSocket::Dialing(d); } Err(err) => { - warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); + log::warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); } } @@ -272,7 +222,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, break NodeSocket::WaitingReconnect(s) } NodeSocket::Poisoned => { - error!(target: "telemetry", "‼️ Poisoned connection with {}", self.addr); + log::error!(target: "telemetry", "‼️ Poisoned connection with {}", self.addr); break NodeSocket::Poisoned } } @@ -287,7 +237,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, let _ = conn.sink.start_send_unpin(item.into()).expect("boo"); }, socket => { - error!( + log::error!( target: "telemetry", "Trying to send something but the connection is not ready ({:?}). This is a bug. Message sent: {}", @@ -322,121 +272,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } -/// Generates a `Delay` object with a random timeout. -/// -/// If there are general connection issues, not all endpoints should be synchronized in their -/// re-connection time. -fn gen_rand_reconnect_delay() -> Delay { - let random_delay = rand::thread_rng().gen_range(5, 10); - Delay::new(Duration::from_secs(random_delay)) -} - -/* -impl NodeSocketConnected -where TTrans::Output: Sink, Error = TSinkErr> - + Stream, TSinkErr>> - + Unpin -{ - /// Processes the queue of messages for the connected socket. - /// - /// The address is passed for logging purposes only. - fn poll( - mut self: Pin<&mut Self>, - cx: &mut Context, - my_addr: &Multiaddr, - ) -> Poll>> { - let nothing_pending = self.pending.len(); - - while let Some(item) = self.pending.pop_front() { - if let Poll::Ready(result) = Sink::poll_ready(Pin::new(&mut self.sink), cx) { - if let Err(err) = result { - return Poll::Ready(Err(ConnectionError::Sink(err))) - } - - let item_len = item.len(); - //log::error!(target: "telemetry", "##### sending"); - if let Err(err) = Sink::start_send(Pin::new(&mut self.sink), item) { - //log::error!(target: "telemetry", "##### fail"); - return Poll::Ready(Err(ConnectionError::Sink(err))) - } - //log::error!(target: "telemetry", "##### success"); - trace!( - target: "telemetry", "Successfully sent {:?} bytes message to {}", - item_len, my_addr - ); - self.need_flush = true; - - } else { - self.pending.push_front(item); - if self.timeout.is_none() { - self.timeout = Some(Delay::new(Duration::from_secs(10))); - } - break; - } - } - - if self.need_flush { - match Sink::poll_flush(Pin::new(&mut self.sink), cx) { - Poll::Pending => { - if self.timeout.is_none() { - self.timeout = Some(Delay::new(Duration::from_secs(10))); - log::error!(target: "telemetry", "##### reset timeout"); - } else { - // TODO browser always go here - //log::error!(target: "telemetry", "##### kept timeout"); - } - }, - Poll::Ready(Err(err)) => { - self.timeout = None; - log::error!(target: "telemetry", "##### remove timeout"); - return Poll::Ready(Err(ConnectionError::Sink(err))) - }, - Poll::Ready(Ok(())) => { - log::error!(target: "telemetry", "##### remove timeout"); - // TODO native always go there - self.timeout = None; - self.need_flush = false; - }, - } - } - - if nothing_pending == 0 { - log::error!(target: "telemetry", "##### reset timeout"); - self.timeout = None; - } - //log::error!(target: "telemetry", "##### no reset timeout: {}", nothing_pending); - - if let Some(timeout) = self.timeout.as_mut() { - match Future::poll(Pin::new(timeout), cx) { - Poll::Pending => {}, - Poll::Ready(()) => { - log::error!(target: "telemetry", "##### timeout!"); - self.timeout = None; - return Poll::Ready(Err(ConnectionError::Timeout)) - } - } - } - - match Stream::poll_next(Pin::new(&mut self.sink), cx) { - Poll::Ready(Some(Ok(_))) => { - // We poll the telemetry `Stream` because the underlying implementation relies on - // this in order to answer PINGs. - // We don't do anything with incoming messages, however. - }, - Poll::Ready(Some(Err(err))) => { - return Poll::Ready(Err(ConnectionError::Sink(err))) - }, - Poll::Ready(None) => { - return Poll::Ready(Err(ConnectionError::Closed)) - }, - Poll::Pending => {}, - } - - Poll::Pending - } -} -*/ - impl fmt::Debug for Node { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let state = match self.socket { From f433698b970262d09eb431d64b3a69fbcd64cef3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 10:23:00 +0100 Subject: [PATCH 134/222] CLEANUP --- client/telemetry/src/node.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 2672d80da492c..67c095971a7a6 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -37,7 +37,6 @@ pub(crate) struct Node { /// Transport used to establish new connections. transport: TTrans, connection_messages: Vec, - buf: Vec>, connection_sinks: Vec, } @@ -80,8 +79,8 @@ impl NodeSocket { struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, - /// Queue of packets to send. TODO remove caching (can be done with SinkExt.buffer()) - pending: Vec>, + /// Queue of packets to send before accepting new packets. + buf: Vec>, } impl Node { @@ -96,7 +95,6 @@ impl Node { addr, socket: NodeSocket::ReconnectNow, transport, - buf: Vec::new(), connection_messages, connection_sinks, } @@ -118,11 +116,11 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, // NOTE: this code has been inspired from `Buffer` (`futures_util::sink::Buffer`). // https://docs.rs/futures-util/0.3.8/src/futures_util/sink/buffer.rs.html#32 fn try_send_connection_messages( - mut self: Pin<&mut Self>, + self: Pin<&mut Self>, cx: &mut Context<'_>, conn: &mut NodeSocketConnected, ) -> Poll> { - while let Some(item) = self.buf.pop() { + while let Some(item) = conn.buf.pop() { if let Err(e) = conn.sink.start_send_unpin(item) { return Poll::Ready(Err(e)); } @@ -180,11 +178,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Ready(Ok(sink)) => { log::debug!(target: "telemetry", "✅ Connected to {}", self.addr); - let conn = NodeSocketConnected { - sink, - pending: Vec::new(), - }; - for connection_sink in self.connection_sinks.iter() { connection_sink.fire(); } @@ -195,9 +188,11 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); buf.push(serde_json::to_vec(obj).expect("todo")); } - let _ = mem::replace(&mut self.buf, buf); - socket = NodeSocket::Connected(conn); + socket = NodeSocket::Connected(NodeSocketConnected { + sink, + buf, + }); }, Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { From 8dc614be18fa6b413d19c01959ad8e6979b76dd4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 10:29:24 +0100 Subject: [PATCH 135/222] CLEANUP --- client/telemetry/src/node.rs | 40 +++++++++++------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 67c095971a7a6..6673f79308449 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -29,6 +29,7 @@ use crate::TelemetryConnectionSinks; /// Maximum number of pending telemetry messages. /// Handler for a single telemetry node. /// TODO: explain 2 properties of this Sink +#[derive(Debug)] pub(crate) struct Node { /// Address of the node. addr: Multiaddr, @@ -53,21 +54,6 @@ enum NodeSocket { Poisoned, } -impl fmt::Debug for NodeSocket { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use NodeSocket::*; - f.write_str( - match self { - Connected(_) => "Connected", - Dialing(_) => "Dialing", - ReconnectNow => "ReconnectNow", - WaitingReconnect(_) => "WaitingReconnect", - Poisoned => "Poisoned", - }, - ) - } -} - impl NodeSocket { fn wait_reconnect() -> NodeSocket { let random_delay = rand::thread_rng().gen_range(5, 10); @@ -267,19 +253,17 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } -impl fmt::Debug for Node { +impl fmt::Debug for NodeSocket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let state = match self.socket { - NodeSocket::Connected(_) => "Connected", - NodeSocket::Dialing(_) => "Dialing", - NodeSocket::ReconnectNow => "Pending reconnect", - NodeSocket::WaitingReconnect(_) => "Pending reconnect", - NodeSocket::Poisoned => "Poisoned", - }; - - f.debug_struct("Node") - .field("addr", &self.addr) - .field("state", &state) - .finish() + use NodeSocket::*; + f.write_str( + match self { + Connected(_) => "Connected", + Dialing(_) => "Dialing", + ReconnectNow => "ReconnectNow", + WaitingReconnect(_) => "WaitingReconnect", + Poisoned => "Poisoned", + }, + ) } } From ddb71efb850ef0d368ee82c2d49de521c81e8ae9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 15:16:55 +0100 Subject: [PATCH 136/222] WIP --- client/telemetry/src/lib.rs | 50 +++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ba53da64a217f..a9f8add71c1fc 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -68,10 +68,12 @@ pub use tracing; mod layer; mod node; pub mod worker; +mod dispatcher; pub use layer::*; use node::*; use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod +use dispatcher::*; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the /// maximum verbosity level. @@ -256,7 +258,7 @@ impl Telemetries { /// TODO pub async fn run(self) { let Self { - mut receiver, + receiver, sender: _sender, mut init_receiver, init_sender, @@ -293,7 +295,7 @@ impl Telemetries { } } - let mut node_pool: HashMap> = + let mut node_pool: Dispatcher = existing_nodes .iter() .map(|addr| { @@ -306,11 +308,10 @@ impl Telemetries { }) .collect(); - let mut messages = receiver - .filter_map(|(id, verbosity, message)| { - // TODO probably wont need anymore + let mut res = receiver + .filter_map(|(id, verbosity, message): (Id, u8, String)| { if let Some(nodes) = node_map.get(&id) { - future::ready(Some((id, verbosity, message, nodes))) + future::ready(Some((verbosity, message, nodes))) } else { log::error!( target: "telemetry", @@ -321,20 +322,11 @@ impl Telemetries { future::ready(None) } }) - .flat_map(|(id, verbosity, message, nodes)| { + .flat_map(|(verbosity, message, nodes): (u8, String, &Vec<(u8, Multiaddr)>)| { let mut to_send = Vec::with_capacity(nodes.len()); let before = Instant::now(); for (node_max_verbosity, addr) in nodes { - if !existing_nodes.contains(addr) { - log::error!( - target: "telemetry", - "Could not find telemetry server in the NodePool: {}", - addr, - ); - continue; - }; - if verbosity > *node_max_verbosity { log::trace!( target: "telemetry", @@ -344,7 +336,7 @@ impl Telemetries { continue; } - to_send.push((addr, message.clone())); + to_send.push((addr.clone(), message.clone())); } if before.elapsed() > Duration::from_millis(200) { @@ -355,14 +347,34 @@ impl Telemetries { } stream::iter(to_send) - }); - // TODO make it forward to a sink that will dispatch? + }) + .map(|x| Ok(x)) + .boxed() + .forward(&mut node_pool) + .await; + + match res { + Ok(()) => {}, + Err(x) => match x {}, + }; + + log::error!( + target: "telemetry", + "Unexpected end of stream. This is a bug.", + ); + + match node_pool.close().await { + Ok(()) => {}, + Err(x) => match x {}, + } + /* while let Some((addr, message)) = messages.next().await { let mut node = node_pool.get_mut(&addr).unwrap(); log::trace!(target: "telemetry", "#### Sending to {}: {}", addr, message); let _ = node.send(message).await; } + */ /* let futures = stream::unfold(messages, |messages| async move { From 49e94346ff478c1d266c50b299951010779e4a2a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 17:25:31 +0100 Subject: [PATCH 137/222] WIP --- client/telemetry/src/dispatcher.rs | 134 +++++++++++++++++++++++++++++ client/telemetry/src/layer.rs | 6 +- 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 client/telemetry/src/dispatcher.rs diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs new file mode 100644 index 0000000000000..44ba430dc542f --- /dev/null +++ b/client/telemetry/src/dispatcher.rs @@ -0,0 +1,134 @@ +use futures::prelude::*; +use std::collections::HashMap; +use crate::node::{Node, Infallible}; +use crate::worker::WsTrans; +use std::iter::FromIterator; +use libp2p::Multiaddr; +use std::task::{Poll, Context}; +use std::pin::Pin; +use std::collections::VecDeque; + +#[derive(Debug)] +pub(crate) struct Dispatcher { + pool: HashMap>, + item: Option<(Multiaddr, String)>, + flush_node: Option, +} + +impl FromIterator<(Multiaddr, Node)> for Dispatcher { + fn from_iter)>>(iter: I) -> Self { + let pool: HashMap<_, _> = FromIterator::from_iter(iter); + Dispatcher { + pool, + item: None, + flush_node: None, + } + } +} + +impl Dispatcher { + fn try_empty_buffer( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + if let Some((addr, message)) = self.item.take() { + let node = if let Some(node) = self.pool.get_mut(&addr) { + node + } else { + log::error!( + target: "telemetry", + "Received message for unknown node ({}). This is a bug. Message sent: {}", + addr, + message, + ); + return Poll::Ready(Ok(())); + }; + + match node.poll_ready_unpin(cx) { + Poll::Ready(Ok(())) => {}, + Poll::Ready(Err(x)) => match x {}, + Poll::Pending => { + self.item = Some((addr, message)); + return Poll::Pending; + } + } + + match node.start_send_unpin(message) { + Ok(()) => {}, + Err(x) => match x {}, + } + + match node.poll_flush_unpin(cx) { + Poll::Ready(Ok(())) => {}, + Poll::Ready(Err(x)) => match x {}, + Poll::Pending => { + self.flush_node = Some(addr); + return Poll::Pending; + }, + } + } + + Poll::Ready(Ok(())) + } +} + +impl Sink<(Multiaddr, String)> for Dispatcher +{ + type Error = Infallible; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + self.try_empty_buffer(cx) + } + + fn start_send(mut self: Pin<&mut Self>, item: (Multiaddr, String)) -> Result<(), Self::Error> { + let overrun = self.item.replace(item).is_some(); + + if overrun { + log::error!( + target: "telemetry", + "Received another message while the previous one has not finished processing. \ + This is a bug", + ); + } + + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if let Some(addr) = self.flush_node.take() { + let node = self.pool.get_mut(&addr).expect("we added the address ourselves; qed"); + match node.poll_flush_unpin(cx) { + Poll::Ready(Ok(())) => return Poll::Ready(Ok(())), + Poll::Ready(Err(x)) => match x {}, + Poll::Pending => { + self.flush_node = Some(addr); + return Poll::Pending; + }, + } + } + + self.try_empty_buffer(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut new_pool = HashMap::with_capacity(self.pool.len()); + + for (addr, mut node) in self.pool.drain() { + match node.poll_close_unpin(cx) { + Poll::Ready(Ok(())) => {}, + Poll::Ready(Err(x)) => match x {}, + Poll::Pending => { + new_pool.insert(addr, node); + }, + } + } + + let _ = std::mem::replace(&mut self.pool, new_pool); + + if self.pool.is_empty() { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + } +} diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 350b458a56a6d..c18f7950a5ed0 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -65,13 +65,15 @@ where .. } = attrs { - let _ = self.0.lock().try_send(( + if self.0.lock().try_send(( id, verbosity .try_into() .expect("telemetry log message verbosity are u8; qed"), json, - )); + )).is_err() { + eprintln!("Telemetry buffer overflowed!"); + } } else { // NOTE: logging in this function doesn't work eprintln!( From ba4274f6f8d682d92bc6e5c320611a3c0ab831d9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 17:42:06 +0100 Subject: [PATCH 138/222] CLEANUP --- client/telemetry/src/dispatcher.rs | 1 - client/telemetry/src/lib.rs | 66 ++---------------------------- client/telemetry/src/node.rs | 5 --- client/telemetry/src/worker.rs | 11 +---- 4 files changed, 5 insertions(+), 78 deletions(-) diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs index 44ba430dc542f..dea5dc6a726fd 100644 --- a/client/telemetry/src/dispatcher.rs +++ b/client/telemetry/src/dispatcher.rs @@ -6,7 +6,6 @@ use std::iter::FromIterator; use libp2p::Multiaddr; use std::task::{Poll, Context}; use std::pin::Pin; -use std::collections::VecDeque; #[derive(Debug)] pub(crate) struct Dispatcher { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index a9f8add71c1fc..17aeca6f57d78 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -48,17 +48,15 @@ use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::{ collections::{HashMap, HashSet}, - fmt, io, pin::Pin, sync::Arc, - task::{Context, Poll}, time::Duration, }; use wasm_timer::Instant; use tracing::Id; use parking_lot::Mutex; -use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; +use sp_utils::{mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; @@ -266,10 +264,8 @@ impl Telemetries { } = self; let mut node_map: HashMap> = HashMap::new(); - let mut node_map_inv: HashMap> = HashMap::new(); // TODO remove? let mut connection_messages: HashMap> = HashMap::new(); let mut connection_sinks: HashMap> = HashMap::new(); - let mut node_first_connect: HashSet<(Multiaddr, Id)> = HashSet::new(); // TODO remove? let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes @@ -281,8 +277,6 @@ impl Telemetries { for (addr, verbosity) in endpoints { node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); - node_map_inv.entry(addr.clone()).or_insert_with(Vec::new).push(id.clone()); - node_first_connect.insert((addr.clone(), id.clone())); existing_nodes.insert(addr.clone()); let mut json = connection_message.clone(); let obj = json.as_object_mut().expect("todo"); @@ -307,8 +301,9 @@ impl Telemetries { (addr.clone(), node) }) .collect(); + //let mut node_pool = node_pool.buffer(2000); - let mut res = receiver + let res = receiver .filter_map(|(id, verbosity, message): (Id, u8, String)| { if let Some(nodes) = node_map.get(&id) { future::ready(Some((verbosity, message, nodes))) @@ -367,61 +362,6 @@ impl Telemetries { Ok(()) => {}, Err(x) => match x {}, } - - /* - while let Some((addr, message)) = messages.next().await { - let mut node = node_pool.get_mut(&addr).unwrap(); - log::trace!(target: "telemetry", "#### Sending to {}: {}", addr, message); - let _ = node.send(message).await; - } - */ - - /* - let futures = stream::unfold(messages, |messages| async move { - let (addr, message) = messages.next().await?; - if let Some(node) = node_pool.get(addr) { - Some((node.send(message), messages)) - } else { - todo!() - } - }); - */ - - // loop indefinitely over telemetry messages - /* - while let Some() = receiver.next().await { - // Detect re-connection - let node_status = node.next().await; - if matches!(node_status, Some(NodeEvent::Connected)) { - // All the instances must re-send the connection message - node_first_connect.extend( - node_map_inv.get(addr) - .iter() - .map(|x| x.iter()) - .flatten() - .map(|id| (addr.clone(), id.to_owned())), - ); - } - - // Reconnection handling - if matches!(node_status, Some(NodeEvent::Connected) | None) { - if node_first_connect.remove(&(addr.to_owned(), id.clone())) { - if let Some(connection_sink) = connection_sinks.get(&id) { - connection_sink.fire(); - } - if let Some(json) = connection_messages.get(&id) { - let mut json = json.clone(); - let obj = json.as_object_mut().expect("todo"); - obj.insert("msg".into(), "system.connected".into()); - obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); - obj.insert("id".into(), id.into_u64().into()); - let _ = node.send_message(serde_json::to_string(obj).expect("todo")); - } - } - } - - } - */ } } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 6673f79308449..8ba035b74d81d 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -85,11 +85,6 @@ impl Node { connection_sinks, } } - - /// Returns the address that was passed to `new`. - pub(crate) fn addr(&self) -> &Multiaddr { - &self.addr - } } impl Node diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index a376646cf4ba0..d7805c86cef6f 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -29,15 +29,8 @@ //! use futures::{prelude::*, ready}; -use libp2p::{ - core::transport::{OptionalTransport, timeout::TransportTimeout}, - Multiaddr, - Transport, - wasm_ext -}; -use log::{trace, error}; -use parking_lot::Mutex; -use std::{io, pin::Pin, sync::Arc, task::Context, task::Poll, time}; +use log::{error}; +use std::{io, pin::Pin, task::Context, task::Poll, time}; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. From b49a0f488eb6659fb0f9761ea9948c87748ef195 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 11 Dec 2020 17:48:41 +0100 Subject: [PATCH 139/222] CLEANUP --- client/telemetry/src/lib.rs | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 17aeca6f57d78..0377996d13572 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -143,16 +143,6 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -/* - * TODO -impl Drop for Telemetry { - fn drop(&mut self) { - let span_id = self.span.id().expect("the span is enabled; qed"); - tracing::dispatcher::get_default(move |dispatch| dispatch.exit(&span_id)); - } -} -*/ - pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionSinks); /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. @@ -301,9 +291,8 @@ impl Telemetries { (addr.clone(), node) }) .collect(); - //let mut node_pool = node_pool.buffer(2000); - let res = receiver + let _ = receiver .filter_map(|(id, verbosity, message): (Id, u8, String)| { if let Some(nodes) = node_map.get(&id) { future::ready(Some((verbosity, message, nodes))) @@ -348,20 +337,10 @@ impl Telemetries { .forward(&mut node_pool) .await; - match res { - Ok(()) => {}, - Err(x) => match x {}, - }; - log::error!( target: "telemetry", "Unexpected end of stream. This is a bug.", ); - - match node_pool.close().await { - Ok(()) => {}, - Err(x) => match x {}, - } } } @@ -401,6 +380,7 @@ impl TelemetryHandle { } } +// TODO maybe rename because it's confusing /// Sinks to propagate telemetry connection established events. #[derive(Default, Clone, Debug)] pub struct TelemetryConnectionSinks(Arc>>>); From eb9aed3cb380ba919d85a7cbf8d568caea05c8c6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 11:20:26 +0100 Subject: [PATCH 140/222] Revert "Make prefix_logs_with accessible also from sc-cli" This reverts commit bed3d310c70308a9dc62ba4683cf616681c10fcb. --- Cargo.lock | 23 ++++---------------- client/cli/Cargo.toml | 1 - client/cli/src/lib.rs | 3 +-- client/cli/tests/ui.rs | 23 -------------------- client/cli/tests/ui/prefix_logs_with.rs | 28 ------------------------- client/tracing/proc-macro/src/lib.rs | 17 +++++++-------- 6 files changed, 13 insertions(+), 82 deletions(-) delete mode 100644 client/cli/tests/ui.rs delete mode 100644 client/cli/tests/ui/prefix_logs_with.rs diff --git a/Cargo.lock b/Cargo.lock index 71d1d61d67279..9d8c9961dd2cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1653,7 +1653,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-std", - "trybuild 1.0.35 (git+https://github.com/bkchr/trybuild.git?branch=bkchr-use-workspace-cargo-lock)", + "trybuild", ] [[package]] @@ -6400,7 +6400,6 @@ dependencies = [ "tiny-bip39", "tokio 0.2.23", "tracing", - "trybuild 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -7871,7 +7870,7 @@ dependencies = [ "sp-state-machine", "sp-version", "substrate-test-runtime-client", - "trybuild 1.0.35 (git+https://github.com/bkchr/trybuild.git?branch=bkchr-use-workspace-cargo-lock)", + "trybuild", ] [[package]] @@ -8324,7 +8323,7 @@ dependencies = [ "sp-tracing", "sp-wasm-interface", "static_assertions", - "trybuild 1.0.35 (git+https://github.com/bkchr/trybuild.git?branch=bkchr-use-workspace-cargo-lock)", + "trybuild", ] [[package]] @@ -8909,7 +8908,7 @@ dependencies = [ "sc-service", "substrate-test-utils-derive", "tokio 0.2.23", - "trybuild 1.0.35 (git+https://github.com/bkchr/trybuild.git?branch=bkchr-use-workspace-cargo-lock)", + "trybuild", ] [[package]] @@ -9573,20 +9572,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -[[package]] -name = "trybuild" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d30fe369fd650072b352b1a9cb9587669de6b89be3b8225544012c1c45292d" -dependencies = [ - "glob", - "lazy_static", - "serde", - "serde_json", - "termcolor", - "toml", -] - [[package]] name = "trybuild" version = "1.0.35" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 285faec1501e1..d2777f503bcda 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -50,7 +50,6 @@ rpassword = "5.0.0" [dev-dependencies] tempfile = "3.1.0" -trybuild = "1.0.35" [features] wasmtime = [ diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 0f1501f19702f..ebbbf455f075c 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -46,8 +46,7 @@ use structopt::{ }; use sc_tracing::logging; #[doc(hidden)] -pub use sc_tracing; -pub use sc_tracing::logging::prefix_logs_with; +pub use tracing; /// Substrate client CLI /// diff --git a/client/cli/tests/ui.rs b/client/cli/tests/ui.rs deleted file mode 100644 index d39ab6574a929..0000000000000 --- a/client/cli/tests/ui.rs +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#[test] -fn prefix_logs_with() { - let t = trybuild::TestCases::new(); - t.pass("tests/ui/prefix_logs_with.rs"); -} diff --git a/client/cli/tests/ui/prefix_logs_with.rs b/client/cli/tests/ui/prefix_logs_with.rs deleted file mode 100644 index ea504303162b4..0000000000000 --- a/client/cli/tests/ui/prefix_logs_with.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -mod sc_tracing {} - -/// This test ensures that prefix_logs_with is usable from sc_cli directly without importing -/// sc_logging. -#[sc_cli::prefix_logs_with("test")] -fn prefix_in_log_lines_process() { - unimplemented!(); -} - -fn main() {} diff --git a/client/tracing/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs index d563e5e5271a4..639aa6dd28d68 100644 --- a/client/tracing/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -20,7 +20,7 @@ use proc_macro::TokenStream; use proc_macro2::Span; use proc_macro_crate::crate_name; use quote::quote; -use syn::{Error, Expr, Ident, ItemFn, Path}; +use syn::{Error, Expr, Ident, ItemFn}; /// Add a log prefix to the function. /// @@ -122,15 +122,14 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { .expect("cargo env var always there when compiling; qed") == "sc-tracing" { - Path::from(Ident::new("sc_tracing", Span::call_site())) + Ident::from(Ident::new("sc_tracing", Span::call_site())) } else { - match crate_name("sc-cli") { - Ok(x) => syn::parse_str::(&format!("{}::sc_tracing", x)).unwrap(), - Err(_) => match crate_name("sc-tracing") { - Ok(x) => Path::from(Ident::new(&x, Span::call_site())), - Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), - }, - } + let crate_name = match crate_name("sc-tracing") { + Ok(x) => x, + Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(), + }; + + Ident::new(&crate_name, Span::call_site()) }; let ItemFn { From 6cf9af2d0751e97132728fd4956aee56d10990e2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 11:30:58 +0100 Subject: [PATCH 141/222] Add check for first character in json attribute --- client/telemetry/src/layer.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index c18f7950a5ed0..1a55aba9f6667 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -121,6 +121,12 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { + if value.chars().next() == Some('{') { + eprintln!( + "Invalid value for JSON in telemetry logging: \ + the attribute's value `json` doesn't start with the character `{{`", + ); + } // NOTE: this is a hack to inject the span id into the json let mut message = format!(r#"{{"id":{},"#, (*self.0).id.into_u64()); message.push_str(&value[1..]); From ef26df600d4cf52b4098de844812dbac25134133 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 12:14:20 +0100 Subject: [PATCH 142/222] WIP --- client/telemetry/src/lib.rs | 2 +- client/telemetry/src/node.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 0377996d13572..d654e68b4fed1 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -388,7 +388,7 @@ pub struct TelemetryConnectionSinks(Arc>>>) impl TelemetryConnectionSinks { /// Get event stream for telemetry connection established events. pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { - let (sink, stream) =tracing_unbounded("mpsc_telemetry_on_connect"); + let (sink, stream) = tracing_unbounded("mpsc_telemetry_on_connect"); self.0.lock().push(sink); stream } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 8ba035b74d81d..2f5ccd8e74fd0 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -124,6 +124,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, type Error = Infallible; fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + // TODO discard messages let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); self.socket = loop { match socket { From 32b0b14ddd81974b5286c80c1fe5c787474f927e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 12:43:45 +0100 Subject: [PATCH 143/222] Remove passing around of WASM transport --- Cargo.lock | 1 + client/cli/src/config.rs | 12 +------- client/cli/src/lib.rs | 5 ---- client/service/src/config.rs | 3 -- client/telemetry/Cargo.toml | 4 ++- client/telemetry/src/lib.rs | 46 ++++++++----------------------- client/tracing/src/logging/mod.rs | 22 ++------------- utils/browser/src/lib.rs | 1 - 8 files changed, 18 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d8c9961dd2cc..4d29cffbf1bd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7339,6 +7339,7 @@ dependencies = [ "futures 0.3.8", "futures-timer 3.0.2", "libp2p", + "libp2p-wasm-ext", "log", "parking_lot 0.11.1", "pin-project 0.4.27", diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index a5d369999248e..59fae27e51fb3 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -28,7 +28,7 @@ use log::warn; use names::{Generator, Name}; use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::config::{ - BasePath, Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration, + BasePath, Configuration, DatabaseConfig, KeystoreConfig, NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods, TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; @@ -362,13 +362,6 @@ pub trait CliConfiguration: Sized { Ok(chain_spec.telemetry_endpoints().clone()) } - /// Get the telemetry external transport - /// - /// By default this is `None`. - fn telemetry_external_transport(&self) -> Result> { - Ok(None) - } - /// Get the default value for heap pages /// /// By default this is `None`. @@ -508,7 +501,6 @@ pub trait CliConfiguration: Sized { rpc_cors: self.rpc_cors(is_dev)?, prometheus_config: self.prometheus_config(DCV::prometheus_listen_port())?, telemetry_endpoints: self.telemetry_endpoints(&chain_spec)?, - telemetry_external_transport: self.telemetry_external_transport()?, default_heap_pages: self.default_heap_pages()?, offchain_worker: self.offchain_worker(&role)?, force_authoring: self.force_authoring()?, @@ -554,7 +546,6 @@ pub trait CliConfiguration: Sized { let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; let disable_log_reloading = self.is_log_filter_reloading_disabled()?; - let telemetry_external_transport = self.telemetry_external_transport()?; sp_panic_handler::set(&C::support_url(), &C::impl_version()); @@ -562,7 +553,6 @@ pub trait CliConfiguration: Sized { &logger_pattern, tracing_receiver, tracing_targets.as_ref().map(|x| x.as_str()), - telemetry_external_transport, disable_log_reloading, )?; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index ebbbf455f075c..8ee58a051c44f 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -237,14 +237,12 @@ pub fn init_logging_and_telemetry( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option<&str>, - telemetry_external_transport: Option, disable_log_reloading: bool, ) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { if disable_log_reloading { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( pattern, - telemetry_external_transport, tracing_receiver, profiling_targets, )?; @@ -259,7 +257,6 @@ pub fn init_logging_and_telemetry( } else { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( pattern, - telemetry_external_transport, tracing_receiver, profiling_targets, )?; @@ -276,7 +273,6 @@ pub fn init_logging_and_telemetry( if disable_log_reloading { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( pattern, - telemetry_external_transport, )?; if let Err(e) = tracing::subscriber::set_global_default(subscriber) { @@ -289,7 +285,6 @@ pub fn init_logging_and_telemetry( } else { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_log_reloading( pattern, - telemetry_external_transport, )?; if let Err(e) = tracing::subscriber::set_global_default(subscriber) { diff --git a/client/service/src/config.rs b/client/service/src/config.rs index e6f6d3a16b322..fa7bfb768b892 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -84,9 +84,6 @@ pub struct Configuration { pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. pub telemetry_endpoints: Option, - /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry - /// endpoint, this transport will be tried in priority before all others. - pub telemetry_external_transport: Option, /// Telemetry handle. pub telemetry_handle: Option, /// The default number of 64KB pages to allocate for Wasm execution diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index fbc0e4c54d399..32af4412c0a43 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -13,7 +13,6 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - [dependencies] parking_lot = "0.11.0" futures = "0.3.4" @@ -31,3 +30,6 @@ tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } + +[target.'cfg(target_os = "unknown")'.dependencies] +libp2p-wasm-ext = { version = "0.25", features = ["websocket"] } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d654e68b4fed1..87db96b13ccb9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -41,8 +41,7 @@ use futures::{channel::mpsc, prelude::*}; use libp2p::{ - core::transport::{OptionalTransport, timeout::TransportTimeout}, - wasm_ext, Multiaddr, Transport, + core::transport::timeout::TransportTimeout, Multiaddr, Transport, }; use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; @@ -70,7 +69,7 @@ mod dispatcher; pub use layer::*; use node::*; -use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod +use worker::CONNECT_TIMEOUT; // TODO mod use dispatcher::*; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the @@ -168,46 +167,23 @@ impl Telemetries { sender, init_receiver, init_sender, - transport: Self::initialize_transport(None)?, + transport: Self::initialize_transport()?, }) } - /// Create a [`Telemetries`] object using an `ExtTransport`. - /// - /// This is used in WASM contexts where we need some binding between the networking provided by - /// the operating system or environment and libp2p. - /// - /// This constructor is expected to be used only when compiling for WASM. - /// - /// > **Important**: Each individual call to `write` corresponds to one message. There is no - /// > internal buffering going on. In the context of WebSockets, each `write` - /// > must be one individual WebSockets frame. - pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Result { - let (sender, receiver) = mpsc::channel(16); - let (init_sender, init_receiver) = mpsc::unbounded(); - - Ok(Self { - receiver, - sender, - init_receiver, - init_sender, - transport: Self::initialize_transport(Some(wasm_external_transport))?, - }) - } - - fn initialize_transport( - wasm_external_transport: Option, - ) -> Result { - let transport = match wasm_external_transport.clone() { - Some(t) => OptionalTransport::some(t), - None => OptionalTransport::none() + fn initialize_transport() -> Result { + // TODO refactor + #[cfg(target_os = "unknown")] + let transport = { + use libp2p_wasm_ext::{ExtTransport, ffi}; + ExtTransport::new(ffi::websocket_transport()) }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); // The main transport is the `wasm_external_transport`, but if we're on desktop we add // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass // an external transport on desktop and the fallback is used all the time. #[cfg(not(target_os = "unknown"))] - let transport = transport.or_transport({ + let transport = { let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; libp2p::websocket::framed::WsConfig::new(inner) .and_then(|connec, _| { @@ -220,7 +196,7 @@ impl Telemetries { .map_ok(|data| data.into_bytes()); future::ready(Ok::<_, io::Error>(connec)) }) - }); + }; Ok(TransportTimeout::new( transport.map(|out, _| { diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 1a6ee051880df..b71be169692aa 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -49,7 +49,6 @@ macro_rules! disable_log_reloading { /// TODO pub fn get_default_subscriber_and_telemetries( pattern: &str, - telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -59,18 +58,14 @@ pub fn get_default_subscriber_and_telemetries( > { get_default_subscriber_and_telemetries_internal( parse_directives(pattern), - telemetry_external_transport, |builder| builder, ) } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] pub fn get_default_subscriber_and_telemetries_with_log_reloading( pattern: &str, - telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -80,18 +75,14 @@ pub fn get_default_subscriber_and_telemetries_with_log_reloading( > { get_default_subscriber_and_telemetries_internal( parse_directives(pattern), - telemetry_external_transport, |builder| disable_log_reloading!(builder), ) } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with /// profiling enabled. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. pub fn get_default_subscriber_and_telemetries_with_profiling( pattern: &str, - telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< @@ -105,7 +96,6 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), - telemetry_external_transport, |builder| builder, )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); @@ -115,12 +105,9 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with /// profiling enabled. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( pattern: &str, - telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< @@ -134,7 +121,6 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), - telemetry_external_transport, |builder| disable_log_reloading!(builder), )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); @@ -146,7 +132,6 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( // `get_default_subscriber_and_telemetries_with_profiling`. fn get_default_subscriber_and_telemetries_internal( extra_directives: impl IntoIterator, - telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< ( @@ -226,11 +211,8 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetries = if let Some(telemetry_external_transport) = telemetry_external_transport { - sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) - } else { - sc_telemetry::Telemetries::new() - }.map_err(|err| format!("Could not initialize telemetry: {}", err))?; + let telemetries = sc_telemetry::Telemetries::new() + .map_err(|err| format!("Could not initialize telemetry: {}", err))?; let sender = telemetries.sender(); let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); let event_format = EventFormat { diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 9c8d80cd61585..c62c662379c8b 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -87,7 +87,6 @@ where wasm_bindgen_futures::spawn_local(fut); async {} }).into(), - telemetry_external_transport: Some(transport), telemetry_handle, role: Role::Light, database: { From 3c12ba7e5f4c9e3580085c441e7a79751cc806d1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 12:46:51 +0100 Subject: [PATCH 144/222] Fix previous commit --- client/telemetry/src/lib.rs | 3 +-- utils/browser/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 87db96b13ccb9..6cdcd68bca4c3 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -172,12 +172,11 @@ impl Telemetries { } fn initialize_transport() -> Result { - // TODO refactor #[cfg(target_os = "unknown")] let transport = { use libp2p_wasm_ext::{ExtTransport, ffi}; ExtTransport::new(ffi::websocket_transport()) - }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); + }.map((|inner, _| worker::StreamSink::from(inner)) as fn(_, _) -> _); // The main transport is the `wasm_external_transport`, but if we're on desktop we add // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index c62c662379c8b..ee60b2ccd5c4d 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -43,7 +43,6 @@ pub fn init_logging_and_telemetry( let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, - Some(transport.clone()), )?; tracing::subscriber::set_global_default(subscriber) From 834eac41a175aff8f4831b98817f2da030ca6de0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 12:56:10 +0100 Subject: [PATCH 145/222] Remove passing around of WASM transport (sc-network) --- Cargo.lock | 1 + bin/node/cli/src/browser.rs | 4 ++-- client/cli/src/params/network_params.rs | 1 - client/network/Cargo.toml | 3 +++ client/network/src/config.rs | 11 +---------- client/network/src/service.rs | 14 ++++++++++---- utils/browser/src/lib.rs | 8 ++------ 7 files changed, 19 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d29cffbf1bd9..3c54d6a4590de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6954,6 +6954,7 @@ dependencies = [ "hex", "ip_network", "libp2p", + "libp2p-wasm-ext", "linked-hash-map", "linked_hash_set", "log", diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 9d579d511188e..ce928cd932015 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,14 +34,14 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let (telemetries, transport) = init_logging_and_telemetry(&log_directives)?; + let telemetries = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; + let mut config = browser_configuration(chain_spec, Some(telemetries.handle())).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index a973d61272ced..415f6ee564a35 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -168,7 +168,6 @@ impl NetworkParams { transport: TransportConfig::Normal { enable_mdns: !is_dev && !self.no_mdns, allow_private_ipv4: !self.no_private_ipv4, - wasm_external_transport: None, }, max_parallel_downloads: self.max_parallel_downloads, allow_non_globals_in_dht, diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 7e78808fa4fe1..38001c116f34f 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -66,6 +66,9 @@ version = "0.31.2" default-features = false features = ["identify", "kad", "mdns-async-std", "mplex", "noise", "ping", "request-response", "tcp-async-std", "websocket", "yamux"] +[target.'cfg(target_os = "unknown")'.dependencies] +libp2p-wasm-ext = { version = "0.25", features = ["websocket"] } + [dev-dependencies] assert_matches = "1.3" libp2p = { version = "0.31.2", default-features = false } diff --git a/client/network/src/config.rs b/client/network/src/config.rs index b7b113dc14692..c8eeb9006fbc1 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -37,7 +37,7 @@ use core::{fmt, iter}; use futures::future; use libp2p::{ identity::{ed25519, Keypair}, - multiaddr, wasm_ext, Multiaddr, PeerId, + multiaddr, Multiaddr, PeerId, }; use prometheus_endpoint::Registry; use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; @@ -422,7 +422,6 @@ impl NetworkConfiguration { transport: TransportConfig::Normal { enable_mdns: false, allow_private_ipv4: true, - wasm_external_transport: None, }, max_parallel_downloads: 5, allow_non_globals_in_dht: false, @@ -483,14 +482,6 @@ pub enum TransportConfig { /// been passed in [`NetworkConfiguration::reserved_nodes`] or /// [`NetworkConfiguration::boot_nodes`]. allow_private_ipv4: bool, - - /// Optional external implementation of a libp2p transport. Used in WASM contexts where we - /// need some binding between the networking provided by the operating system or environment - /// and libp2p. - /// - /// This parameter exists whatever the target platform is, but it is expected to be set to - /// `Some` only when compiling for WASM. - wasm_external_transport: Option, }, /// Only allow connections within the same process. diff --git a/client/network/src/service.rs b/client/network/src/service.rs index b6f162affd671..945f025f09dcb 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -349,11 +349,17 @@ impl NetworkWorker { behaviour.register_notifications_protocol(protocol.clone()); } let (transport, bandwidth) = { - let (config_mem, config_wasm) = match params.network_config.transport { - TransportConfig::MemoryOnly => (true, None), - TransportConfig::Normal { wasm_external_transport, .. } => - (false, wasm_external_transport) + let config_mem = match params.network_config.transport { + TransportConfig::MemoryOnly => true, + TransportConfig::Normal { .. } => false, }; + #[cfg(target_os = "unknown")] + let config_wasm = { + use libp2p_wasm_ext::{ExtTransport, ffi}; + Some(ExtTransport::new(ffi::websocket_transport())) + }; + #[cfg(not(target_os = "unknown"))] + let config_wasm = None; transport::build_transport(local_identity, config_mem, config_wasm) }; let mut builder = SwarmBuilder::new(transport, behaviour, local_peer_id.clone()) diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index ee60b2ccd5c4d..cfe7da086364a 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -29,7 +29,6 @@ use futures::{ }; use std::pin::Pin; use sc_chain_spec::Extension; -use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; @@ -39,8 +38,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { - let transport = ExtTransport::new(ffi::websocket_transport()); +) -> Result { let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, )?; @@ -48,7 +46,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok((telemetries, transport)) + Ok(telemetries) } /// Create a service configuration from a chain spec. @@ -57,7 +55,6 @@ pub fn init_logging_and_telemetry( pub async fn browser_configuration( chain_spec: GenericChainSpec, telemetry_handle: Option, - transport: ExtTransport, ) -> Result> where G: RuntimeGenesis + 'static, @@ -73,7 +70,6 @@ where ); network.boot_nodes = chain_spec.boot_nodes().to_vec(); network.transport = TransportConfig::Normal { - wasm_external_transport: Some(transport.clone()), allow_private_ipv4: true, enable_mdns: false, }; From a63bb25e0446a4228f7b2bdb68aec28f806dd345 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 12:59:34 +0100 Subject: [PATCH 146/222] Removed useless proof --- client/tracing/src/logging/layers/prefix_layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tracing/src/logging/layers/prefix_layer.rs b/client/tracing/src/logging/layers/prefix_layer.rs index 843845bf6408e..67a6afb420664 100644 --- a/client/tracing/src/logging/layers/prefix_layer.rs +++ b/client/tracing/src/logging/layers/prefix_layer.rs @@ -62,7 +62,7 @@ macro_rules! write_node_name { ($method:ident, $type:ty, $format:expr) => { fn $method(&mut self, field: &tracing::field::Field, value: $type) { if field.name() == "name" { - write!(self.0, $format, value).expect("no way to return the err; qed"); + let _ = write!(self.0, $format, value); } } }; From 2c24ccb5f647e891e00013500903e54b5d06b727 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 13:09:38 +0100 Subject: [PATCH 147/222] Revert "Remove passing around of WASM transport (sc-network)" This reverts commit 834eac41a175aff8f4831b98817f2da030ca6de0. --- Cargo.lock | 1 - bin/node/cli/src/browser.rs | 4 ++-- client/cli/src/params/network_params.rs | 1 + client/network/Cargo.toml | 3 --- client/network/src/config.rs | 11 ++++++++++- client/network/src/service.rs | 14 ++++---------- utils/browser/src/lib.rs | 8 ++++++-- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c54d6a4590de..4d29cffbf1bd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6954,7 +6954,6 @@ dependencies = [ "hex", "ip_network", "libp2p", - "libp2p-wasm-ext", "linked-hash-map", "linked_hash_set", "log", diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index ce928cd932015..9d579d511188e 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,14 +34,14 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let telemetries = init_logging_and_telemetry(&log_directives)?; + let (telemetries, transport) = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, Some(telemetries.handle())).await?; + let mut config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 415f6ee564a35..a973d61272ced 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -168,6 +168,7 @@ impl NetworkParams { transport: TransportConfig::Normal { enable_mdns: !is_dev && !self.no_mdns, allow_private_ipv4: !self.no_private_ipv4, + wasm_external_transport: None, }, max_parallel_downloads: self.max_parallel_downloads, allow_non_globals_in_dht, diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 38001c116f34f..7e78808fa4fe1 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -66,9 +66,6 @@ version = "0.31.2" default-features = false features = ["identify", "kad", "mdns-async-std", "mplex", "noise", "ping", "request-response", "tcp-async-std", "websocket", "yamux"] -[target.'cfg(target_os = "unknown")'.dependencies] -libp2p-wasm-ext = { version = "0.25", features = ["websocket"] } - [dev-dependencies] assert_matches = "1.3" libp2p = { version = "0.31.2", default-features = false } diff --git a/client/network/src/config.rs b/client/network/src/config.rs index c8eeb9006fbc1..b7b113dc14692 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -37,7 +37,7 @@ use core::{fmt, iter}; use futures::future; use libp2p::{ identity::{ed25519, Keypair}, - multiaddr, Multiaddr, PeerId, + multiaddr, wasm_ext, Multiaddr, PeerId, }; use prometheus_endpoint::Registry; use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; @@ -422,6 +422,7 @@ impl NetworkConfiguration { transport: TransportConfig::Normal { enable_mdns: false, allow_private_ipv4: true, + wasm_external_transport: None, }, max_parallel_downloads: 5, allow_non_globals_in_dht: false, @@ -482,6 +483,14 @@ pub enum TransportConfig { /// been passed in [`NetworkConfiguration::reserved_nodes`] or /// [`NetworkConfiguration::boot_nodes`]. allow_private_ipv4: bool, + + /// Optional external implementation of a libp2p transport. Used in WASM contexts where we + /// need some binding between the networking provided by the operating system or environment + /// and libp2p. + /// + /// This parameter exists whatever the target platform is, but it is expected to be set to + /// `Some` only when compiling for WASM. + wasm_external_transport: Option, }, /// Only allow connections within the same process. diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 945f025f09dcb..b6f162affd671 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -349,17 +349,11 @@ impl NetworkWorker { behaviour.register_notifications_protocol(protocol.clone()); } let (transport, bandwidth) = { - let config_mem = match params.network_config.transport { - TransportConfig::MemoryOnly => true, - TransportConfig::Normal { .. } => false, + let (config_mem, config_wasm) = match params.network_config.transport { + TransportConfig::MemoryOnly => (true, None), + TransportConfig::Normal { wasm_external_transport, .. } => + (false, wasm_external_transport) }; - #[cfg(target_os = "unknown")] - let config_wasm = { - use libp2p_wasm_ext::{ExtTransport, ffi}; - Some(ExtTransport::new(ffi::websocket_transport())) - }; - #[cfg(not(target_os = "unknown"))] - let config_wasm = None; transport::build_transport(local_identity, config_mem, config_wasm) }; let mut builder = SwarmBuilder::new(transport, behaviour, local_peer_id.clone()) diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index cfe7da086364a..ee60b2ccd5c4d 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -29,6 +29,7 @@ use futures::{ }; use std::pin::Pin; use sc_chain_spec::Extension; +use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; @@ -38,7 +39,8 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result { +) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { + let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, )?; @@ -46,7 +48,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok(telemetries) + Ok((telemetries, transport)) } /// Create a service configuration from a chain spec. @@ -55,6 +57,7 @@ pub fn init_logging_and_telemetry( pub async fn browser_configuration( chain_spec: GenericChainSpec, telemetry_handle: Option, + transport: ExtTransport, ) -> Result> where G: RuntimeGenesis + 'static, @@ -70,6 +73,7 @@ where ); network.boot_nodes = chain_spec.boot_nodes().to_vec(); network.transport = TransportConfig::Normal { + wasm_external_transport: Some(transport.clone()), allow_private_ipv4: true, enable_mdns: false, }; From bd687ef5a820854f423e916fc61d559c97292c1d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 13:09:39 +0100 Subject: [PATCH 148/222] Revert "Fix previous commit" This reverts commit 3c12ba7e5f4c9e3580085c441e7a79751cc806d1. --- client/telemetry/src/lib.rs | 3 ++- utils/browser/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6cdcd68bca4c3..87db96b13ccb9 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -172,11 +172,12 @@ impl Telemetries { } fn initialize_transport() -> Result { + // TODO refactor #[cfg(target_os = "unknown")] let transport = { use libp2p_wasm_ext::{ExtTransport, ffi}; ExtTransport::new(ffi::websocket_transport()) - }.map((|inner, _| worker::StreamSink::from(inner)) as fn(_, _) -> _); + }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); // The main transport is the `wasm_external_transport`, but if we're on desktop we add // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index ee60b2ccd5c4d..c62c662379c8b 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -43,6 +43,7 @@ pub fn init_logging_and_telemetry( let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, + Some(transport.clone()), )?; tracing::subscriber::set_global_default(subscriber) From f7e88faca65c319aeedd2dd327e40263f27afad9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 13:09:39 +0100 Subject: [PATCH 149/222] Revert "Remove passing around of WASM transport" This reverts commit 32b0b14ddd81974b5286c80c1fe5c787474f927e. --- Cargo.lock | 1 - client/cli/src/config.rs | 12 +++++++- client/cli/src/lib.rs | 5 ++++ client/service/src/config.rs | 3 ++ client/telemetry/Cargo.toml | 4 +-- client/telemetry/src/lib.rs | 46 +++++++++++++++++++++++-------- client/tracing/src/logging/mod.rs | 22 +++++++++++++-- utils/browser/src/lib.rs | 1 + 8 files changed, 76 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d29cffbf1bd9..9d8c9961dd2cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7339,7 +7339,6 @@ dependencies = [ "futures 0.3.8", "futures-timer 3.0.2", "libp2p", - "libp2p-wasm-ext", "log", "parking_lot 0.11.1", "pin-project 0.4.27", diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 59fae27e51fb3..a5d369999248e 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -28,7 +28,7 @@ use log::warn; use names::{Generator, Name}; use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::config::{ - BasePath, Configuration, DatabaseConfig, KeystoreConfig, NetworkConfiguration, + BasePath, Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods, TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; @@ -362,6 +362,13 @@ pub trait CliConfiguration: Sized { Ok(chain_spec.telemetry_endpoints().clone()) } + /// Get the telemetry external transport + /// + /// By default this is `None`. + fn telemetry_external_transport(&self) -> Result> { + Ok(None) + } + /// Get the default value for heap pages /// /// By default this is `None`. @@ -501,6 +508,7 @@ pub trait CliConfiguration: Sized { rpc_cors: self.rpc_cors(is_dev)?, prometheus_config: self.prometheus_config(DCV::prometheus_listen_port())?, telemetry_endpoints: self.telemetry_endpoints(&chain_spec)?, + telemetry_external_transport: self.telemetry_external_transport()?, default_heap_pages: self.default_heap_pages()?, offchain_worker: self.offchain_worker(&role)?, force_authoring: self.force_authoring()?, @@ -546,6 +554,7 @@ pub trait CliConfiguration: Sized { let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; let disable_log_reloading = self.is_log_filter_reloading_disabled()?; + let telemetry_external_transport = self.telemetry_external_transport()?; sp_panic_handler::set(&C::support_url(), &C::impl_version()); @@ -553,6 +562,7 @@ pub trait CliConfiguration: Sized { &logger_pattern, tracing_receiver, tracing_targets.as_ref().map(|x| x.as_str()), + telemetry_external_transport, disable_log_reloading, )?; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 8ee58a051c44f..ebbbf455f075c 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -237,12 +237,14 @@ pub fn init_logging_and_telemetry( pattern: &str, tracing_receiver: sc_tracing::TracingReceiver, profiling_targets: Option<&str>, + telemetry_external_transport: Option, disable_log_reloading: bool, ) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { if disable_log_reloading { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( pattern, + telemetry_external_transport, tracing_receiver, profiling_targets, )?; @@ -257,6 +259,7 @@ pub fn init_logging_and_telemetry( } else { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( pattern, + telemetry_external_transport, tracing_receiver, profiling_targets, )?; @@ -273,6 +276,7 @@ pub fn init_logging_and_telemetry( if disable_log_reloading { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( pattern, + telemetry_external_transport, )?; if let Err(e) = tracing::subscriber::set_global_default(subscriber) { @@ -285,6 +289,7 @@ pub fn init_logging_and_telemetry( } else { let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_log_reloading( pattern, + telemetry_external_transport, )?; if let Err(e) = tracing::subscriber::set_global_default(subscriber) { diff --git a/client/service/src/config.rs b/client/service/src/config.rs index fa7bfb768b892..e6f6d3a16b322 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -84,6 +84,9 @@ pub struct Configuration { pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. pub telemetry_endpoints: Option, + /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry + /// endpoint, this transport will be tried in priority before all others. + pub telemetry_external_transport: Option, /// Telemetry handle. pub telemetry_handle: Option, /// The default number of 64KB pages to allocate for Wasm execution diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 32af4412c0a43..fbc0e4c54d399 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + [dependencies] parking_lot = "0.11.0" futures = "0.3.4" @@ -30,6 +31,3 @@ tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } - -[target.'cfg(target_os = "unknown")'.dependencies] -libp2p-wasm-ext = { version = "0.25", features = ["websocket"] } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 87db96b13ccb9..d654e68b4fed1 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -41,7 +41,8 @@ use futures::{channel::mpsc, prelude::*}; use libp2p::{ - core::transport::timeout::TransportTimeout, Multiaddr, Transport, + core::transport::{OptionalTransport, timeout::TransportTimeout}, + wasm_ext, Multiaddr, Transport, }; use log::{error, warn}; use serde::{Deserialize, Deserializer, Serialize}; @@ -69,7 +70,7 @@ mod dispatcher; pub use layer::*; use node::*; -use worker::CONNECT_TIMEOUT; // TODO mod +use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod use dispatcher::*; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the @@ -167,23 +168,46 @@ impl Telemetries { sender, init_receiver, init_sender, - transport: Self::initialize_transport()?, + transport: Self::initialize_transport(None)?, }) } - fn initialize_transport() -> Result { - // TODO refactor - #[cfg(target_os = "unknown")] - let transport = { - use libp2p_wasm_ext::{ExtTransport, ffi}; - ExtTransport::new(ffi::websocket_transport()) + /// Create a [`Telemetries`] object using an `ExtTransport`. + /// + /// This is used in WASM contexts where we need some binding between the networking provided by + /// the operating system or environment and libp2p. + /// + /// This constructor is expected to be used only when compiling for WASM. + /// + /// > **Important**: Each individual call to `write` corresponds to one message. There is no + /// > internal buffering going on. In the context of WebSockets, each `write` + /// > must be one individual WebSockets frame. + pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Result { + let (sender, receiver) = mpsc::channel(16); + let (init_sender, init_receiver) = mpsc::unbounded(); + + Ok(Self { + receiver, + sender, + init_receiver, + init_sender, + transport: Self::initialize_transport(Some(wasm_external_transport))?, + }) + } + + fn initialize_transport( + wasm_external_transport: Option, + ) -> Result { + let transport = match wasm_external_transport.clone() { + Some(t) => OptionalTransport::some(t), + None => OptionalTransport::none() }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); // The main transport is the `wasm_external_transport`, but if we're on desktop we add // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass // an external transport on desktop and the fallback is used all the time. #[cfg(not(target_os = "unknown"))] - let transport = { + let transport = transport.or_transport({ let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; libp2p::websocket::framed::WsConfig::new(inner) .and_then(|connec, _| { @@ -196,7 +220,7 @@ impl Telemetries { .map_ok(|data| data.into_bytes()); future::ready(Ok::<_, io::Error>(connec)) }) - }; + }); Ok(TransportTimeout::new( transport.map(|out, _| { diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index b71be169692aa..1a6ee051880df 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -49,6 +49,7 @@ macro_rules! disable_log_reloading { /// TODO pub fn get_default_subscriber_and_telemetries( pattern: &str, + telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -58,14 +59,18 @@ pub fn get_default_subscriber_and_telemetries( > { get_default_subscriber_and_telemetries_internal( parse_directives(pattern), + telemetry_external_transport, |builder| builder, ) } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] pub fn get_default_subscriber_and_telemetries_with_log_reloading( pattern: &str, + telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, @@ -75,14 +80,18 @@ pub fn get_default_subscriber_and_telemetries_with_log_reloading( > { get_default_subscriber_and_telemetries_internal( parse_directives(pattern), + telemetry_external_transport, |builder| disable_log_reloading!(builder), ) } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with /// profiling enabled. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. pub fn get_default_subscriber_and_telemetries_with_profiling( pattern: &str, + telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< @@ -96,6 +105,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), + telemetry_external_transport, |builder| builder, )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); @@ -105,9 +115,12 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( /// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with /// profiling enabled. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( pattern: &str, + telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< @@ -121,6 +134,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), + telemetry_external_transport, |builder| disable_log_reloading!(builder), )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); @@ -132,6 +146,7 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( // `get_default_subscriber_and_telemetries_with_profiling`. fn get_default_subscriber_and_telemetries_internal( extra_directives: impl IntoIterator, + telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< ( @@ -211,8 +226,11 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetries = sc_telemetry::Telemetries::new() - .map_err(|err| format!("Could not initialize telemetry: {}", err))?; + let telemetries = if let Some(telemetry_external_transport) = telemetry_external_transport { + sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) + } else { + sc_telemetry::Telemetries::new() + }.map_err(|err| format!("Could not initialize telemetry: {}", err))?; let sender = telemetries.sender(); let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); let event_format = EventFormat { diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index c62c662379c8b..9c8d80cd61585 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -87,6 +87,7 @@ where wasm_bindgen_futures::spawn_local(fut); async {} }).into(), + telemetry_external_transport: Some(transport), telemetry_handle, role: Role::Light, database: { From 5140912da054c801534c76b2417baa57a07cccce Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 13:11:33 +0100 Subject: [PATCH 150/222] Re-create transport instead of passing it around --- bin/node/cli/src/browser.rs | 4 ++-- utils/browser/src/lib.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 9d579d511188e..ce928cd932015 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,14 +34,14 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let (telemetries, transport) = init_logging_and_telemetry(&log_directives)?; + let telemetries = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, Some(telemetries.handle()), transport).await?; + let mut config = browser_configuration(chain_spec, Some(telemetries.handle())).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 9c8d80cd61585..249dfa4ac3016 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -39,7 +39,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result<(sc_telemetry::Telemetries, ExtTransport), String> { +) -> Result { let transport = ExtTransport::new(ffi::websocket_transport()); let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( pattern, @@ -49,7 +49,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok((telemetries, transport)) + Ok(telemetries) } /// Create a service configuration from a chain spec. @@ -58,13 +58,13 @@ pub fn init_logging_and_telemetry( pub async fn browser_configuration( chain_spec: GenericChainSpec, telemetry_handle: Option, - transport: ExtTransport, ) -> Result> where G: RuntimeGenesis + 'static, E: Extension + 'static + Send + Sync, { let name = chain_spec.name().to_string(); + let transport = ExtTransport::new(ffi::websocket_transport()); let mut network = NetworkConfiguration::new( format!("{} (Browser)", name), From 0c41445f0e22be5207d637893a8af4d0d75fcab7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 15:40:27 +0100 Subject: [PATCH 151/222] WIP --- client/telemetry/src/layer.rs | 2 +- client/telemetry/src/node.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 1a55aba9f6667..9e5f47c185b2b 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -121,7 +121,7 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { - if value.chars().next() == Some('{') { + if value.chars().next() != Some('{') { eprintln!( "Invalid value for JSON in telemetry logging: \ the attribute's value `json` doesn't start with the character `{{`", diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 2f5ccd8e74fd0..314bc4da2fe10 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -28,7 +28,7 @@ use crate::TelemetryConnectionSinks; /// Maximum number of pending telemetry messages. /// Handler for a single telemetry node. -/// TODO: explain 2 properties of this Sink +/// TODO: explain 3 properties of this Sink (infailible, connection message, discard messages) #[derive(Debug)] pub(crate) struct Node { /// Address of the node. @@ -124,7 +124,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, type Error = Infallible; fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - // TODO discard messages let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); self.socket = loop { match socket { @@ -205,7 +204,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } }; - Poll::Pending + Poll::Ready(Ok(())) } fn start_send(mut self: Pin<&mut Self>, item: String) -> Result<(), Self::Error> { @@ -214,14 +213,11 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, let _ = conn.sink.start_send_unpin(item.into()).expect("boo"); }, socket => { - log::error!( + log::trace!( target: "telemetry", - "Trying to send something but the connection is not ready ({:?}). - This is a bug. Message sent: {}", - socket, + "Message has been discarded: {}", item, ); - todo!("should never happen"); }, } Ok(()) From 12740fe6675e17b3f042198370a33a0ae8ec1c6f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 16:50:24 +0100 Subject: [PATCH 152/222] CLEANUP --- client/telemetry/src/layer.rs | 21 ----------------- client/telemetry/src/node.rs | 43 +++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 9e5f47c185b2b..7d79d0999974a 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -18,9 +18,7 @@ use futures::channel::mpsc; use parking_lot::Mutex; -use std::collections::HashMap; use std::convert::TryInto; -use std::sync::Arc; use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; @@ -134,22 +132,3 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { } } } - -/// A collection of `futures::channel::mpsc::Sender` with their associated span's ID. -/// -/// This is used by [`TelemetryLayer`] to route the log events to the correct channel based on the -/// span's ID. -// TODO remove -#[derive(Default, Debug, Clone)] -pub struct Senders( - Arc>>>>, -); - -impl Senders { - /// Insert a channel `Sender` to the collection using an `Id` for its key. - pub fn insert(&self, id: Id, sender: mpsc::Sender<(u8, String)>) { - self.0 - .lock() - .insert(id, std::panic::AssertUnwindSafe(sender)); - } -} diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index c02876b4beb3a..0ea4555701ad5 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -26,9 +26,17 @@ use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; use crate::TelemetryConnectionSinks; -/// Maximum number of pending telemetry messages. /// Handler for a single telemetry node. -/// TODO: explain 3 properties of this Sink (infailible, connection message, discard messages) +/// +/// This is a wrapper `Sink` around a network `Sink` with 3 particularities: +/// - It is infallible: if the connection stops, it will reconnect automatically when the server +/// becomes available again. +/// - It holds a list of "connection messages" which are sent automatically when the connection is +/// (re-)established. This is used for the "system.connected" message that needs to be send for +/// every substrate node that connects. +/// - It doesn't stay in pending while waiting for connection. Instead, it moves data into the +/// void if the connection could not be established. This is important for the `Dispatcher` +/// `Sink` which we don't want to block if one connection is broken. #[derive(Debug)] pub(crate) struct Node { /// Address of the node. @@ -37,7 +45,9 @@ pub(crate) struct Node { socket: NodeSocket, /// Transport used to establish new connections. transport: TTrans, + /// Messages that are sent when the connection (re-)establishes. connection_messages: Vec, + /// Notifier for when the connection (re-)establishes. connection_sinks: Vec, } @@ -111,7 +121,6 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, } } -// TODO not pub pub(crate) enum Infallible {} impl Sink for Node @@ -163,13 +172,33 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, connection_sink.fire(); } - let mut buf = Vec::with_capacity(self.connection_messages.len()); - for mut json in self.connection_messages.iter().cloned() { - let obj = json.as_object_mut().expect("todo"); + fn generate_message(mut json: serde_json::Value) -> Result, String> { + let obj = json.as_object_mut() + .ok_or_else(|| { + "Invalid JSON message: it must be an object".to_owned() + })?; obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); - buf.push(serde_json::to_vec(obj).expect("todo")); + serde_json::to_vec(obj) + .map_err(|err| format!("Could not serialize JSON message: {}", err)) } + let buf = self.connection_messages + .iter() + .cloned() + .filter_map(|json| match generate_message(json) { + Ok(message) => Some(message), + Err(err) => { + log::error!( + target: "telemetry", + "An error occurred while generating new connection \ + messages: {}", + err, + ); + None + }, + }) + .collect(); + socket = NodeSocket::Connected(NodeSocketConnected { sink, buf, From a04451dd34cdf722c1ddc30d143ba7ca1dd8424e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 16 Dec 2020 17:01:23 +0100 Subject: [PATCH 153/222] Renamed Telemetries to TelemetryWorker --- bin/node/cli/src/browser.rs | 6 ++-- client/cli/src/config.rs | 6 ++-- client/cli/src/lib.rs | 22 ++++++------ client/cli/src/runner.rs | 16 ++++----- client/telemetry/src/lib.rs | 12 +++---- client/telemetry/src/node.rs | 2 -- client/tracing/src/logging/mod.rs | 56 +++++++++++++++---------------- utils/browser/src/lib.rs | 10 +++--- 8 files changed, 64 insertions(+), 66 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index ce928cd932015..bd41287d50817 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -34,14 +34,14 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { set_console_error_panic_hook(); - let telemetries = init_logging_and_telemetry(&log_directives)?; + let telemetry_worker = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) .map_err(|e| format!("{:?}", e))?, None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, Some(telemetries.handle())).await?; + let mut config = browser_configuration(chain_spec, Some(telemetry_worker.handle())).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); @@ -57,7 +57,7 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu .map(|(components, rpc_handlers, _, _, _, _)| (components, rpc_handlers)) .map_err(|e| format!("{:?}", e))?; - task_manager.spawn_handle().spawn("telemetry", telemetries.run()); + task_manager.spawn_handle().spawn("telemetry", telemetry_worker.run()); Ok(browser_utils::start_client(task_manager, rpc_handlers)) } diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 387bb7073421f..ab58e40cf7cd9 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -551,7 +551,7 @@ pub trait CliConfiguration: Sized { /// 1. Sets the panic handler /// 2. Initializes the logger /// 3. Raises the FD limit - fn init(&self) -> Result { + fn init(&self) -> Result { let logger_pattern = self.log_filters()?; let tracing_receiver = self.tracing_receiver()?; let tracing_targets = self.tracing_targets()?; @@ -560,7 +560,7 @@ pub trait CliConfiguration: Sized { sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let telemetries = init_logging_and_telemetry( + let telemetry_worker = init_logging_and_telemetry( &logger_pattern, tracing_receiver, tracing_targets.as_ref().map(|x| x.as_str()), @@ -578,7 +578,7 @@ pub trait CliConfiguration: Sized { } } - Ok(telemetries) + Ok(telemetry_worker) } } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index ebbbf455f075c..862743c4afac1 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -222,8 +222,8 @@ pub trait SubstrateCli: Sized { /// Create a runner for the command provided in argument. This will create a Configuration and /// a tokio runtime fn create_runner(&self, command: &T) -> error::Result> { - let telemetries = command.init::()?; - Runner::new(self, command, telemetries) + let telemetry_worker = command.init::()?; + Runner::new(self, command, telemetry_worker) } /// Native runtime version. @@ -239,10 +239,10 @@ pub fn init_logging_and_telemetry( profiling_targets: Option<&str>, telemetry_external_transport: Option, disable_log_reloading: bool, -) -> std::result::Result { +) -> std::result::Result { Ok(if let Some(profiling_targets) = profiling_targets { if disable_log_reloading { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling( + let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_profiling( pattern, telemetry_external_transport, tracing_receiver, @@ -255,9 +255,9 @@ pub fn init_logging_and_telemetry( )) } - telemetries + telemetry_worker } else { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( + let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( pattern, telemetry_external_transport, tracing_receiver, @@ -270,11 +270,11 @@ pub fn init_logging_and_telemetry( )) } - telemetries + telemetry_worker } } else { if disable_log_reloading { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker( pattern, telemetry_external_transport, )?; @@ -285,9 +285,9 @@ pub fn init_logging_and_telemetry( )) } - telemetries + telemetry_worker } else { - let (subscriber, telemetries) = logging::get_default_subscriber_and_telemetries_with_log_reloading( + let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_log_reloading( pattern, telemetry_external_transport, )?; @@ -298,7 +298,7 @@ pub fn init_logging_and_telemetry( )) } - telemetries + telemetry_worker } }) } diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 0e8360e2c2877..7a77f8c4907f3 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -113,7 +113,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetries: Arc, + telemetry_worker: Arc, phantom: PhantomData, } @@ -122,7 +122,7 @@ impl Runner { pub fn new( cli: &C, command: &T, - telemetries: sc_telemetry::Telemetries, + telemetry_worker: sc_telemetry::TelemetryWorker, ) -> Result> { let tokio_runtime = build_runtime()?; let runtime_handle = tokio_runtime.handle().clone(); @@ -135,16 +135,16 @@ impl Runner { .map(drop), } }; - let telemetries = Arc::new(telemetries); + let telemetry_worker = Arc::new(telemetry_worker); Ok(Runner { config: command.create_configuration( cli, task_executor.into(), - Some(telemetries.handle()), + Some(telemetry_worker.handle()), )?, tokio_runtime, - telemetries, + telemetry_worker, phantom: PhantomData, }) } @@ -190,12 +190,12 @@ impl Runner { ) -> Result<()> { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; - let telemetries = Arc::try_unwrap(self.telemetries) + let telemetry_worker = Arc::try_unwrap(self.telemetry_worker) .map_err(|_| String::from( - "Could not initialize telemetries! \ + "Could not initialize telemetry_worker! \ Maybe some node Configuration are pending?" ))?; - task_manager.spawn_handle().spawn("telemetries", telemetries.run()); + task_manager.spawn_handle().spawn("telemetry_worker", telemetry_worker.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); res.map_err(|e| e.to_string().into()) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d654e68b4fed1..00d59986ec5cc 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -29,9 +29,9 @@ //! telemetries. If multiple `Telemetry` objects are created, the latest one (higher up in the //! stack) will be used. If no `Telemetry` object can be found, nothing is reported. //! -//! To re-use connections to the same server you need to use the `Telemetries` object to create -//! multiple `Telemetry`. `Telemetries` also manages a collection of channel `Sender` for you (see -//! `Senders`). `Telemetries` should be used unless you need finer control. +//! To re-use connections to the same server you need to use the `TelemetryWorker` object to create +//! multiple `Telemetry`. `TelemetryWorker` also manages a collection of channel `Sender` for you (see +//! `Senders`). `TelemetryWorker` should be used unless you need finer control. //! //! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a //! background thread/task) in order for the telemetry to properly function. @@ -149,7 +149,7 @@ pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, Teleme /// /// [`Telemetry`] created through this object re-use connections if possible. #[derive(Debug)] -pub struct Telemetries { +pub struct TelemetryWorker { receiver: mpsc::Receiver<(Id, u8, String)>, sender: mpsc::Sender<(Id, u8, String)>, init_receiver: mpsc::UnboundedReceiver, @@ -157,7 +157,7 @@ pub struct Telemetries { transport: crate::worker::WsTrans, } -impl Telemetries { +impl TelemetryWorker { /// TODO pub fn new() -> Result { let (sender, receiver) = mpsc::channel(16); @@ -172,7 +172,7 @@ impl Telemetries { }) } - /// Create a [`Telemetries`] object using an `ExtTransport`. + /// Create a [`TelemetryWorker`] object using an `ExtTransport`. /// /// This is used in WASM contexts where we need some binding between the networking provided by /// the operating system or environment and libp2p. diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 0ea4555701ad5..d443c88911018 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -16,8 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Contains the `Node` struct, which handles communications with a single telemetry endpoint. - use futures::prelude::*; use futures_timer::Delay; use libp2p::Multiaddr; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 1a6ee051880df..a2a1333ed9633 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -47,49 +47,49 @@ macro_rules! disable_log_reloading { } /// TODO -pub fn get_default_subscriber_and_telemetries( +pub fn get_default_subscriber_and_telemetry_worker( pattern: &str, telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::Telemetries, + sc_telemetry::TelemetryWorker, ), String, > { - get_default_subscriber_and_telemetries_internal( + get_default_subscriber_and_telemetry_worker_internal( parse_directives(pattern), telemetry_external_transport, |builder| builder, ) } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects. +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects. /// /// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] -pub fn get_default_subscriber_and_telemetries_with_log_reloading( +pub fn get_default_subscriber_and_telemetry_worker_with_log_reloading( pattern: &str, telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::Telemetries, + sc_telemetry::TelemetryWorker, ), String, > { - get_default_subscriber_and_telemetries_internal( + get_default_subscriber_and_telemetry_worker_internal( parse_directives(pattern), telemetry_external_transport, |builder| disable_log_reloading!(builder), ) } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with /// profiling enabled. /// /// When running in a browser, the `telemetry_external_transport` should be provided. -pub fn get_default_subscriber_and_telemetries_with_profiling( +pub fn get_default_subscriber_and_telemetry_worker_with_profiling( pattern: &str, telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, @@ -97,11 +97,11 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::Telemetries, + sc_telemetry::TelemetryWorker, ), String, > { - let (subscriber, telemetries) = get_default_subscriber_and_telemetries_internal( + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), @@ -110,15 +110,15 @@ pub fn get_default_subscriber_and_telemetries_with_profiling( )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); - Ok((subscriber.with(profiling), telemetries)) + Ok((subscriber.with(profiling), telemetry_worker)) } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `Telemetries` objects with +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with /// profiling enabled. /// /// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] -pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( +pub fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( pattern: &str, telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, @@ -126,11 +126,11 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::Telemetries, + sc_telemetry::TelemetryWorker, ), String, > { - let (subscriber, telemetries) = get_default_subscriber_and_telemetries_internal( + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( parse_directives(pattern) .into_iter() .chain(parse_directives(profiling_targets).into_iter()), @@ -139,19 +139,19 @@ pub fn get_default_subscriber_and_telemetries_with_profiling_and_log_reloading( )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); - Ok((subscriber.with(profiling), telemetries)) + Ok((subscriber.with(profiling), telemetry_worker)) } -// Common implementation for `get_default_subscriber_and_telemetries` and -// `get_default_subscriber_and_telemetries_with_profiling`. -fn get_default_subscriber_and_telemetries_internal( +// Common implementation for `get_default_subscriber_and_telemetry_worker` and +// `get_default_subscriber_and_telemetry_worker_with_profiling`. +fn get_default_subscriber_and_telemetry_worker_internal( extra_directives: impl IntoIterator, telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::Telemetries, + sc_telemetry::TelemetryWorker, ), String, > @@ -226,12 +226,12 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetries = if let Some(telemetry_external_transport) = telemetry_external_transport { - sc_telemetry::Telemetries::with_wasm_external_transport(telemetry_external_transport) + let telemetry_worker = if let Some(telemetry_external_transport) = telemetry_external_transport { + sc_telemetry::TelemetryWorker::with_wasm_external_transport(telemetry_external_transport) } else { - sc_telemetry::Telemetries::new() + sc_telemetry::TelemetryWorker::new() }.map_err(|err| format!("Could not initialize telemetry: {}", err))?; - let sender = telemetries.sender(); + let sender = telemetry_worker.sender(); let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); let event_format = EventFormat { timer, @@ -266,7 +266,7 @@ where #[cfg(target_os = "unknown")] let subscriber = subscriber.with(ConsoleLogLayer::new(event_format)); - Ok((subscriber, telemetries)) + Ok((subscriber, telemetry_worker)) } // Transform a string of comma separated logging directive into a `Vec`. @@ -285,8 +285,8 @@ mod tests { const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; fn init_logger(pattern: &str) -> tracing::subscriber::DefaultGuard { - let (subscriber, _telemetries) = - get_default_subscriber_and_telemetries(pattern, None, false).unwrap(); + let (subscriber, _telemetry_worker) = + get_default_subscriber_and_telemetry_worker(pattern, None, false).unwrap(); tracing::subscriber::set_default(subscriber) } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 1974ae00e6f3b..6909704860d54 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -33,15 +33,15 @@ use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; -/// Initialize the logger and return a `Telemetries` and a wasm `ExtTransport`. +/// Initialize the logger and return a `TelemetryWorker` and a wasm `ExtTransport`. /// -/// The `Telemetries` object can be use to create `Telemetry` objects and the wasm `ExtTransport` +/// The `TelemetryWorker` object can be use to create `Telemetry` objects and the wasm `ExtTransport` /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result { +) -> Result { let transport = ExtTransport::new(ffi::websocket_transport()); - let (subscriber, telemetries) = sc_tracing::logging::get_default_subscriber_and_telemetries( + let (subscriber, telemetry_worker) = sc_tracing::logging::get_default_subscriber_and_telemetry_worker( pattern, Some(transport.clone()), )?; @@ -49,7 +49,7 @@ pub fn init_logging_and_telemetry( tracing::subscriber::set_global_default(subscriber) .map_err(|e| format!("could not set global default subscriber: {}", e))?; - Ok(telemetries) + Ok(telemetry_worker) } /// Create a service configuration from a chain spec. From 7b3cdb377e53cd28665dbd34e73fc9b603964edf Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 10:22:30 +0100 Subject: [PATCH 154/222] doc --- client/telemetry/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 00d59986ec5cc..ae54e65470899 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -158,7 +158,7 @@ pub struct TelemetryWorker { } impl TelemetryWorker { - /// TODO + /// Create a new [`TelemetryWorker`] instance. pub fn new() -> Result { let (sender, receiver) = mpsc::channel(16); let (init_sender, init_receiver) = mpsc::unbounded(); @@ -172,7 +172,7 @@ impl TelemetryWorker { }) } - /// Create a [`TelemetryWorker`] object using an `ExtTransport`. + /// Create a [`TelemetryWorker`] instance using an `ExtTransport`. /// /// This is used in WASM contexts where we need some binding between the networking provided by /// the operating system or environment and libp2p. @@ -233,7 +233,9 @@ impl TelemetryWorker { ).boxed()) } - /// TODO + /// Get a handle to this [`TelemetryWorker`]. + /// + /// This is used when you want to register a new telemetry for a Substrate node. pub fn handle(&self) -> TelemetryHandle { TelemetryHandle(self.init_sender.clone()) } From 7ef81dccc93d1a58b5984644170dd6048b4e6549 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 10:23:35 +0100 Subject: [PATCH 155/222] Renamed TelemetryConnectionSinks to TelemetryConnectionNotifier --- bin/node-template/node/src/service.rs | 4 ++-- bin/node/cli/src/service.rs | 12 ++++++------ client/service/src/builder.rs | 10 +++++----- client/telemetry/src/lib.rs | 19 +++++++++---------- client/telemetry/src/node.rs | 10 +++++----- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index f764549cd5ea9..99dba64d65545 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -160,7 +160,7 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - let (_rpc_handlers, telemetry_connection_sinks) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let (_rpc_handlers, telemetry_telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), @@ -234,7 +234,7 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: telemetry_connection_sinks.map(|x| x.on_connect_stream()), + telemetry_on_connect: telemetry_telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index af414bc4a9f49..afb7e76b7c4e2 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -34,7 +34,7 @@ use sp_runtime::traits::Block as BlockT; use futures::prelude::*; use sc_client_api::{ExecutorProvider, RemoteBackend}; use node_executor::Executor; -use sc_telemetry::TelemetryConnectionSinks; +use sc_telemetry::TelemetryConnectionNotifier; type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; @@ -218,7 +218,7 @@ pub fn new_full_base( let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let (_rpc_handlers, telemetry_connection_sinks) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let (_rpc_handlers, telemetry_telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { config, backend: backend.clone(), client: client.clone(), @@ -316,7 +316,7 @@ pub fn new_full_base( config, link: grandpa_link, network: network.clone(), - telemetry_on_connect: telemetry_connection_sinks.map(|x| x.on_connect_stream()), + telemetry_on_connect: telemetry_telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state, @@ -350,7 +350,7 @@ pub fn new_full(config: Configuration) } pub fn new_light_base(mut config: Configuration) -> Result<( - TaskManager, RpcHandlers, TelemetryConnectionSinks, Arc, + TaskManager, RpcHandlers, TelemetryConnectionNotifier, Arc, Arc::Hash>>, Arc>> ), ServiceError> { @@ -423,7 +423,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<( let rpc_extensions = node_rpc::create_light(light_deps); - let (rpc_handlers, telemetry_connection_sinks) = + let (rpc_handlers, telemetry_telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { on_demand: Some(on_demand), remote_blockchain: Some(backend.remote_blockchain()), @@ -436,7 +436,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<( task_manager: &mut task_manager, })?; - Ok((task_manager, rpc_handlers, telemetry_connection_sinks.unwrap_or_default(), client, network, transaction_pool)) + Ok((task_manager, rpc_handlers, telemetry_telemetry_connection_notifier.unwrap_or_default(), client, network, transaction_pool)) } /// Builds a new service for a light client. diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 86ca09c2feedc..d96340a6d442f 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -50,7 +50,7 @@ use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{telemetry, TelemetryConnectionSinks, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, TelemetryConnectionNotifier, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; @@ -526,7 +526,7 @@ pub fn build_offchain_workers( /// Spawn the tasks that are required to run a node. pub fn spawn_tasks( params: SpawnTasksParams, -) -> Result<(RpcHandlers, Option), Error> +) -> Result<(RpcHandlers, Option), Error> where TCl: ProvideRuntimeApi + HeaderMetadata + Chain + BlockBackend + BlockIdTo + ProofProvider + @@ -569,7 +569,7 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - let telemetry_connection_sinks = init_telemetry( + let telemetry_telemetry_connection_notifier = init_telemetry( &mut config, network.clone(), client.clone(), @@ -649,7 +649,7 @@ pub fn spawn_tasks( task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone())); - Ok((rpc_handlers, telemetry_connection_sinks)) + Ok((rpc_handlers, telemetry_telemetry_connection_notifier)) } async fn transaction_notifications( @@ -678,7 +678,7 @@ fn init_telemetry>( config: &mut Configuration, network: Arc::Hash>>, client: Arc, -) -> Option { +) -> Option { let telemetry_handle = if let Some(handle) = config.telemetry_handle.as_mut() { handle } else { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ae54e65470899..0c091d16f4432 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -143,7 +143,7 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionSinks); +pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionNotifier); /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// @@ -257,7 +257,7 @@ impl TelemetryWorker { let mut node_map: HashMap> = HashMap::new(); let mut connection_messages: HashMap> = HashMap::new(); - let mut connection_sinks: HashMap> = HashMap::new(); + let mut telemetry_connection_notifier: HashMap> = HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes @@ -276,7 +276,7 @@ impl TelemetryWorker { obj.insert("id".into(), id.into_u64().into()); connection_messages.entry(addr.clone()).or_insert_with(Vec::new) .push(json); - connection_sinks.entry(addr.clone()).or_insert_with(Vec::new) + telemetry_connection_notifier.entry(addr.clone()).or_insert_with(Vec::new) .push(connection_sink.clone()); } } @@ -287,9 +287,9 @@ impl TelemetryWorker { .map(|addr| { let connection_messages = connection_messages.remove(addr) .expect("there is a node for every connection message; qed"); - let connection_sinks = connection_sinks.remove(addr) + let telemetry_connection_notifier = telemetry_connection_notifier.remove(addr) .expect("there is a node for every connection sink; qed"); - let node = Node::new(transport.clone(), addr.clone(), connection_messages, connection_sinks); + let node = Node::new(transport.clone(), addr.clone(), connection_messages, telemetry_connection_notifier); (addr.clone(), node) }) .collect(); @@ -359,8 +359,8 @@ impl TelemetryHandle { &mut self, endpoints: TelemetryEndpoints, connection_message: serde_json::Value, - ) -> TelemetryConnectionSinks { - let connection_sink = TelemetryConnectionSinks::default(); + ) -> TelemetryConnectionNotifier { + let connection_sink = TelemetryConnectionNotifier::default(); let span = tracing::info_span!(TELEMETRY_LOG_SPAN); let id = span.id().expect("the span is enabled; qed"); // TODO: this error happen if the log is disabled by the command line @@ -382,12 +382,11 @@ impl TelemetryHandle { } } -// TODO maybe rename because it's confusing /// Sinks to propagate telemetry connection established events. #[derive(Default, Clone, Debug)] -pub struct TelemetryConnectionSinks(Arc>>>); +pub struct TelemetryConnectionNotifier(Arc>>>); -impl TelemetryConnectionSinks { +impl TelemetryConnectionNotifier { /// Get event stream for telemetry connection established events. pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { let (sink, stream) = tracing_unbounded("mpsc_telemetry_on_connect"); diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index d443c88911018..0858ba80659f9 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -22,7 +22,7 @@ use libp2p::Multiaddr; use libp2p::core::transport::Transport; use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; -use crate::TelemetryConnectionSinks; +use crate::TelemetryConnectionNotifier; /// Handler for a single telemetry node. /// @@ -46,7 +46,7 @@ pub(crate) struct Node { /// Messages that are sent when the connection (re-)establishes. connection_messages: Vec, /// Notifier for when the connection (re-)establishes. - connection_sinks: Vec, + telemetry_connection_notifier: Vec, } enum NodeSocket { @@ -83,14 +83,14 @@ impl Node { transport: TTrans, addr: Multiaddr, connection_messages: Vec, - connection_sinks: Vec, + telemetry_connection_notifier: Vec, ) -> Self { Node { addr, socket: NodeSocket::ReconnectNow, transport, connection_messages, - connection_sinks, + telemetry_connection_notifier, } } } @@ -166,7 +166,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Ready(Ok(sink)) => { log::debug!(target: "telemetry", "✅ Connected to {}", self.addr); - for connection_sink in self.connection_sinks.iter() { + for connection_sink in self.telemetry_connection_notifier.iter() { connection_sink.fire(); } From dfa0dab165903147f51eaedeca4dcbeecc939cf2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 11:10:09 +0100 Subject: [PATCH 156/222] Refactor initialization and doc --- client/telemetry/src/layer.rs | 9 +++- client/telemetry/src/lib.rs | 68 +++++++++++++++---------------- client/tracing/src/logging/mod.rs | 8 +--- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 7d79d0999974a..d6b896509ef57 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -21,6 +21,9 @@ use parking_lot::Mutex; use std::convert::TryInto; use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; +use libp2p::wasm_ext::ExtTransport; +use crate::TelemetryWorker; +use std::io; /// Span name used to report the telemetry. pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; @@ -31,8 +34,10 @@ pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. - pub fn new(sender: mpsc::Sender<(Id, u8, String)>) -> Self { - Self(Mutex::new(sender)) + pub fn new(telemetry_external_transport: Option) -> Result<(Self, TelemetryWorker), io::Error> { + let worker = TelemetryWorker::new(telemetry_external_transport)?; + let sender = worker.sender(); + Ok((Self(Mutex::new(sender)), worker)) } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 0c091d16f4432..66abd344a1a5e 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -158,20 +158,6 @@ pub struct TelemetryWorker { } impl TelemetryWorker { - /// Create a new [`TelemetryWorker`] instance. - pub fn new() -> Result { - let (sender, receiver) = mpsc::channel(16); - let (init_sender, init_receiver) = mpsc::unbounded(); - - Ok(Self { - receiver, - sender, - init_receiver, - init_sender, - transport: Self::initialize_transport(None)?, - }) - } - /// Create a [`TelemetryWorker`] instance using an `ExtTransport`. /// /// This is used in WASM contexts where we need some binding between the networking provided by @@ -182,7 +168,7 @@ impl TelemetryWorker { /// > **Important**: Each individual call to `write` corresponds to one message. There is no /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. - pub fn with_wasm_external_transport(wasm_external_transport: wasm_ext::ExtTransport) -> Result { + pub fn new(wasm_external_transport: Option) -> Result { let (sender, receiver) = mpsc::channel(16); let (init_sender, init_receiver) = mpsc::unbounded(); @@ -191,7 +177,7 @@ impl TelemetryWorker { sender, init_receiver, init_sender, - transport: Self::initialize_transport(Some(wasm_external_transport))?, + transport: Self::initialize_transport(wasm_external_transport)?, }) } @@ -240,12 +226,12 @@ impl TelemetryWorker { TelemetryHandle(self.init_sender.clone()) } - /// TODO - pub fn sender(&self) -> mpsc::Sender<(Id, u8, String)> { + /// Get a clone of the channel's `Sender` used to send telemetry event. + pub(crate) fn sender(&self) -> mpsc::Sender<(Id, u8, String)> { self.sender.clone() } - /// TODO + /// Run the telemetry worker. pub async fn run(self) { let Self { receiver, @@ -346,43 +332,55 @@ impl TelemetryWorker { } } -/// TODO +/// Handle to the [`TelemetryWorker`] thats allows initializing the telemetry for a Substrate node. #[derive(Clone, Debug)] pub struct TelemetryHandle(mpsc::UnboundedSender); impl TelemetryHandle { - /// Create a new [`Telemetry`] for the endpoints provided in argument. + /// Initialize the telemetry with the endpoints provided in argument for the current substrate + /// node. + /// + /// This method must be called during the substrate node initialization. /// /// The `endpoints` argument is a collection of telemetry WebSocket servers with a corresponding - /// verbosity level. TODO doc + /// verbosity level. + /// + /// The `connection_message` argument is a JSON object that is sent every time the connection + /// (re-)establishes. pub fn start_telemetry( &mut self, endpoints: TelemetryEndpoints, connection_message: serde_json::Value, ) -> TelemetryConnectionNotifier { let connection_sink = TelemetryConnectionNotifier::default(); - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let id = span.id().expect("the span is enabled; qed"); // TODO: this error happen if the log is disabled by the command line - { - let id = id.clone(); - // TODO where to drop span? - tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)); - } - if let Err(err) = self.0.unbounded_send((id, endpoints, connection_message, connection_sink.clone())) { - error!( + match span.id() { + Some(id) => { + match self.0.unbounded_send( + (id.clone(), endpoints, connection_message, connection_sink.clone()), + ) { + Ok(()) => + tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)), + Err(err) => error!( + target: "telemetry", + "Could not initialize telemetry: {}", + err, + ), + } + }, + None => error!( target: "telemetry", - "Could not initialize telemetry: {}", - err, - ); + "Could not initialize telemetry: the span could not be entered", + ), } connection_sink } } -/// Sinks to propagate telemetry connection established events. +/// Used to create a stream of events with only one event: when a telemetry connection +/// (re-)establishes. #[derive(Default, Clone, Debug)] pub struct TelemetryConnectionNotifier(Arc>>>); diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index a2a1333ed9633..caebcf26b61a0 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -226,13 +226,7 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let telemetry_worker = if let Some(telemetry_external_transport) = telemetry_external_transport { - sc_telemetry::TelemetryWorker::with_wasm_external_transport(telemetry_external_transport) - } else { - sc_telemetry::TelemetryWorker::new() - }.map_err(|err| format!("Could not initialize telemetry: {}", err))?; - let sender = telemetry_worker.sender(); - let telemetry_layer = sc_telemetry::TelemetryLayer::new(sender); + let (telemetry_layer, telemetry_worker) = sc_telemetry::TelemetryLayer::new(telemetry_external_transport).map_err(|err| format!("Could not initialize telemetry: {}", err))?; let event_format = EventFormat { timer, display_target: !simple, From e044c0e955fa7b666422f66962c04a98282a7b0c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 11:35:03 +0100 Subject: [PATCH 157/222] Re-organize --- client/telemetry/src/dispatcher.rs | 20 +++- client/telemetry/src/endpoints.rs | 78 +++++++++++++ client/telemetry/src/lib.rs | 109 ++---------------- .../telemetry/src/{worker.rs => transport.rs} | 72 ++++++++---- 4 files changed, 156 insertions(+), 123 deletions(-) create mode 100644 client/telemetry/src/endpoints.rs rename client/telemetry/src/{worker.rs => transport.rs} (64%) diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs index dea5dc6a726fd..c5a64ac40d818 100644 --- a/client/telemetry/src/dispatcher.rs +++ b/client/telemetry/src/dispatcher.rs @@ -1,7 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + use futures::prelude::*; use std::collections::HashMap; use crate::node::{Node, Infallible}; -use crate::worker::WsTrans; +use crate::transport::WsTrans; use std::iter::FromIterator; use libp2p::Multiaddr; use std::task::{Poll, Context}; diff --git a/client/telemetry/src/endpoints.rs b/client/telemetry/src/endpoints.rs new file mode 100644 index 0000000000000..5d7773e2dd63c --- /dev/null +++ b/client/telemetry/src/endpoints.rs @@ -0,0 +1,78 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use libp2p::{ + Multiaddr, +}; +use serde::{Deserialize, Deserializer, Serialize}; + +/// List of telemetry servers we want to talk to. Contains the URL of the server, and the +/// maximum verbosity level. +/// +/// The URL string can be either a URL or a multiaddress. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct TelemetryEndpoints( + #[serde(deserialize_with = "url_or_multiaddr_deser")] + pub(crate) Vec<(Multiaddr, u8)> +); + +/// Custom deserializer for TelemetryEndpoints, used to convert urls or multiaddr to multiaddr. +fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result, D::Error> + where D: Deserializer<'de> +{ + Vec::<(String, u8)>::deserialize(deserializer)? + .iter() + .map(|e| Ok((url_to_multiaddr(&e.0) + .map_err(serde::de::Error::custom)?, e.1))) + .collect() +} + +impl TelemetryEndpoints { + /// Create a `TelemetryEndpoints` based on a list of `(String, u8)`. + pub fn new(endpoints: Vec<(String, u8)>) -> Result { + let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() + .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) + .collect(); + endpoints.map(Self) + } +} + +impl TelemetryEndpoints { + /// Return `true` if there are no telemetry endpoints, `false` otherwise. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +/// Parses a WebSocket URL into a libp2p `Multiaddr`. +fn url_to_multiaddr(url: &str) -> Result { + // First, assume that we have a `Multiaddr`. + let parse_error = match url.parse() { + Ok(ma) => return Ok(ma), + Err(err) => err, + }; + + // If not, try the `ws://path/url` format. + if let Ok(ma) = libp2p::multiaddr::from_url(url) { + return Ok(ma) + } + + // If we have no clue about the format of that string, assume that we were expecting a + // `Multiaddr`. + Err(parse_error) +} diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 66abd344a1a5e..895b8ea8e2968 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -41,15 +41,12 @@ use futures::{channel::mpsc, prelude::*}; use libp2p::{ - core::transport::{OptionalTransport, timeout::TransportTimeout}, - wasm_ext, Multiaddr, Transport, + wasm_ext, Multiaddr, }; use log::{error, warn}; -use serde::{Deserialize, Deserializer, Serialize}; use std::{ collections::{HashMap, HashSet}, io, - pin::Pin, sync::Arc, time::Duration, }; @@ -65,69 +62,15 @@ pub use tracing; mod layer; mod node; -pub mod worker; mod dispatcher; +mod transport; +mod endpoints; pub use layer::*; use node::*; -use worker::{CONNECT_TIMEOUT, StreamSink}; // TODO mod use dispatcher::*; - -/// List of telemetry servers we want to talk to. Contains the URL of the server, and the -/// maximum verbosity level. -/// -/// The URL string can be either a URL or a multiaddress. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] -pub struct TelemetryEndpoints( - #[serde(deserialize_with = "url_or_multiaddr_deser")] - Vec<(Multiaddr, u8)> -); - -/// Custom deserializer for TelemetryEndpoints, used to convert urls or multiaddr to multiaddr. -fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result, D::Error> - where D: Deserializer<'de> -{ - Vec::<(String, u8)>::deserialize(deserializer)? - .iter() - .map(|e| Ok((url_to_multiaddr(&e.0) - .map_err(serde::de::Error::custom)?, e.1))) - .collect() -} - -impl TelemetryEndpoints { - /// Create a `TelemetryEndpoints` based on a list of `(String, u8)`. - pub fn new(endpoints: Vec<(String, u8)>) -> Result { - let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() - .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) - .collect(); - endpoints.map(Self) - } -} - -impl TelemetryEndpoints { - /// Return `true` if there are no telemetry endpoints, `false` otherwise. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -/// Parses a WebSocket URL into a libp2p `Multiaddr`. -fn url_to_multiaddr(url: &str) -> Result { - // First, assume that we have a `Multiaddr`. - let parse_error = match url.parse() { - Ok(ma) => return Ok(ma), - Err(err) => err, - }; - - // If not, try the `ws://path/url` format. - if let Ok(ma) = libp2p::multiaddr::from_url(url) { - return Ok(ma) - } - - // If we have no clue about the format of that string, assume that we were expecting a - // `Multiaddr`. - Err(parse_error) -} +pub use endpoints::*; +use transport::*; /// Substrate DEBUG log level. pub const SUBSTRATE_DEBUG: u8 = 9; @@ -154,7 +97,7 @@ pub struct TelemetryWorker { sender: mpsc::Sender<(Id, u8, String)>, init_receiver: mpsc::UnboundedReceiver, init_sender: mpsc::UnboundedSender, - transport: crate::worker::WsTrans, + transport: WsTrans, } impl TelemetryWorker { @@ -177,48 +120,10 @@ impl TelemetryWorker { sender, init_receiver, init_sender, - transport: Self::initialize_transport(wasm_external_transport)?, + transport: initialize_transport(wasm_external_transport)?, }) } - fn initialize_transport( - wasm_external_transport: Option, - ) -> Result { - let transport = match wasm_external_transport.clone() { - Some(t) => OptionalTransport::some(t), - None => OptionalTransport::none() - }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); - - // The main transport is the `wasm_external_transport`, but if we're on desktop we add - // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass - // an external transport on desktop and the fallback is used all the time. - #[cfg(not(target_os = "unknown"))] - let transport = transport.or_transport({ - let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; - libp2p::websocket::framed::WsConfig::new(inner) - .and_then(|connec, _| { - let connec = connec - .with(|item| { - let item = libp2p::websocket::framed::OutgoingData::Binary(item); - future::ready(Ok::<_, io::Error>(item)) - }) - .try_filter(|item| future::ready(item.is_data())) - .map_ok(|data| data.into_bytes()); - future::ready(Ok::<_, io::Error>(connec)) - }) - }); - - Ok(TransportTimeout::new( - transport.map(|out, _| { - let out = out - .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) - .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); - Box::pin(out) as Pin> - }), - CONNECT_TIMEOUT - ).boxed()) - } - /// Get a handle to this [`TelemetryWorker`]. /// /// This is used when you want to register a new telemetry for a Substrate node. diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/transport.rs similarity index 64% rename from client/telemetry/src/worker.rs rename to client/telemetry/src/transport.rs index d7805c86cef6f..d1767cf567316 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/transport.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 // This program is free software: you can redistribute it and/or modify @@ -16,32 +16,63 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Contains the object that makes the telemetry work. -//! -//! # Usage -//! -//! - Create a `TelemetryWorker` with `TelemetryWorker::new`. -//! - Send messages to the telemetry with `TelemetryWorker::send_message`. Messages will only be -//! sent to the appropriate targets. Messages may be ignored if the target happens to be -//! temporarily unreachable. -//! - You must appropriately poll the worker with `TelemetryWorker::poll`. Polling will/may produce -//! events indicating what happened since the latest polling. -//! - -use futures::{prelude::*, ready}; -use log::{error}; -use std::{io, pin::Pin, task::Context, task::Poll, time}; +use futures::{prelude::*, task::{Context, Poll}, ready}; +use std::pin::Pin; +use std::io; +use libp2p::{ + core::transport::{OptionalTransport, timeout::TransportTimeout}, + wasm_ext, Transport, +}; +use std::time::Duration; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP /// upgrading. -pub(crate) const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); +const CONNECT_TIMEOUT: Duration = Duration::from_secs(20); + +pub(crate) fn initialize_transport( + wasm_external_transport: Option, +) -> Result { + let transport = match wasm_external_transport.clone() { + Some(t) => OptionalTransport::some(t), + None => OptionalTransport::none() + }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); + + // The main transport is the `wasm_external_transport`, but if we're on desktop we add + // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass + // an external transport on desktop and the fallback is used all the time. + #[cfg(not(target_os = "unknown"))] + let transport = transport.or_transport({ + let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; + libp2p::websocket::framed::WsConfig::new(inner) + .and_then(|connec, _| { + let connec = connec + .with(|item| { + let item = libp2p::websocket::framed::OutgoingData::Binary(item); + future::ready(Ok::<_, io::Error>(item)) + }) + .try_filter(|item| future::ready(item.is_data())) + .map_ok(|data| data.into_bytes()); + future::ready(Ok::<_, io::Error>(connec)) + }) + }); + + Ok(TransportTimeout::new( + transport.map(|out, _| { + let out = out + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); + Box::pin(out) as Pin> + }), + CONNECT_TIMEOUT + ).boxed()) +} /// A trait that implements `Stream` and `Sink`. -pub trait StreamAndSink: Stream + Sink {} +pub(crate) trait StreamAndSink: Stream + Sink {} impl, I> StreamAndSink for T {} /// A type alias for the WebSocket transport. -pub type WsTrans = libp2p::core::transport::Boxed< +pub(crate) type WsTrans = libp2p::core::transport::Boxed< Pin, Item = Result, io::Error>, @@ -86,7 +117,7 @@ impl StreamSink { if let Some(buffer) = this.1 { if ready!(this.0.poll_write(cx, &buffer[..]))? != buffer.len() { - error!(target: "telemetry", + log::error!(target: "telemetry", "Detected some internal buffering happening in the telemetry"); let err = io::Error::new(io::ErrorKind::Other, "Internal buffering detected"); return Poll::Ready(Err(err)); @@ -125,3 +156,4 @@ impl Sink> for StreamSink { AsyncWrite::poll_close(this.0, cx) } } + From af28034402e43fa2fa6581636028d85fb53f28e4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 11:38:15 +0100 Subject: [PATCH 158/222] doc --- client/tracing/src/logging/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index caebcf26b61a0..62fdfc455ed2a 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -41,12 +41,14 @@ macro_rules! disable_log_reloading { ($builder:expr) => {{ let builder = $builder.with_filter_reloading(); let handle = builder.reload_handle(); - crate::set_reload_handle(handle); + $crate::set_reload_handle(handle); builder }}; } -/// TODO +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects. +/// +/// When running in a browser, the `telemetry_external_transport` should be provided. pub fn get_default_subscriber_and_telemetry_worker( pattern: &str, telemetry_external_transport: Option, @@ -64,7 +66,8 @@ pub fn get_default_subscriber_and_telemetry_worker( ) } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects. +/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with log +/// reloading. /// /// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] @@ -114,7 +117,7 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling( } /// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with -/// profiling enabled. +/// profiling enabled and log reloading. /// /// When running in a browser, the `telemetry_external_transport` should be provided. #[cfg(not(target_os = "unknown"))] From 281cacb0e8b5a25ca123edbf6246981462f88072 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 12:23:46 +0100 Subject: [PATCH 159/222] Fix, clean-up & re-organize --- client/rpc/src/system/mod.rs | 7 +- client/tracing/src/lib.rs | 97 +------------------- client/tracing/src/logging/directives.rs | 108 +++++++++++++++++++++++ client/tracing/src/logging/mod.rs | 47 +++++----- 4 files changed, 133 insertions(+), 126 deletions(-) create mode 100644 client/tracing/src/logging/directives.rs diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index f1ebf5f702a27..c8cb068ba85d2 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -24,6 +24,7 @@ mod tests; use futures::{future::BoxFuture, FutureExt, TryFutureExt}; use futures::{channel::oneshot, compat::Compat}; use sc_rpc_api::{DenyUnsafe, Receiver}; +use sc_tracing::logging; use sp_utils::mpsc::TracingUnboundedSender; use sp_runtime::traits::{self, Header as HeaderT}; @@ -200,12 +201,12 @@ impl SystemApi::Number> for Sy fn system_add_log_filter(&self, directives: String) -> std::result::Result<(), rpc::Error> { self.deny_unsafe.check_if_safe()?; - sc_tracing::add_directives(&directives); - sc_tracing::reload_filter().map_err(|_e| rpc::Error::internal_error()) + logging::add_directives(&directives); + logging::reload_filter().map_err(|_e| rpc::Error::internal_error()) } fn system_reset_log_filter(&self)-> std::result::Result<(), rpc::Error> { self.deny_unsafe.check_if_safe()?; - sc_tracing::reset_log_filter().map_err(|_e| rpc::Error::internal_error()) + logging::reset_log_filter().map_err(|_e| rpc::Error::internal_error()) } } diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 0717d12c1b24d..a769a83246e11 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -29,7 +29,6 @@ pub mod logging; use rustc_hash::FxHashMap; use std::fmt; use std::time::{Duration, Instant}; - use parking_lot::Mutex; use serde::ser::{Serialize, Serializer, SerializeMap}; use tracing::{ @@ -40,111 +39,17 @@ use tracing::{ subscriber::Subscriber, }; use tracing_subscriber::{ - fmt::time::ChronoLocal, CurrentSpan, - EnvFilter, - layer::{self, Layer, Context}, - fmt as tracing_fmt, - Registry, + layer::{Layer, Context}, }; - use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; -use tracing_subscriber::reload::Handle; -use once_cell::sync::OnceCell; -use tracing_subscriber::filter::Directive; const ZERO_DURATION: Duration = Duration::from_nanos(0); #[doc(hidden)] pub use tracing; -// The layered Subscriber as built up in `init_logger()`. -// Used in the reload `Handle`. -type SCSubscriber< - N = tracing_fmt::format::DefaultFields, - E = logging::EventFormat, - W = fn() -> std::io::Stderr -> = layer::Layered, Registry>; - -// Handle to reload the tracing log filter -static FILTER_RELOAD_HANDLE: OnceCell> = OnceCell::new(); -// Directives that are defaulted to when resetting the log filter -static DEFAULT_DIRECTIVES: OnceCell>> = OnceCell::new(); -// Current state of log filter -static CURRENT_DIRECTIVES: OnceCell>> = OnceCell::new(); - -/// Initialize FILTER_RELOAD_HANDLE, only possible once -pub fn set_reload_handle(handle: Handle) { - let _ = FILTER_RELOAD_HANDLE.set(handle); -} - -/// Add log filter directive(s) to the defaults -/// -/// The syntax is identical to the CLI `=`: -/// -/// `sync=debug,state=trace` -pub fn add_default_directives(directives: &str) { - DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); - add_directives(directives); -} - -/// Add directives to current directives -pub fn add_directives(directives: &str) { - CURRENT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); -} - -/// Reload the logging filter with the supplied directives added to the existing directives -pub fn reload_filter() -> Result<(), String> { - let mut env_filter = EnvFilter::default(); - if let Some(current_directives) = CURRENT_DIRECTIVES.get() { - // Use join and then split in case any directives added together - for directive in current_directives.lock().join(",").split(',').map(|d| d.parse()) { - match directive { - Ok(dir) => env_filter = env_filter.add_directive(dir), - Err(invalid_directive) => { - log::warn!( - target: "tracing", - "Unable to parse directive while setting log filter: {:?}", - invalid_directive, - ); - } - } - } - } - env_filter = env_filter.add_directive( - "sc_tracing=trace" - .parse() - .expect("provided directive is valid"), - ); - log::debug!(target: "tracing", "Reloading log filter with: {}", env_filter); - FILTER_RELOAD_HANDLE.get() - .ok_or("No reload handle present".to_string())? - .reload(env_filter) - .map_err(|e| format!("{}", e)) -} - -/// Resets the log filter back to the original state when the node was started. -/// -/// Includes substrate defaults and CLI supplied directives. -pub fn reset_log_filter() -> Result<(), String> { - *CURRENT_DIRECTIVES - .get_or_init(|| Mutex::new(Vec::new())).lock() = - DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().clone(); - reload_filter() -} - -/// Parse `Directive` and add to default directives if successful. -/// -/// Ensures the supplied directive will be restored when resetting the log filter. -pub fn parse_default_directive(directive: &str) -> Result { - let dir = directive - .parse() - .map_err(|_| format!("Unable to parse directive: {}", directive))?; - add_default_directives(directive); - Ok(dir) -} - /// Responsible for assigning ids to new spans, which are not re-used. pub struct ProfilingLayer { targets: Vec<(String, Level)>, diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs new file mode 100644 index 0000000000000..83b2b1866a518 --- /dev/null +++ b/client/tracing/src/logging/directives.rs @@ -0,0 +1,108 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use once_cell::sync::OnceCell; +use parking_lot::Mutex; +use tracing_subscriber::{ + fmt::time::ChronoLocal, Registry, EnvFilter, reload::Handle, filter::Directive, + fmt as tracing_fmt, layer, +}; + +// Handle to reload the tracing log filter +static FILTER_RELOAD_HANDLE: OnceCell> = OnceCell::new(); +// Directives that are defaulted to when resetting the log filter +static DEFAULT_DIRECTIVES: OnceCell>> = OnceCell::new(); +// Current state of log filter +static CURRENT_DIRECTIVES: OnceCell>> = OnceCell::new(); + +/// Add log filter directive(s) to the defaults +/// +/// The syntax is identical to the CLI `=`: +/// +/// `sync=debug,state=trace` +pub(crate) fn add_default_directives(directives: &str) { + DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); + add_directives(directives); +} + +/// Add directives to current directives +pub fn add_directives(directives: &str) { + CURRENT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); +} + +/// Parse `Directive` and add to default directives if successful. +/// +/// Ensures the supplied directive will be restored when resetting the log filter. +pub(crate) fn parse_default_directive(directive: &str) -> Result { + let dir = directive + .parse() + .map_err(|_| format!("Unable to parse directive: {}", directive))?; + add_default_directives(directive); + Ok(dir) +} + +/// Reload the logging filter with the supplied directives added to the existing directives +pub fn reload_filter() -> Result<(), String> { + let mut env_filter = EnvFilter::default(); + if let Some(current_directives) = CURRENT_DIRECTIVES.get() { + // Use join and then split in case any directives added together + for directive in current_directives.lock().join(",").split(',').map(|d| d.parse()) { + match directive { + Ok(dir) => env_filter = env_filter.add_directive(dir), + Err(invalid_directive) => { + log::warn!( + target: "tracing", + "Unable to parse directive while setting log filter: {:?}", + invalid_directive, + ); + } + } + } + } + env_filter = env_filter.add_directive( + "sc_tracing=trace" + .parse() + .expect("provided directive is valid"), + ); + log::debug!(target: "tracing", "Reloading log filter with: {}", env_filter); + FILTER_RELOAD_HANDLE.get() + .ok_or("No reload handle present".to_string())? + .reload(env_filter) + .map_err(|e| format!("{}", e)) +} + +/// Resets the log filter back to the original state when the node was started. +/// +/// Includes substrate defaults and CLI supplied directives. +pub fn reset_log_filter() -> Result<(), String> { + *CURRENT_DIRECTIVES + .get_or_init(|| Mutex::new(Vec::new())).lock() = + DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().clone(); + reload_filter() +} + +/// Initialize FILTER_RELOAD_HANDLE, only possible once +pub(crate) fn set_reload_handle(handle: Handle) { + let _ = FILTER_RELOAD_HANDLE.set(handle); +} + +// The layered Subscriber as built up in `init_logger()`. +// Used in the reload `Handle`. +type SCSubscriber< + N = tracing_fmt::format::DefaultFields, + E = crate::logging::EventFormat, + W = fn() -> std::io::Stderr +> = layer::Layered, Registry>; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 62fdfc455ed2a..60ff0be8f3de4 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -22,14 +22,16 @@ #![warn(missing_docs)] +mod directives; mod event_format; mod layers; pub use sc_tracing_proc_macro::*; +pub use directives::*; use tracing::Subscriber; use tracing_subscriber::{ - filter::Directive, fmt::time::ChronoLocal, layer::{self, SubscriberExt}, registry::LookupSpan, + fmt::time::ChronoLocal, layer::{self, SubscriberExt}, registry::LookupSpan, FmtSubscriber, Layer, EnvFilter, fmt::{SubscriberBuilder, format, FormatFields, MakeWriter, FormatEvent, Formatter, Layer as FmtLayer}, Registry, }; @@ -41,7 +43,7 @@ macro_rules! disable_log_reloading { ($builder:expr) => {{ let builder = $builder.with_filter_reloading(); let handle = builder.reload_handle(); - $crate::set_reload_handle(handle); + set_reload_handle(handle); builder }}; } @@ -60,7 +62,7 @@ pub fn get_default_subscriber_and_telemetry_worker( String, > { get_default_subscriber_and_telemetry_worker_internal( - parse_directives(pattern), + pattern, telemetry_external_transport, |builder| builder, ) @@ -82,7 +84,7 @@ pub fn get_default_subscriber_and_telemetry_worker_with_log_reloading( String, > { get_default_subscriber_and_telemetry_worker_internal( - parse_directives(pattern), + pattern, telemetry_external_transport, |builder| disable_log_reloading!(builder), ) @@ -105,9 +107,7 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling( String, > { let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( - parse_directives(pattern) - .into_iter() - .chain(parse_directives(profiling_targets).into_iter()), + &format!("{},{}", pattern, profiling_targets), telemetry_external_transport, |builder| builder, )?; @@ -134,9 +134,7 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reload String, > { let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( - parse_directives(pattern) - .into_iter() - .chain(parse_directives(profiling_targets).into_iter()), + &format!("{},{}", pattern, profiling_targets), telemetry_external_transport, |builder| disable_log_reloading!(builder), )?; @@ -148,7 +146,7 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reload // Common implementation for `get_default_subscriber_and_telemetry_worker` and // `get_default_subscriber_and_telemetry_worker_with_profiling`. fn get_default_subscriber_and_telemetry_worker_internal( - extra_directives: impl IntoIterator, + pattern: &str, telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< @@ -165,7 +163,13 @@ where F: layer::Layer> + Send + Sync + 'static, FmtLayer: layer::Layer + Send + Sync + 'static, { - use crate::parse_default_directive; + // Accept all valid directives and print invalid ones + fn parse_user_directives(mut env_filter: EnvFilter, dirs: &str) -> std::result::Result { + for dir in dirs.split(',') { + env_filter = env_filter.add_directive(parse_default_directive(&dir)?); + } + Ok(env_filter) + } if let Err(e) = tracing_log::LogTracer::init() { return Err(format!("Registering Substrate logger failed: {:}!", e)); @@ -191,17 +195,15 @@ where .expect("provided directive is valid")); if let Ok(lvl) = std::env::var("RUST_LOG") { - // We're not sure if log or tracing is available at this moment, so silently ignore the - // parse error. - for directive in parse_directives(lvl) { - env_filter = env_filter.add_directive(directive); + if lvl != "" { + env_filter = parse_user_directives(env_filter, &lvl)?; } } - for directive in extra_directives { + if pattern != "" { // We're not sure if log or tracing is available at this moment, so silently ignore the // parse error. - env_filter = env_filter.add_directive(directive); + env_filter = parse_user_directives(env_filter, pattern)?; } // If we're only logging `INFO` entries then we'll use a simplified logging format. @@ -217,10 +219,6 @@ where env_filter = env_filter.add_directive( parse_default_directive("sc_tracing=trace").expect("provided directive is valid") ); - env_filter = env_filter.add_directive( - // TODO - parse_default_directive("telemetry-logger=trace").expect("provided directive is valid") - ); let enable_color = atty::is(atty::Stream::Stderr); let timer = ChronoLocal::with_format(if simple { @@ -266,11 +264,6 @@ where Ok((subscriber, telemetry_worker)) } -// Transform a string of comma separated logging directive into a `Vec`. -fn parse_directives(dirs: impl AsRef) -> Vec { - dirs.as_ref().split(',').filter_map(|s| s.parse().ok()).collect() -} - #[cfg(test)] mod tests { use super::*; From 566d95a51670388817b014c9ad25a6535f4c25ea Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 13:19:37 +0100 Subject: [PATCH 160/222] Use a builder pattern for global logger and remove tracing dependencies --- Cargo.lock | 3 - bin/node/cli/Cargo.toml | 1 - client/cli/Cargo.toml | 1 - client/cli/src/config.rs | 31 +++---- client/cli/src/lib.rs | 76 ----------------- client/tracing/src/logging/mod.rs | 135 ++++++++++++++++++++++++++---- utils/browser/Cargo.toml | 1 - utils/browser/src/lib.rs | 11 +-- 8 files changed, 139 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0de4de933af9..ea416f752766a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3792,7 +3792,6 @@ dependencies = [ "substrate-build-script-utils", "substrate-frame-cli", "tempfile", - "tracing", "wasm-bindgen", "wasm-bindgen-futures", ] @@ -6512,7 +6511,6 @@ dependencies = [ "thiserror", "tiny-bip39", "tokio 0.2.23", - "tracing", ] [[package]] @@ -8834,7 +8832,6 @@ dependencies = [ "sc-telemetry", "sc-tracing", "sp-database", - "tracing", "wasm-bindgen", "wasm-bindgen-futures", ] diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 6574ccb733b52..d5a6e724eb0ab 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -41,7 +41,6 @@ hex-literal = "0.3.1" log = "0.4.8" rand = "0.7.2" structopt = { version = "0.3.8", optional = true } -tracing = "0.1.22" parking_lot = "0.10.0" # primitives diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index dbf23a2e7ab90..535a420a82044 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -42,7 +42,6 @@ structopt = "0.3.8" sc-tracing = { version = "2.0.0", path = "../tracing" } chrono = "0.4.10" serde = "1.0.111" -tracing = "0.1.22" thiserror = "1.0.21" [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index ab58e40cf7cd9..466f21df95f95 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -21,8 +21,8 @@ use crate::arg_enums::Database; use crate::error::Result; use crate::{ - init_logging_and_telemetry, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, - NodeKeyParams, OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, + DatabaseParams, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams, + OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, }; use log::warn; use names::{Generator, Name}; @@ -33,6 +33,7 @@ use sc_service::config::{ TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; use sc_service::{ChainSpec, TracingReceiver}; +use sc_tracing::logging::GlobalLogger; use std::net::SocketAddr; use std::path::PathBuf; @@ -552,21 +553,21 @@ pub trait CliConfiguration: Sized { /// 2. Initializes the logger /// 3. Raises the FD limit fn init(&self) -> Result { - let logger_pattern = self.log_filters()?; - let tracing_receiver = self.tracing_receiver()?; - let tracing_targets = self.tracing_targets()?; - let disable_log_reloading = self.is_log_filter_reloading_disabled()?; - let telemetry_external_transport = self.telemetry_external_transport()?; - sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let telemetry_worker = init_logging_and_telemetry( - &logger_pattern, - tracing_receiver, - tracing_targets.as_ref().map(|x| x.as_str()), - telemetry_external_transport, - disable_log_reloading, - )?; + let mut logger = GlobalLogger::new(self.log_filters()?); + logger.with_log_reloading(!self.is_log_filter_reloading_disabled()?); + + if let Some(transport) = self.telemetry_external_transport()? { + logger.with_transport(transport); + } + + if let Some(tracing_targets) = self.tracing_targets()? { + let tracing_receiver = self.tracing_receiver()?; + logger.with_profiling(tracing_receiver, tracing_targets); + } + + let telemetry_worker = logger.init()?; if let Some(new_limit) = fdlimit::raise_fd_limit() { if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT { diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 862743c4afac1..3d40a0fa1de33 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -44,9 +44,6 @@ use structopt::{ clap::{self, AppSettings}, StructOpt, }; -use sc_tracing::logging; -#[doc(hidden)] -pub use tracing; /// Substrate client CLI /// @@ -229,76 +226,3 @@ pub trait SubstrateCli: Sized { /// Native runtime version. fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion; } - -/// Initialize the global logger -/// -/// This sets various global logging and tracing instances and thus may only be called once. -pub fn init_logging_and_telemetry( - pattern: &str, - tracing_receiver: sc_tracing::TracingReceiver, - profiling_targets: Option<&str>, - telemetry_external_transport: Option, - disable_log_reloading: bool, -) -> std::result::Result { - Ok(if let Some(profiling_targets) = profiling_targets { - if disable_log_reloading { - let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_profiling( - pattern, - telemetry_external_transport, - tracing_receiver, - profiling_targets, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } - - telemetry_worker - } else { - let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( - pattern, - telemetry_external_transport, - tracing_receiver, - profiling_targets, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } - - telemetry_worker - } - } else { - if disable_log_reloading { - let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker( - pattern, - telemetry_external_transport, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } - - telemetry_worker - } else { - let (subscriber, telemetry_worker) = logging::get_default_subscriber_and_telemetry_worker_with_log_reloading( - pattern, - telemetry_external_transport, - )?; - - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } - - telemetry_worker - } - }) -} diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 60ff0be8f3de4..b2c4a947ba9d3 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -29,6 +29,7 @@ mod layers; pub use sc_tracing_proc_macro::*; pub use directives::*; +use sc_telemetry::{ExtTransport, TelemetryWorker}; use tracing::Subscriber; use tracing_subscriber::{ fmt::time::ChronoLocal, layer::{self, SubscriberExt}, registry::LookupSpan, @@ -51,13 +52,13 @@ macro_rules! disable_log_reloading { /// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects. /// /// When running in a browser, the `telemetry_external_transport` should be provided. -pub fn get_default_subscriber_and_telemetry_worker( +fn get_default_subscriber_and_telemetry_worker( pattern: &str, - telemetry_external_transport: Option, + telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::TelemetryWorker, + TelemetryWorker, ), String, > { @@ -72,14 +73,13 @@ pub fn get_default_subscriber_and_telemetry_worker( /// reloading. /// /// When running in a browser, the `telemetry_external_transport` should be provided. -#[cfg(not(target_os = "unknown"))] -pub fn get_default_subscriber_and_telemetry_worker_with_log_reloading( +fn get_default_subscriber_and_telemetry_worker_with_log_reloading( pattern: &str, - telemetry_external_transport: Option, + telemetry_external_transport: Option, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::TelemetryWorker, + TelemetryWorker, ), String, > { @@ -94,15 +94,15 @@ pub fn get_default_subscriber_and_telemetry_worker_with_log_reloading( /// profiling enabled. /// /// When running in a browser, the `telemetry_external_transport` should be provided. -pub fn get_default_subscriber_and_telemetry_worker_with_profiling( +fn get_default_subscriber_and_telemetry_worker_with_profiling( pattern: &str, - telemetry_external_transport: Option, + telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::TelemetryWorker, + TelemetryWorker, ), String, > { @@ -120,16 +120,15 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling( /// profiling enabled and log reloading. /// /// When running in a browser, the `telemetry_external_transport` should be provided. -#[cfg(not(target_os = "unknown"))] -pub fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( +fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( pattern: &str, - telemetry_external_transport: Option, + telemetry_external_transport: Option, tracing_receiver: crate::TracingReceiver, profiling_targets: &str, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::TelemetryWorker, + TelemetryWorker, ), String, > { @@ -147,12 +146,12 @@ pub fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reload // `get_default_subscriber_and_telemetry_worker_with_profiling`. fn get_default_subscriber_and_telemetry_worker_internal( pattern: &str, - telemetry_external_transport: Option, + telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, ) -> std::result::Result< ( impl Subscriber + for<'a> LookupSpan<'a>, - sc_telemetry::TelemetryWorker, + TelemetryWorker, ), String, > @@ -264,6 +263,110 @@ where Ok((subscriber, telemetry_worker)) } +pub struct GlobalLogger { + pattern: String, + profiling: Option<(crate::TracingReceiver, String)>, + telemetry_external_transport: Option, + disable_log_reloading: bool, +} + +impl GlobalLogger { + pub fn new>(pattern: S) -> Self { + Self { + pattern: pattern.into(), + profiling: None, + telemetry_external_transport: None, + disable_log_reloading: false, + } + } + + pub fn with_profiling>( + &mut self, + tracing_receiver: crate::TracingReceiver, + profiling_targets: S, + ) -> &mut Self { + self.profiling = Some((tracing_receiver, profiling_targets.into())); + self + } + + pub fn with_log_reloading(&mut self, enabled: bool) -> &mut Self { + self.disable_log_reloading = !enabled; + self + } + + pub fn with_transport(&mut self, transport: ExtTransport) -> &mut Self { + self.telemetry_external_transport = Some(transport); + self + } + + /// Initialize the global logger + /// + /// This sets various global logging and tracing instances and thus may only be called once. + pub fn init(self) -> Result { + Ok(if let Some((tracing_receiver, profiling_targets)) = self.profiling { + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_profiling( + &self.pattern, + self.telemetry_external_transport, + tracing_receiver, + &profiling_targets, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetry_worker + } else { + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( + &self.pattern, + self.telemetry_external_transport, + tracing_receiver, + &profiling_targets, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetry_worker + } + } else { + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker( + &self.pattern, + self.telemetry_external_transport, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetry_worker + } else { + let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_log_reloading( + &self.pattern, + self.telemetry_external_transport, + )?; + + if let Err(e) = tracing::subscriber::set_global_default(subscriber) { + return Err(format!( + "Registering Substrate tracing subscriber failed: {:}!", e + )) + } + + telemetry_worker + } + }) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 727dbfc6111a6..11cf698e7ba58 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -19,7 +19,6 @@ log = "0.4.8" libp2p-wasm-ext = { version = "0.25", features = ["websocket"] } console_error_panic_hook = "0.1.6" js-sys = "0.3.34" -tracing = "0.1.10" wasm-bindgen = "0.2.57" wasm-bindgen-futures = "0.4.18" kvdb-web = "0.7" diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 6909704860d54..34f418270511c 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -23,6 +23,7 @@ use sc_service::{ config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration}, GenericChainSpec, RuntimeGenesis }; +use sc_tracing::logging::GlobalLogger; use wasm_bindgen::prelude::*; use futures::{ prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select} @@ -41,13 +42,9 @@ pub fn init_logging_and_telemetry( pattern: &str, ) -> Result { let transport = ExtTransport::new(ffi::websocket_transport()); - let (subscriber, telemetry_worker) = sc_tracing::logging::get_default_subscriber_and_telemetry_worker( - pattern, - Some(transport.clone()), - )?; - - tracing::subscriber::set_global_default(subscriber) - .map_err(|e| format!("could not set global default subscriber: {}", e))?; + let mut logger = GlobalLogger::new(pattern); + logger.with_transport(transport); + let telemetry_worker = logger.init()?; Ok(telemetry_worker) } From bb926c069405507451dc63d89e1c1a02dbcc7f74 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 13:22:41 +0100 Subject: [PATCH 161/222] Rename to GlobalLoggerBuilder --- client/cli/src/config.rs | 4 ++-- client/tracing/src/logging/mod.rs | 4 ++-- utils/browser/src/lib.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 466f21df95f95..03f3eda88c52e 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -33,7 +33,7 @@ use sc_service::config::{ TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; use sc_service::{ChainSpec, TracingReceiver}; -use sc_tracing::logging::GlobalLogger; +use sc_tracing::logging::GlobalLoggerBuilder; use std::net::SocketAddr; use std::path::PathBuf; @@ -555,7 +555,7 @@ pub trait CliConfiguration: Sized { fn init(&self) -> Result { sp_panic_handler::set(&C::support_url(), &C::impl_version()); - let mut logger = GlobalLogger::new(self.log_filters()?); + let mut logger = GlobalLoggerBuilder::new(self.log_filters()?); logger.with_log_reloading(!self.is_log_filter_reloading_disabled()?); if let Some(transport) = self.telemetry_external_transport()? { diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index b2c4a947ba9d3..6bbcd42f6858a 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -263,14 +263,14 @@ where Ok((subscriber, telemetry_worker)) } -pub struct GlobalLogger { +pub struct GlobalLoggerBuilder { pattern: String, profiling: Option<(crate::TracingReceiver, String)>, telemetry_external_transport: Option, disable_log_reloading: bool, } -impl GlobalLogger { +impl GlobalLoggerBuilder { pub fn new>(pattern: S) -> Self { Self { pattern: pattern.into(), diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 34f418270511c..ba630344760bd 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -23,7 +23,7 @@ use sc_service::{ config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration}, GenericChainSpec, RuntimeGenesis }; -use sc_tracing::logging::GlobalLogger; +use sc_tracing::logging::GlobalLoggerBuilder; use wasm_bindgen::prelude::*; use futures::{ prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select} @@ -42,7 +42,7 @@ pub fn init_logging_and_telemetry( pattern: &str, ) -> Result { let transport = ExtTransport::new(ffi::websocket_transport()); - let mut logger = GlobalLogger::new(pattern); + let mut logger = GlobalLoggerBuilder::new(pattern); logger.with_transport(transport); let telemetry_worker = logger.init()?; From fe160aadf20f5e8170c3b20e65759fccab8e9efd Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 13:39:57 +0100 Subject: [PATCH 162/222] Refactor a bit --- client/tracing/src/logging/mod.rs | 150 ++++++------------------------ 1 file changed, 26 insertions(+), 124 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 6bbcd42f6858a..94631e58345fd 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -49,102 +49,18 @@ macro_rules! disable_log_reloading { }}; } -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. -fn get_default_subscriber_and_telemetry_worker( - pattern: &str, - telemetry_external_transport: Option, -) -> std::result::Result< - ( - impl Subscriber + for<'a> LookupSpan<'a>, - TelemetryWorker, - ), - String, -> { - get_default_subscriber_and_telemetry_worker_internal( - pattern, - telemetry_external_transport, - |builder| builder, - ) -} - -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with log -/// reloading. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. -fn get_default_subscriber_and_telemetry_worker_with_log_reloading( - pattern: &str, - telemetry_external_transport: Option, -) -> std::result::Result< - ( - impl Subscriber + for<'a> LookupSpan<'a>, - TelemetryWorker, - ), - String, -> { - get_default_subscriber_and_telemetry_worker_internal( - pattern, - telemetry_external_transport, - |builder| disable_log_reloading!(builder), - ) -} - -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with -/// profiling enabled. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. -fn get_default_subscriber_and_telemetry_worker_with_profiling( - pattern: &str, - telemetry_external_transport: Option, - tracing_receiver: crate::TracingReceiver, - profiling_targets: &str, -) -> std::result::Result< - ( - impl Subscriber + for<'a> LookupSpan<'a>, - TelemetryWorker, - ), - String, -> { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( - &format!("{},{}", pattern, profiling_targets), - telemetry_external_transport, - |builder| builder, - )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); - - Ok((subscriber.with(profiling), telemetry_worker)) -} - -/// Get a new default tracing's `Subscriber` and a sc-telemetry's `TelemetryWorker` objects with -/// profiling enabled and log reloading. -/// -/// When running in a browser, the `telemetry_external_transport` should be provided. -fn get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( - pattern: &str, - telemetry_external_transport: Option, - tracing_receiver: crate::TracingReceiver, - profiling_targets: &str, -) -> std::result::Result< - ( - impl Subscriber + for<'a> LookupSpan<'a>, - TelemetryWorker, - ), - String, -> { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_internal( - &format!("{},{}", pattern, profiling_targets), - telemetry_external_transport, - |builder| disable_log_reloading!(builder), - )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, profiling_targets); - - Ok((subscriber.with(profiling), telemetry_worker)) +macro_rules! set_global_default { + ($subscriber:expr) => {{ + tracing::subscriber::set_global_default($subscriber) + .map_err(|err| format!( + "Registering Substrate tracing subscriber failed: {}!", + err, + )) + }}; } -// Common implementation for `get_default_subscriber_and_telemetry_worker` and -// `get_default_subscriber_and_telemetry_worker_with_profiling`. -fn get_default_subscriber_and_telemetry_worker_internal( +/// Common implementation to get the subscriber. +fn get_subscriber_internal( pattern: &str, telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, @@ -305,61 +221,47 @@ impl GlobalLoggerBuilder { pub fn init(self) -> Result { Ok(if let Some((tracing_receiver, profiling_targets)) = self.profiling { if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_profiling( - &self.pattern, + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), self.telemetry_external_transport, - tracing_receiver, - &profiling_targets, + |builder| builder, )?; + let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } + set_global_default!(subscriber.with(profiling))?; telemetry_worker } else { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_profiling_and_log_reloading( - &self.pattern, + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), self.telemetry_external_transport, - tracing_receiver, - &profiling_targets, + |builder| disable_log_reloading!(builder), )?; + let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } + set_global_default!(subscriber.with(profiling))?; telemetry_worker } } else { if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker( + let (subscriber, telemetry_worker) = get_subscriber_internal( &self.pattern, self.telemetry_external_transport, + |builder| builder, )?; - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } + set_global_default!(subscriber)?; telemetry_worker } else { - let (subscriber, telemetry_worker) = get_default_subscriber_and_telemetry_worker_with_log_reloading( + let (subscriber, telemetry_worker) = get_subscriber_internal( &self.pattern, self.telemetry_external_transport, + |builder| disable_log_reloading!(builder), )?; - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err(format!( - "Registering Substrate tracing subscriber failed: {:}!", e - )) - } + set_global_default!(subscriber)?; telemetry_worker } From f2667bee521bf6d0694d584e428f30634694bb84 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 14:01:13 +0100 Subject: [PATCH 163/222] Handle errors better --- Cargo.lock | 2 + client/cli/src/error.rs | 3 ++ client/telemetry/Cargo.toml | 1 + client/telemetry/src/layer.rs | 3 +- client/telemetry/src/lib.rs | 15 +++++- client/tracing/Cargo.toml | 1 + client/tracing/src/logging/directives.rs | 5 +- client/tracing/src/logging/mod.rs | 62 +++++++++++++----------- utils/browser/src/lib.rs | 2 +- 9 files changed, 59 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea416f752766a..8aad1941ba425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7458,6 +7458,7 @@ dependencies = [ "serde_json", "sp-utils", "take_mut", + "thiserror", "tracing", "tracing-subscriber", "void", @@ -7482,6 +7483,7 @@ dependencies = [ "serde", "serde_json", "sp-tracing", + "thiserror", "tracing", "tracing-core", "tracing-log", diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index 5190cae2c2ff8..7ac32eb032b76 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -80,6 +80,9 @@ pub enum Error { /// Application specific error chain sequence forwarder. #[error(transparent)] Application(#[from] Box), + + #[error(transparent)] + GlobalLoggerError(#[from] sc_tracing::logging::Error), } impl std::convert::From<&str> for Error { diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 1876c5734de42..15b76a2c54efa 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -31,3 +31,4 @@ tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } +thiserror = "1.0.21" diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index d6b896509ef57..4409db0db9ff6 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -23,7 +23,6 @@ use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; use libp2p::wasm_ext::ExtTransport; use crate::TelemetryWorker; -use std::io; /// Span name used to report the telemetry. pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; @@ -34,7 +33,7 @@ pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. - pub fn new(telemetry_external_transport: Option) -> Result<(Self, TelemetryWorker), io::Error> { + pub fn new(telemetry_external_transport: Option) -> super::Result<(Self, TelemetryWorker)> { let worker = TelemetryWorker::new(telemetry_external_transport)?; let sender = worker.sender(); Ok((Self(Mutex::new(sender)), worker)) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 895b8ea8e2968..fe6159f9fc8a0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -46,7 +46,6 @@ use libp2p::{ use log::{error, warn}; use std::{ collections::{HashMap, HashSet}, - io, sync::Arc, time::Duration, }; @@ -100,6 +99,18 @@ pub struct TelemetryWorker { transport: WsTrans, } +/// Telemetry Result typedef. +pub type Result = std::result::Result; + +/// Telemetry errors. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +#[non_exhaustive] +pub enum Error { + #[error(transparent)] + Io(#[from] std::io::Error), +} + impl TelemetryWorker { /// Create a [`TelemetryWorker`] instance using an `ExtTransport`. /// @@ -111,7 +122,7 @@ impl TelemetryWorker { /// > **Important**: Each individual call to `write` corresponds to one message. There is no /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. - pub fn new(wasm_external_transport: Option) -> Result { + pub fn new(wasm_external_transport: Option) -> Result { let (sender, receiver) = mpsc::channel(16); let (init_sender, init_receiver) = mpsc::unbounded(); diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index c81341e7c5366..9ddd1298f7dd9 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -24,6 +24,7 @@ regex = "1.4.2" rustc-hash = "1.1.0" serde = "1.0.101" serde_json = "1.0.41" +thiserror = "1.0.21" tracing = "0.1.22" tracing-core = "0.1.17" tracing-log = "0.1.1" diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 83b2b1866a518..97e845a07157c 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -46,10 +46,9 @@ pub fn add_directives(directives: &str) { /// Parse `Directive` and add to default directives if successful. /// /// Ensures the supplied directive will be restored when resetting the log filter. -pub(crate) fn parse_default_directive(directive: &str) -> Result { +pub(crate) fn parse_default_directive(directive: &str) -> super::Result { let dir = directive - .parse() - .map_err(|_| format!("Unable to parse directive: {}", directive))?; + .parse()?; add_default_directives(directive); Ok(dir) } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 94631e58345fd..b68b7d1b38b29 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -40,6 +40,27 @@ use tracing_subscriber::{ pub use event_format::*; pub use layers::*; +/// Logging Result typedef. +pub type Result = std::result::Result; + +/// Logging errors. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +#[non_exhaustive] +pub enum Error { + #[error(transparent)] + TelemetryError(#[from] sc_telemetry::Error), + + #[error(transparent)] + SetGlobalDefaultError(#[from] tracing::subscriber::SetGlobalDefaultError), + + #[error(transparent)] + DirectiveParseError(#[from] tracing_subscriber::filter::ParseError), + + #[error(transparent)] + SetLoggerError(#[from] tracing_log::log_tracer::SetLoggerError), +} + macro_rules! disable_log_reloading { ($builder:expr) => {{ let builder = $builder.with_filter_reloading(); @@ -49,28 +70,12 @@ macro_rules! disable_log_reloading { }}; } -macro_rules! set_global_default { - ($subscriber:expr) => {{ - tracing::subscriber::set_global_default($subscriber) - .map_err(|err| format!( - "Registering Substrate tracing subscriber failed: {}!", - err, - )) - }}; -} - /// Common implementation to get the subscriber. fn get_subscriber_internal( pattern: &str, telemetry_external_transport: Option, builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, -) -> std::result::Result< - ( - impl Subscriber + for<'a> LookupSpan<'a>, - TelemetryWorker, - ), - String, -> +) -> Result<(impl Subscriber + for<'a> LookupSpan<'a>, TelemetryWorker)> where N: for<'writer> FormatFields<'writer> + 'static, E: FormatEvent + 'static, @@ -79,16 +84,14 @@ where FmtLayer: layer::Layer + Send + Sync + 'static, { // Accept all valid directives and print invalid ones - fn parse_user_directives(mut env_filter: EnvFilter, dirs: &str) -> std::result::Result { + fn parse_user_directives(mut env_filter: EnvFilter, dirs: &str) -> Result { for dir in dirs.split(',') { env_filter = env_filter.add_directive(parse_default_directive(&dir)?); } Ok(env_filter) } - if let Err(e) = tracing_log::LogTracer::init() { - return Err(format!("Registering Substrate logger failed: {:}!", e)); - } + tracing_log::LogTracer::init()?; // Initialize filter - ensure to use `parse_default_directive` for any defaults to persist // after log filter reloading by RPC @@ -142,7 +145,7 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let (telemetry_layer, telemetry_worker) = sc_telemetry::TelemetryLayer::new(telemetry_external_transport).map_err(|err| format!("Could not initialize telemetry: {}", err))?; + let (telemetry_layer, telemetry_worker) = sc_telemetry::TelemetryLayer::new(telemetry_external_transport)?; let event_format = EventFormat { timer, display_target: !simple, @@ -179,6 +182,7 @@ where Ok((subscriber, telemetry_worker)) } +/// A builder that is used to initialize the global logger. pub struct GlobalLoggerBuilder { pattern: String, profiling: Option<(crate::TracingReceiver, String)>, @@ -187,6 +191,7 @@ pub struct GlobalLoggerBuilder { } impl GlobalLoggerBuilder { + /// Create a new [`GlobalLoggerBuilder`] which can be used to initialize the global logger. pub fn new>(pattern: S) -> Self { Self { pattern: pattern.into(), @@ -196,6 +201,7 @@ impl GlobalLoggerBuilder { } } + /// Set up the profiling. pub fn with_profiling>( &mut self, tracing_receiver: crate::TracingReceiver, @@ -205,11 +211,13 @@ impl GlobalLoggerBuilder { self } + /// Wether or not to disable log reloading. pub fn with_log_reloading(&mut self, enabled: bool) -> &mut Self { self.disable_log_reloading = !enabled; self } + /// Set a custom network transport (used for the telemetry). pub fn with_transport(&mut self, transport: ExtTransport) -> &mut Self { self.telemetry_external_transport = Some(transport); self @@ -218,7 +226,7 @@ impl GlobalLoggerBuilder { /// Initialize the global logger /// /// This sets various global logging and tracing instances and thus may only be called once. - pub fn init(self) -> Result { + pub fn init(self) -> Result { Ok(if let Some((tracing_receiver, profiling_targets)) = self.profiling { if self.disable_log_reloading { let (subscriber, telemetry_worker) = get_subscriber_internal( @@ -228,7 +236,7 @@ impl GlobalLoggerBuilder { )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - set_global_default!(subscriber.with(profiling))?; + tracing::subscriber::set_global_default(subscriber.with(profiling))?; telemetry_worker } else { @@ -239,7 +247,7 @@ impl GlobalLoggerBuilder { )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - set_global_default!(subscriber.with(profiling))?; + tracing::subscriber::set_global_default(subscriber.with(profiling))?; telemetry_worker } @@ -251,7 +259,7 @@ impl GlobalLoggerBuilder { |builder| builder, )?; - set_global_default!(subscriber)?; + tracing::subscriber::set_global_default(subscriber)?; telemetry_worker } else { @@ -261,7 +269,7 @@ impl GlobalLoggerBuilder { |builder| disable_log_reloading!(builder), )?; - set_global_default!(subscriber)?; + tracing::subscriber::set_global_default(subscriber)?; telemetry_worker } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index ba630344760bd..1a3c365381375 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -40,7 +40,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result { +) -> Result> { let transport = ExtTransport::new(ffi::websocket_transport()); let mut logger = GlobalLoggerBuilder::new(pattern); logger.with_transport(transport); From 4e1de2affa06ba8fee29e5330f9067a300f17126 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 14:08:26 +0100 Subject: [PATCH 164/222] CLEANUP --- Cargo.lock | 2 -- client/service/Cargo.toml | 4 ---- 2 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8aad1941ba425..0fe5961b1a6fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7367,9 +7367,7 @@ dependencies = [ "tracing-futures", "tracing-log", "tracing-subscriber", - "wasm-bindgen", "wasm-timer", - "web-sys", ] [[package]] diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 760d1710e5b76..f5cd6ada14d83 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -87,10 +87,6 @@ parity-util-mem = { version = "0.7.0", default-features = false, features = ["pr tempfile = "3.1.0" directories = "3.0.1" -[target.'cfg(target_os = "unknown")'.dependencies] -wasm-bindgen = "0.2.67" -web-sys = "0.3.44" - [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime/" } From 074fa7e4d1eb59170a2ec0763cb6ef18ea052a1a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 14:22:20 +0100 Subject: [PATCH 165/222] CLEANUP --- client/service/src/builder.rs | 4 +++- client/telemetry/src/lib.rs | 11 +++++------ client/telemetry/src/node.rs | 14 ++++++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index d96340a6d442f..f2b7358f7c684 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -718,7 +718,9 @@ fn init_telemetry>( "network_id": network_id.clone() }}; - Some(telemetry_handle.start_telemetry(endpoints, json)) + let obj = serde_json::from_value(json).expect("it's an object; qed"); + + Some(telemetry_handle.start_telemetry(endpoints, obj)) } fn gen_handler( diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index fe6159f9fc8a0..2208233acc74f 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -85,7 +85,7 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -pub(crate) type InitPayload = (Id, TelemetryEndpoints, serde_json::Value, TelemetryConnectionNotifier); +pub(crate) type InitPayload = (Id, TelemetryEndpoints, ConnectionMessage, TelemetryConnectionNotifier); /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// @@ -158,7 +158,7 @@ impl TelemetryWorker { } = self; let mut node_map: HashMap> = HashMap::new(); - let mut connection_messages: HashMap> = HashMap::new(); + let mut connection_messages: HashMap> = HashMap::new(); let mut telemetry_connection_notifier: HashMap> = HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); @@ -172,12 +172,11 @@ impl TelemetryWorker { node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); - let mut json = connection_message.clone(); - let obj = json.as_object_mut().expect("todo"); + let mut obj = connection_message.clone(); obj.insert("msg".into(), "system.connected".into()); obj.insert("id".into(), id.into_u64().into()); connection_messages.entry(addr.clone()).or_insert_with(Vec::new) - .push(json); + .push(obj); telemetry_connection_notifier.entry(addr.clone()).or_insert_with(Vec::new) .push(connection_sink.clone()); } @@ -266,7 +265,7 @@ impl TelemetryHandle { pub fn start_telemetry( &mut self, endpoints: TelemetryEndpoints, - connection_message: serde_json::Value, + connection_message: ConnectionMessage, ) -> TelemetryConnectionNotifier { let connection_sink = TelemetryConnectionNotifier::default(); let span = tracing::info_span!(TELEMETRY_LOG_SPAN); diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 0858ba80659f9..7b3fbaef0a3e0 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -24,6 +24,8 @@ use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; use crate::TelemetryConnectionNotifier; +pub(crate) type ConnectionMessage = serde_json::Map; + /// Handler for a single telemetry node. /// /// This is a wrapper `Sink` around a network `Sink` with 3 particularities: @@ -44,7 +46,7 @@ pub(crate) struct Node { /// Transport used to establish new connections. transport: TTrans, /// Messages that are sent when the connection (re-)establishes. - connection_messages: Vec, + connection_messages: Vec, /// Notifier for when the connection (re-)establishes. telemetry_connection_notifier: Vec, } @@ -82,7 +84,7 @@ impl Node { pub(crate) fn new( transport: TTrans, addr: Multiaddr, - connection_messages: Vec, + connection_messages: Vec, telemetry_connection_notifier: Vec, ) -> Self { Node { @@ -170,13 +172,9 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, connection_sink.fire(); } - fn generate_message(mut json: serde_json::Value) -> Result, String> { - let obj = json.as_object_mut() - .ok_or_else(|| { - "Invalid JSON message: it must be an object".to_owned() - })?; + fn generate_message(mut obj: ConnectionMessage) -> Result, String> { obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); - serde_json::to_vec(obj) + serde_json::to_vec(&obj) .map_err(|err| format!("Could not serialize JSON message: {}", err)) } From 70e1ac5427ec267ae60ee9148f644463423e298e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 14:27:16 +0100 Subject: [PATCH 166/222] CLEANUP --- client/cli/src/runner.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 7a77f8c4907f3..75be118279169 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -27,7 +27,6 @@ use log::info; use sc_service::{Configuration, TaskType, TaskManager}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; -use std::sync::Arc; #[cfg(target_family = "unix")] async fn main(func: F) -> std::result::Result<(), Box> @@ -113,7 +112,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetry_worker: Arc, + telemetry_worker: sc_telemetry::TelemetryWorker, phantom: PhantomData, } @@ -135,7 +134,6 @@ impl Runner { .map(drop), } }; - let telemetry_worker = Arc::new(telemetry_worker); Ok(Runner { config: command.create_configuration( @@ -190,12 +188,7 @@ impl Runner { ) -> Result<()> { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; - let telemetry_worker = Arc::try_unwrap(self.telemetry_worker) - .map_err(|_| String::from( - "Could not initialize telemetry_worker! \ - Maybe some node Configuration are pending?" - ))?; - task_manager.spawn_handle().spawn("telemetry_worker", telemetry_worker.run()); + task_manager.spawn_handle().spawn("telemetry_worker", self.telemetry_worker.run()); let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); self.tokio_runtime.block_on(task_manager.clean_shutdown()); res.map_err(|e| e.to_string().into()) From 6130ee3ee367f450eb8c8a9a195ebe0fd68513ab Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 15:54:48 +0100 Subject: [PATCH 167/222] Refactor to remove Arc Mutex --- bin/node/cli/src/service.rs | 4 +-- client/telemetry/src/lib.rs | 60 +++++++++++++++++++----------------- client/telemetry/src/node.rs | 10 +++--- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index afb7e76b7c4e2..cec5fe59094c3 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -350,7 +350,7 @@ pub fn new_full(config: Configuration) } pub fn new_light_base(mut config: Configuration) -> Result<( - TaskManager, RpcHandlers, TelemetryConnectionNotifier, Arc, + TaskManager, RpcHandlers, Option, Arc, Arc::Hash>>, Arc>> ), ServiceError> { @@ -436,7 +436,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<( task_manager: &mut task_manager, })?; - Ok((task_manager, rpc_handlers, telemetry_telemetry_connection_notifier.unwrap_or_default(), client, network, transaction_pool)) + Ok((task_manager, rpc_handlers, telemetry_telemetry_connection_notifier, client, network, transaction_pool)) } /// Builds a new service for a light client. diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2208233acc74f..bd252c9037480 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -46,13 +46,11 @@ use libp2p::{ use log::{error, warn}; use std::{ collections::{HashMap, HashSet}, - sync::Arc, time::Duration, }; use wasm_timer::Instant; use tracing::Id; -use parking_lot::Mutex; -use sp_utils::{mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; +use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; @@ -85,7 +83,7 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -pub(crate) type InitPayload = (Id, TelemetryEndpoints, ConnectionMessage, TelemetryConnectionNotifier); +pub(crate) type InitPayload = (Id, TelemetryEndpoints, ConnectionMessage, mpsc::UnboundedReceiver); /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// @@ -153,21 +151,24 @@ impl TelemetryWorker { receiver, sender: _sender, mut init_receiver, - init_sender, + init_sender: _init_sender, transport, } = self; let mut node_map: HashMap> = HashMap::new(); let mut connection_messages: HashMap> = HashMap::new(); - let mut telemetry_connection_notifier: HashMap> = HashMap::new(); + let mut connection_notifiers: HashMap> = HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes - init_sender.close_channel(); - while let Some((id, endpoints, connection_message, connection_sink)) = init_receiver.next().await + init_receiver.close(); + while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = init_receiver.next().await { let endpoints = endpoints.0; + connection_notifiers_rx.close(); + let connection_notifier_senders: Vec<_> = connection_notifiers_rx.collect().await; + for (addr, verbosity) in endpoints { node_map.entry(id.clone()).or_insert_with(Vec::new) .push((verbosity, addr.clone())); @@ -177,8 +178,8 @@ impl TelemetryWorker { obj.insert("id".into(), id.into_u64().into()); connection_messages.entry(addr.clone()).or_insert_with(Vec::new) .push(obj); - telemetry_connection_notifier.entry(addr.clone()).or_insert_with(Vec::new) - .push(connection_sink.clone()); + connection_notifiers.entry(addr.clone()).or_insert_with(Vec::new) + .extend(connection_notifier_senders.clone()); } } @@ -188,9 +189,9 @@ impl TelemetryWorker { .map(|addr| { let connection_messages = connection_messages.remove(addr) .expect("there is a node for every connection message; qed"); - let telemetry_connection_notifier = telemetry_connection_notifier.remove(addr) - .expect("there is a node for every connection sink; qed"); - let node = Node::new(transport.clone(), addr.clone(), connection_messages, telemetry_connection_notifier); + let connection_notifiers = connection_notifiers.remove(addr) + .expect("there is a node for every connection notifier; qed"); + let node = Node::new(transport.clone(), addr.clone(), connection_messages, connection_notifiers); (addr.clone(), node) }) .collect(); @@ -267,19 +268,21 @@ impl TelemetryHandle { endpoints: TelemetryEndpoints, connection_message: ConnectionMessage, ) -> TelemetryConnectionNotifier { - let connection_sink = TelemetryConnectionNotifier::default(); let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + let (sender, receiver) = mpsc::unbounded(); + let connection_notifier = TelemetryConnectionNotifier(sender); match span.id() { Some(id) => { match self.0.unbounded_send( - (id.clone(), endpoints, connection_message, connection_sink.clone()), + (id.clone(), endpoints, connection_message, receiver), ) { Ok(()) => tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)), Err(err) => error!( target: "telemetry", - "Could not initialize telemetry: {}", + "Could not initialize telemetry: \ + the telemetry is probably already running: {}", err, ), } @@ -290,27 +293,28 @@ impl TelemetryHandle { ), } - connection_sink + connection_notifier } } /// Used to create a stream of events with only one event: when a telemetry connection /// (re-)establishes. -#[derive(Default, Clone, Debug)] -pub struct TelemetryConnectionNotifier(Arc>>>); +#[derive(Clone, Debug)] +pub struct TelemetryConnectionNotifier(mpsc::UnboundedSender); impl TelemetryConnectionNotifier { /// Get event stream for telemetry connection established events. pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { - let (sink, stream) = tracing_unbounded("mpsc_telemetry_on_connect"); - self.0.lock().push(sink); - stream - } - - pub(crate) fn fire(&self) { - self.0.lock().retain(|sink| { - sink.unbounded_send(()).is_ok() - }); + let (sender, receiver) = tracing_unbounded("mpsc_telemetry_on_connect"); + if let Err(err) = self.0.unbounded_send(sender) { + error!( + target: "telemetry", + "Could not create a telemetry connection notifier: \ + the telemetry is probably already running: {}", + err, + ); + } + receiver } } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 7b3fbaef0a3e0..b78c5e634a77b 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -22,9 +22,9 @@ use libp2p::Multiaddr; use libp2p::core::transport::Transport; use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; -use crate::TelemetryConnectionNotifier; pub(crate) type ConnectionMessage = serde_json::Map; +pub(crate) type ConnectionNotifierSender = sp_utils::mpsc::TracingUnboundedSender<()>; /// Handler for a single telemetry node. /// @@ -48,7 +48,7 @@ pub(crate) struct Node { /// Messages that are sent when the connection (re-)establishes. connection_messages: Vec, /// Notifier for when the connection (re-)establishes. - telemetry_connection_notifier: Vec, + telemetry_connection_notifier: Vec, } enum NodeSocket { @@ -85,7 +85,7 @@ impl Node { transport: TTrans, addr: Multiaddr, connection_messages: Vec, - telemetry_connection_notifier: Vec, + telemetry_connection_notifier: Vec, ) -> Self { Node { addr, @@ -168,8 +168,8 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Ready(Ok(sink)) => { log::debug!(target: "telemetry", "✅ Connected to {}", self.addr); - for connection_sink in self.telemetry_connection_notifier.iter() { - connection_sink.fire(); + for sender in self.telemetry_connection_notifier.iter_mut() { + let _ = sender.send(()); } fn generate_message(mut obj: ConnectionMessage) -> Result, String> { From 7a3fb6e877836cbb229e6426a3b6d4535c374333 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 16:01:42 +0100 Subject: [PATCH 168/222] WIP --- client/telemetry/src/dispatcher.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs index c5a64ac40d818..66ba138ad3755 100644 --- a/client/telemetry/src/dispatcher.rs +++ b/client/telemetry/src/dispatcher.rs @@ -48,6 +48,18 @@ impl Dispatcher { mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { + if let Some(addr) = self.flush_node.take() { + let node = self.pool.get_mut(&addr).expect("we added the address ourselves; qed"); + match node.poll_flush_unpin(cx) { + Poll::Ready(Ok(())) => {}, + Poll::Ready(Err(x)) => match x {}, + Poll::Pending => { + self.flush_node = Some(addr); + return Poll::Pending; + }, + } + } + if let Some((addr, message)) = self.item.take() { let node = if let Some(node) = self.pool.get_mut(&addr) { node @@ -112,18 +124,6 @@ impl Sink<(Multiaddr, String)> for Dispatcher } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if let Some(addr) = self.flush_node.take() { - let node = self.pool.get_mut(&addr).expect("we added the address ourselves; qed"); - match node.poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => return Poll::Ready(Ok(())), - Poll::Ready(Err(x)) => match x {}, - Poll::Pending => { - self.flush_node = Some(addr); - return Poll::Pending; - }, - } - } - self.try_empty_buffer(cx) } From 1c5860d833b172e2c02b957d2eee6642049fa21d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 16:06:23 +0100 Subject: [PATCH 169/222] formatting --- client/telemetry/src/dispatcher.rs | 34 ++--- client/telemetry/src/endpoints.rs | 23 ++-- client/telemetry/src/layer.rs | 27 ++-- client/telemetry/src/lib.rs | 150 ++++++++++++--------- client/telemetry/src/node.rs | 119 ++++++++--------- client/telemetry/src/transport.rs | 56 ++++---- client/tracing/src/logging/directives.rs | 36 +++-- client/tracing/src/logging/mod.rs | 160 ++++++++++++----------- 8 files changed, 336 insertions(+), 269 deletions(-) diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs index 66ba138ad3755..02bec8dc4834f 100644 --- a/client/telemetry/src/dispatcher.rs +++ b/client/telemetry/src/dispatcher.rs @@ -16,14 +16,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::node::{Infallible, Node}; +use crate::transport::WsTrans; use futures::prelude::*; +use libp2p::Multiaddr; use std::collections::HashMap; -use crate::node::{Node, Infallible}; -use crate::transport::WsTrans; use std::iter::FromIterator; -use libp2p::Multiaddr; -use std::task::{Poll, Context}; use std::pin::Pin; +use std::task::{Context, Poll}; #[derive(Debug)] pub(crate) struct Dispatcher { @@ -33,7 +33,7 @@ pub(crate) struct Dispatcher { } impl FromIterator<(Multiaddr, Node)> for Dispatcher { - fn from_iter)>>(iter: I) -> Self { + fn from_iter)>>(iter: I) -> Self { let pool: HashMap<_, _> = FromIterator::from_iter(iter); Dispatcher { pool, @@ -49,14 +49,17 @@ impl Dispatcher { cx: &mut Context<'_>, ) -> Poll> { if let Some(addr) = self.flush_node.take() { - let node = self.pool.get_mut(&addr).expect("we added the address ourselves; qed"); + let node = self + .pool + .get_mut(&addr) + .expect("we added the address ourselves; qed"); match node.poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => {}, + Poll::Ready(Ok(())) => {} Poll::Ready(Err(x)) => match x {}, Poll::Pending => { self.flush_node = Some(addr); return Poll::Pending; - }, + } } } @@ -74,7 +77,7 @@ impl Dispatcher { }; match node.poll_ready_unpin(cx) { - Poll::Ready(Ok(())) => {}, + Poll::Ready(Ok(())) => {} Poll::Ready(Err(x)) => match x {}, Poll::Pending => { self.item = Some((addr, message)); @@ -83,17 +86,17 @@ impl Dispatcher { } match node.start_send_unpin(message) { - Ok(()) => {}, + Ok(()) => {} Err(x) => match x {}, } match node.poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => {}, + Poll::Ready(Ok(())) => {} Poll::Ready(Err(x)) => match x {}, Poll::Pending => { self.flush_node = Some(addr); return Poll::Pending; - }, + } } } @@ -101,8 +104,7 @@ impl Dispatcher { } } -impl Sink<(Multiaddr, String)> for Dispatcher -{ +impl Sink<(Multiaddr, String)> for Dispatcher { type Error = Infallible; fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { @@ -132,11 +134,11 @@ impl Sink<(Multiaddr, String)> for Dispatcher for (addr, mut node) in self.pool.drain() { match node.poll_close_unpin(cx) { - Poll::Ready(Ok(())) => {}, + Poll::Ready(Ok(())) => {} Poll::Ready(Err(x)) => match x {}, Poll::Pending => { new_pool.insert(addr, node); - }, + } } } diff --git a/client/telemetry/src/endpoints.rs b/client/telemetry/src/endpoints.rs index 5d7773e2dd63c..941bbdebd6af9 100644 --- a/client/telemetry/src/endpoints.rs +++ b/client/telemetry/src/endpoints.rs @@ -16,9 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use libp2p::{ - Multiaddr, -}; +use libp2p::Multiaddr; use serde::{Deserialize, Deserializer, Serialize}; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the @@ -27,25 +25,30 @@ use serde::{Deserialize, Deserializer, Serialize}; /// The URL string can be either a URL or a multiaddress. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct TelemetryEndpoints( - #[serde(deserialize_with = "url_or_multiaddr_deser")] - pub(crate) Vec<(Multiaddr, u8)> + #[serde(deserialize_with = "url_or_multiaddr_deser")] pub(crate) Vec<(Multiaddr, u8)>, ); /// Custom deserializer for TelemetryEndpoints, used to convert urls or multiaddr to multiaddr. fn url_or_multiaddr_deser<'de, D>(deserializer: D) -> Result, D::Error> - where D: Deserializer<'de> +where + D: Deserializer<'de>, { Vec::<(String, u8)>::deserialize(deserializer)? .iter() - .map(|e| Ok((url_to_multiaddr(&e.0) - .map_err(serde::de::Error::custom)?, e.1))) + .map(|e| { + Ok(( + url_to_multiaddr(&e.0).map_err(serde::de::Error::custom)?, + e.1, + )) + }) .collect() } impl TelemetryEndpoints { /// Create a `TelemetryEndpoints` based on a list of `(String, u8)`. pub fn new(endpoints: Vec<(String, u8)>) -> Result { - let endpoints: Result, libp2p::multiaddr::Error> = endpoints.iter() + let endpoints: Result, libp2p::multiaddr::Error> = endpoints + .iter() .map(|e| Ok((url_to_multiaddr(&e.0)?, e.1))) .collect(); endpoints.map(Self) @@ -69,7 +72,7 @@ fn url_to_multiaddr(url: &str) -> Result { // If not, try the `ws://path/url` format. if let Ok(ma) = libp2p::multiaddr::from_url(url) { - return Ok(ma) + return Ok(ma); } // If we have no clue about the format of that string, assume that we were expecting a diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 4409db0db9ff6..23868337ea03d 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,13 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::TelemetryWorker; use futures::channel::mpsc; +use libp2p::wasm_ext::ExtTransport; use parking_lot::Mutex; use std::convert::TryInto; use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; -use libp2p::wasm_ext::ExtTransport; -use crate::TelemetryWorker; /// Span name used to report the telemetry. pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; @@ -33,7 +33,9 @@ pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. - pub fn new(telemetry_external_transport: Option) -> super::Result<(Self, TelemetryWorker)> { + pub fn new( + telemetry_external_transport: Option, + ) -> super::Result<(Self, TelemetryWorker)> { let worker = TelemetryWorker::new(telemetry_external_transport)?; let sender = worker.sender(); Ok((Self(Mutex::new(sender)), worker)) @@ -67,13 +69,18 @@ where .. } = attrs { - if self.0.lock().try_send(( - id, - verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )).is_err() { + if self + .0 + .lock() + .try_send(( + id, + verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )) + .is_err() + { eprintln!("Telemetry buffer overflowed!"); } } else { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index bd252c9037480..16db072f71cf0 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -40,33 +40,31 @@ #![warn(missing_docs)] use futures::{channel::mpsc, prelude::*}; -use libp2p::{ - wasm_ext, Multiaddr, -}; +use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; +use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use std::{ collections::{HashMap, HashSet}, time::Duration, }; -use wasm_timer::Instant; use tracing::Id; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; +use wasm_timer::Instant; pub use chrono; pub use libp2p::wasm_ext::ExtTransport; pub use serde_json; pub use tracing; +mod dispatcher; +mod endpoints; mod layer; mod node; -mod dispatcher; mod transport; -mod endpoints; -pub use layer::*; -use node::*; use dispatcher::*; pub use endpoints::*; +pub use layer::*; +use node::*; use transport::*; /// Substrate DEBUG log level. @@ -83,7 +81,12 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -pub(crate) type InitPayload = (Id, TelemetryEndpoints, ConnectionMessage, mpsc::UnboundedReceiver); +pub(crate) type InitPayload = ( + Id, + TelemetryEndpoints, + ConnectionMessage, + mpsc::UnboundedReceiver, +); /// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. /// @@ -157,12 +160,14 @@ impl TelemetryWorker { let mut node_map: HashMap> = HashMap::new(); let mut connection_messages: HashMap> = HashMap::new(); - let mut connection_notifiers: HashMap> = HashMap::new(); + let mut connection_notifiers: HashMap> = + HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes init_receiver.close(); - while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = init_receiver.next().await + while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = + init_receiver.next().await { let endpoints = endpoints.0; @@ -170,31 +175,43 @@ impl TelemetryWorker { let connection_notifier_senders: Vec<_> = connection_notifiers_rx.collect().await; for (addr, verbosity) in endpoints { - node_map.entry(id.clone()).or_insert_with(Vec::new) + node_map + .entry(id.clone()) + .or_insert_with(Vec::new) .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); let mut obj = connection_message.clone(); obj.insert("msg".into(), "system.connected".into()); obj.insert("id".into(), id.into_u64().into()); - connection_messages.entry(addr.clone()).or_insert_with(Vec::new) + connection_messages + .entry(addr.clone()) + .or_insert_with(Vec::new) .push(obj); - connection_notifiers.entry(addr.clone()).or_insert_with(Vec::new) + connection_notifiers + .entry(addr.clone()) + .or_insert_with(Vec::new) .extend(connection_notifier_senders.clone()); } } - let mut node_pool: Dispatcher = - existing_nodes - .iter() - .map(|addr| { - let connection_messages = connection_messages.remove(addr) - .expect("there is a node for every connection message; qed"); - let connection_notifiers = connection_notifiers.remove(addr) - .expect("there is a node for every connection notifier; qed"); - let node = Node::new(transport.clone(), addr.clone(), connection_messages, connection_notifiers); - (addr.clone(), node) - }) - .collect(); + let mut node_pool: Dispatcher = existing_nodes + .iter() + .map(|addr| { + let connection_messages = connection_messages + .remove(addr) + .expect("there is a node for every connection message; qed"); + let connection_notifiers = connection_notifiers + .remove(addr) + .expect("there is a node for every connection notifier; qed"); + let node = Node::new( + transport.clone(), + addr.clone(), + connection_messages, + connection_notifiers, + ); + (addr.clone(), node) + }) + .collect(); let _ = receiver .filter_map(|(id, verbosity, message): (Id, u8, String)| { @@ -210,32 +227,34 @@ impl TelemetryWorker { future::ready(None) } }) - .flat_map(|(verbosity, message, nodes): (u8, String, &Vec<(u8, Multiaddr)>)| { - let mut to_send = Vec::with_capacity(nodes.len()); - let before = Instant::now(); - - for (node_max_verbosity, addr) in nodes { - if verbosity > *node_max_verbosity { - log::trace!( + .flat_map( + |(verbosity, message, nodes): (u8, String, &Vec<(u8, Multiaddr)>)| { + let mut to_send = Vec::with_capacity(nodes.len()); + let before = Instant::now(); + + for (node_max_verbosity, addr) in nodes { + if verbosity > *node_max_verbosity { + log::trace!( target: "telemetry", "Skipping {} for log entry with verbosity {:?}", addr, verbosity); - continue; - } + continue; + } - to_send.push((addr.clone(), message.clone())); - } + to_send.push((addr.clone(), message.clone())); + } - if before.elapsed() > Duration::from_millis(200) { - log::warn!( - target: "telemetry", - "Processing one telemetry message took more than 200ms", - ); - } + if before.elapsed() > Duration::from_millis(200) { + log::warn!( + target: "telemetry", + "Processing one telemetry message took more than 200ms", + ); + } - stream::iter(to_send) - }) + stream::iter(to_send) + }, + ) .map(|x| Ok(x)) .boxed() .forward(&mut node_pool) @@ -274,11 +293,11 @@ impl TelemetryHandle { match span.id() { Some(id) => { - match self.0.unbounded_send( - (id.clone(), endpoints, connection_message, receiver), - ) { - Ok(()) => - tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)), + match self + .0 + .unbounded_send((id.clone(), endpoints, connection_message, receiver)) + { + Ok(()) => tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)), Err(err) => error!( target: "telemetry", "Could not initialize telemetry: \ @@ -286,7 +305,7 @@ impl TelemetryHandle { err, ), } - }, + } None => error!( target: "telemetry", "Could not initialize telemetry: the span could not be entered", @@ -387,31 +406,44 @@ macro_rules! format_fields_to_json { #[cfg(test)] mod telemetry_endpoints_tests { - use libp2p::Multiaddr; - use super::TelemetryEndpoints; use super::url_to_multiaddr; + use super::TelemetryEndpoints; + use libp2p::Multiaddr; #[test] fn valid_endpoints() { - let endp = vec![("wss://telemetry.polkadot.io/submit/".into(), 3), ("/ip4/80.123.90.4/tcp/5432".into(), 4)]; - let telem = TelemetryEndpoints::new(endp.clone()).expect("Telemetry endpoint should be valid"); + let endp = vec![ + ("wss://telemetry.polkadot.io/submit/".into(), 3), + ("/ip4/80.123.90.4/tcp/5432".into(), 4), + ]; + let telem = + TelemetryEndpoints::new(endp.clone()).expect("Telemetry endpoint should be valid"); let mut res: Vec<(Multiaddr, u8)> = vec![]; for (a, b) in endp.iter() { - res.push((url_to_multiaddr(a).expect("provided url should be valid"), *b)) + res.push(( + url_to_multiaddr(a).expect("provided url should be valid"), + *b, + )) } assert_eq!(telem.0, res); } #[test] fn invalid_endpoints() { - let endp = vec![("/ip4/...80.123.90.4/tcp/5432".into(), 3), ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4)]; + let endp = vec![ + ("/ip4/...80.123.90.4/tcp/5432".into(), 3), + ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), + ]; let telem = TelemetryEndpoints::new(endp); assert!(telem.is_err()); } #[test] fn valid_and_invalid_endpoints() { - let endp = vec![("/ip4/80.123.90.4/tcp/5432".into(), 3), ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4)]; + let endp = vec![ + ("/ip4/80.123.90.4/tcp/5432".into(), 3), + ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), + ]; let telem = TelemetryEndpoints::new(endp); assert!(telem.is_err()); } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index b78c5e634a77b..11a0ae080954d 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -18,8 +18,8 @@ use futures::prelude::*; use futures_timer::Delay; -use libp2p::Multiaddr; use libp2p::core::transport::Transport; +use libp2p::Multiaddr; use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; @@ -98,11 +98,12 @@ impl Node { } impl Node -where TTrans: Clone + Unpin, TTrans::Dial: Unpin, - TTrans::Output: Sink, Error = TSinkErr> - + Stream, TSinkErr>> - + Unpin, - TSinkErr: fmt::Debug +where + TTrans: Clone + Unpin, + TTrans::Dial: Unpin, + TTrans::Output: + Sink, Error = TSinkErr> + Stream, TSinkErr>> + Unpin, + TSinkErr: fmt::Debug, { // NOTE: this code has been inspired from `Buffer` (`futures_util::sink::Buffer`). // https://docs.rs/futures-util/0.3.8/src/futures_util/sink/buffer.rs.html#32 @@ -124,11 +125,12 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, pub(crate) enum Infallible {} impl Sink for Node -where TTrans: Clone + Unpin, TTrans::Dial: Unpin, - TTrans::Output: Sink, Error = TSinkErr> - + Stream, TSinkErr>> - + Unpin, - TSinkErr: fmt::Debug +where + TTrans: Clone + Unpin, + TTrans::Dial: Unpin, + TTrans::Output: + Sink, Error = TSinkErr> + Stream, TSinkErr>> + Unpin, + TSinkErr: fmt::Debug, { type Error = Infallible; @@ -136,34 +138,32 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); self.socket = loop { match socket { - NodeSocket::Connected(mut conn) => { - match conn.sink.poll_ready_unpin(cx) { - Poll::Ready(Ok(())) => { - match self.as_mut().try_send_connection_messages(cx, &mut conn) { - Poll::Ready(Err(err)) => { - log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); - socket = NodeSocket::wait_reconnect(); - }, - Poll::Ready(Ok(())) => { - self.socket = NodeSocket::Connected(conn); - return Poll::Ready(Ok(())); - }, - Poll::Pending => { - self.socket = NodeSocket::Connected(conn); - return Poll::Pending; - }, + NodeSocket::Connected(mut conn) => match conn.sink.poll_ready_unpin(cx) { + Poll::Ready(Ok(())) => { + match self.as_mut().try_send_connection_messages(cx, &mut conn) { + Poll::Ready(Err(err)) => { + log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); + socket = NodeSocket::wait_reconnect(); + } + Poll::Ready(Ok(())) => { + self.socket = NodeSocket::Connected(conn); + return Poll::Ready(Ok(())); } - }, - Poll::Ready(Err(err)) => { - log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); - socket = NodeSocket::wait_reconnect(); - }, - Poll::Pending => { - self.socket = NodeSocket::Connected(conn); - return Poll::Pending; - }, + Poll::Pending => { + self.socket = NodeSocket::Connected(conn); + return Poll::Pending; + } + } } - } + Poll::Ready(Err(err)) => { + log::warn!(target: "telemetry", "⚠️ Disconnected from {}: {:?}", self.addr, err); + socket = NodeSocket::wait_reconnect(); + } + Poll::Pending => { + self.socket = NodeSocket::Connected(conn); + return Poll::Pending; + } + }, NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { Poll::Ready(Ok(sink)) => { log::debug!(target: "telemetry", "✅ Connected to {}", self.addr); @@ -178,7 +178,8 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, .map_err(|err| format!("Could not serialize JSON message: {}", err)) } - let buf = self.connection_messages + let buf = self + .connection_messages .iter() .cloned() .filter_map(|json| match generate_message(json) { @@ -191,21 +192,18 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, err, ); None - }, + } }) .collect(); - socket = NodeSocket::Connected(NodeSocketConnected { - sink, - buf, - }); - }, + socket = NodeSocket::Connected(NodeSocketConnected { sink, buf }); + } Poll::Pending => break NodeSocket::Dialing(s), Poll::Ready(Err(err)) => { log::warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); } - } + }, NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { Ok(d) => { log::debug!(target: "telemetry", "Started dialing {}", self.addr); @@ -215,16 +213,17 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, log::warn!(target: "telemetry", "❌ Error while dialing {}: {:?}", self.addr, err); socket = NodeSocket::wait_reconnect(); } - } - NodeSocket::WaitingReconnect(mut s) => + }, + NodeSocket::WaitingReconnect(mut s) => { if let Poll::Ready(_) = Future::poll(Pin::new(&mut s), cx) { socket = NodeSocket::ReconnectNow; } else { - break NodeSocket::WaitingReconnect(s) + break NodeSocket::WaitingReconnect(s); } + } NodeSocket::Poisoned => { log::error!(target: "telemetry", "‼️ Poisoned connection with {}", self.addr); - break NodeSocket::Poisoned + break NodeSocket::Poisoned; } } }; @@ -236,14 +235,14 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, match &mut self.socket { NodeSocket::Connected(conn) => { let _ = conn.sink.start_send_unpin(item.into()).expect("boo"); - }, + } _socket => { log::trace!( target: "telemetry", "Message has been discarded: {}", item, ); - }, + } } Ok(()) } @@ -254,7 +253,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, Poll::Ready(Err(_)) => { self.socket = NodeSocket::wait_reconnect(); Poll::Ready(Ok(())) - }, + } Poll::Ready(Ok(())) => Poll::Ready(Ok(())), Poll::Pending => Poll::Pending, }, @@ -273,14 +272,12 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, impl fmt::Debug for NodeSocket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use NodeSocket::*; - f.write_str( - match self { - Connected(_) => "Connected", - Dialing(_) => "Dialing", - ReconnectNow => "ReconnectNow", - WaitingReconnect(_) => "WaitingReconnect", - Poisoned => "Poisoned", - }, - ) + f.write_str(match self { + Connected(_) => "Connected", + Dialing(_) => "Dialing", + ReconnectNow => "ReconnectNow", + WaitingReconnect(_) => "WaitingReconnect", + Poisoned => "Poisoned", + }) } } diff --git a/client/telemetry/src/transport.rs b/client/telemetry/src/transport.rs index d1767cf567316..13a9029e158c0 100644 --- a/client/telemetry/src/transport.rs +++ b/client/telemetry/src/transport.rs @@ -16,13 +16,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use futures::{prelude::*, task::{Context, Poll}, ready}; -use std::pin::Pin; -use std::io; +use futures::{ + prelude::*, + ready, + task::{Context, Poll}, +}; use libp2p::{ - core::transport::{OptionalTransport, timeout::TransportTimeout}, + core::transport::{timeout::TransportTimeout, OptionalTransport}, wasm_ext, Transport, }; +use std::io; +use std::pin::Pin; use std::time::Duration; /// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP @@ -34,8 +38,9 @@ pub(crate) fn initialize_transport( ) -> Result { let transport = match wasm_external_transport.clone() { Some(t) => OptionalTransport::some(t), - None => OptionalTransport::none() - }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); + None => OptionalTransport::none(), + } + .map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); // The main transport is the `wasm_external_transport`, but if we're on desktop we add // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass @@ -43,17 +48,16 @@ pub(crate) fn initialize_transport( #[cfg(not(target_os = "unknown"))] let transport = transport.or_transport({ let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; - libp2p::websocket::framed::WsConfig::new(inner) - .and_then(|connec, _| { - let connec = connec - .with(|item| { - let item = libp2p::websocket::framed::OutgoingData::Binary(item); - future::ready(Ok::<_, io::Error>(item)) - }) - .try_filter(|item| future::ready(item.is_data())) - .map_ok(|data| data.into_bytes()); - future::ready(Ok::<_, io::Error>(connec)) - }) + libp2p::websocket::framed::WsConfig::new(inner).and_then(|connec, _| { + let connec = connec + .with(|item| { + let item = libp2p::websocket::framed::OutgoingData::Binary(item); + future::ready(Ok::<_, io::Error>(item)) + }) + .try_filter(|item| future::ready(item.is_data())) + .map_ok(|data| data.into_bytes()); + future::ready(Ok::<_, io::Error>(connec)) + }) }); Ok(TransportTimeout::new( @@ -63,8 +67,9 @@ pub(crate) fn initialize_transport( .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); Box::pin(out) as Pin> }), - CONNECT_TIMEOUT - ).boxed()) + CONNECT_TIMEOUT, + ) + .boxed()) } /// A trait that implements `Stream` and `Sink`. @@ -73,11 +78,11 @@ impl, I> StreamAndSink for T {} /// A type alias for the WebSocket transport. pub(crate) type WsTrans = libp2p::core::transport::Boxed< - Pin, - Item = Result, io::Error>, - Error = io::Error - > + Send>> + Pin< + Box< + dyn StreamAndSink, Item = Result, io::Error>, Error = io::Error> + Send, + >, + >, >; /// Wraps around an `AsyncWrite` and implements `Sink`. Guarantees that each item being sent maps @@ -105,7 +110,7 @@ impl Stream for StreamSink { Ok(n) => { buf.truncate(n); Poll::Ready(Some(Ok(buf))) - }, + } Err(err) => Poll::Ready(Some(Err(err))), } } @@ -156,4 +161,3 @@ impl Sink> for StreamSink { AsyncWrite::poll_close(this.0, cx) } } - diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 97e845a07157c..a958413083285 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -17,8 +17,8 @@ use once_cell::sync::OnceCell; use parking_lot::Mutex; use tracing_subscriber::{ - fmt::time::ChronoLocal, Registry, EnvFilter, reload::Handle, filter::Directive, - fmt as tracing_fmt, layer, + filter::Directive, fmt as tracing_fmt, fmt::time::ChronoLocal, layer, reload::Handle, + EnvFilter, Registry, }; // Handle to reload the tracing log filter @@ -34,21 +34,26 @@ static CURRENT_DIRECTIVES: OnceCell>> = OnceCell::new(); /// /// `sync=debug,state=trace` pub(crate) fn add_default_directives(directives: &str) { - DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); + DEFAULT_DIRECTIVES + .get_or_init(|| Mutex::new(Vec::new())) + .lock() + .push(directives.to_owned()); add_directives(directives); } /// Add directives to current directives pub fn add_directives(directives: &str) { - CURRENT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().push(directives.to_owned()); + CURRENT_DIRECTIVES + .get_or_init(|| Mutex::new(Vec::new())) + .lock() + .push(directives.to_owned()); } /// Parse `Directive` and add to default directives if successful. /// /// Ensures the supplied directive will be restored when resetting the log filter. pub(crate) fn parse_default_directive(directive: &str) -> super::Result { - let dir = directive - .parse()?; + let dir = directive.parse()?; add_default_directives(directive); Ok(dir) } @@ -58,7 +63,12 @@ pub fn reload_filter() -> Result<(), String> { let mut env_filter = EnvFilter::default(); if let Some(current_directives) = CURRENT_DIRECTIVES.get() { // Use join and then split in case any directives added together - for directive in current_directives.lock().join(",").split(',').map(|d| d.parse()) { + for directive in current_directives + .lock() + .join(",") + .split(',') + .map(|d| d.parse()) + { match directive { Ok(dir) => env_filter = env_filter.add_directive(dir), Err(invalid_directive) => { @@ -77,7 +87,8 @@ pub fn reload_filter() -> Result<(), String> { .expect("provided directive is valid"), ); log::debug!(target: "tracing", "Reloading log filter with: {}", env_filter); - FILTER_RELOAD_HANDLE.get() + FILTER_RELOAD_HANDLE + .get() .ok_or("No reload handle present".to_string())? .reload(env_filter) .map_err(|e| format!("{}", e)) @@ -88,8 +99,11 @@ pub fn reload_filter() -> Result<(), String> { /// Includes substrate defaults and CLI supplied directives. pub fn reset_log_filter() -> Result<(), String> { *CURRENT_DIRECTIVES - .get_or_init(|| Mutex::new(Vec::new())).lock() = - DEFAULT_DIRECTIVES.get_or_init(|| Mutex::new(Vec::new())).lock().clone(); + .get_or_init(|| Mutex::new(Vec::new())) + .lock() = DEFAULT_DIRECTIVES + .get_or_init(|| Mutex::new(Vec::new())) + .lock() + .clone(); reload_filter() } @@ -103,5 +117,5 @@ pub(crate) fn set_reload_handle(handle: Handle) { type SCSubscriber< N = tracing_fmt::format::DefaultFields, E = crate::logging::EventFormat, - W = fn() -> std::io::Stderr + W = fn() -> std::io::Stderr, > = layer::Layered, Registry>; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index b68b7d1b38b29..d339c0f27762c 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -26,15 +26,20 @@ mod directives; mod event_format; mod layers; -pub use sc_tracing_proc_macro::*; pub use directives::*; +pub use sc_tracing_proc_macro::*; use sc_telemetry::{ExtTransport, TelemetryWorker}; use tracing::Subscriber; use tracing_subscriber::{ - fmt::time::ChronoLocal, layer::{self, SubscriberExt}, registry::LookupSpan, - FmtSubscriber, Layer, EnvFilter, fmt::{SubscriberBuilder, format, FormatFields, MakeWriter, FormatEvent, Formatter, Layer as FmtLayer}, - Registry, + fmt::time::ChronoLocal, + fmt::{ + format, FormatEvent, FormatFields, Formatter, Layer as FmtLayer, MakeWriter, + SubscriberBuilder, + }, + layer::{self, SubscriberExt}, + registry::LookupSpan, + EnvFilter, FmtSubscriber, Layer, Registry, }; pub use event_format::*; @@ -67,14 +72,21 @@ macro_rules! disable_log_reloading { let handle = builder.reload_handle(); set_reload_handle(handle); builder - }}; + }}; } /// Common implementation to get the subscriber. fn get_subscriber_internal( pattern: &str, telemetry_external_transport: Option, - builder_hook: impl Fn(SubscriberBuilder, EnvFilter, fn() -> std::io::Stderr>) -> SubscriberBuilder, + builder_hook: impl Fn( + SubscriberBuilder< + format::DefaultFields, + EventFormat, + EnvFilter, + fn() -> std::io::Stderr, + >, + ) -> SubscriberBuilder, ) -> Result<(impl Subscriber + for<'a> LookupSpan<'a>, TelemetryWorker)> where N: for<'writer> FormatFields<'writer> + 'static, @@ -97,20 +109,18 @@ where // after log filter reloading by RPC let mut env_filter = EnvFilter::default() // Enable info - .add_directive(parse_default_directive("info") - .expect("provided directive is valid")) + .add_directive(parse_default_directive("info").expect("provided directive is valid")) // Disable info logging by default for some modules. - .add_directive(parse_default_directive("ws=off") - .expect("provided directive is valid")) - .add_directive(parse_default_directive("yamux=off") - .expect("provided directive is valid")) - .add_directive(parse_default_directive("cranelift_codegen=off") - .expect("provided directive is valid")) + .add_directive(parse_default_directive("ws=off").expect("provided directive is valid")) + .add_directive(parse_default_directive("yamux=off").expect("provided directive is valid")) + .add_directive( + parse_default_directive("cranelift_codegen=off").expect("provided directive is valid"), + ) // Set warn logging by default for some modules. - .add_directive(parse_default_directive("cranelift_wasm=warn") - .expect("provided directive is valid")) - .add_directive(parse_default_directive("hyper=warn") - .expect("provided directive is valid")); + .add_directive( + parse_default_directive("cranelift_wasm=warn").expect("provided directive is valid"), + ) + .add_directive(parse_default_directive("hyper=warn").expect("provided directive is valid")); if let Ok(lvl) = std::env::var("RUST_LOG") { if lvl != "" { @@ -135,7 +145,7 @@ where // NOTE: this must be done after we check the `max_level_hint` otherwise // it is always raised to `TRACE`. env_filter = env_filter.add_directive( - parse_default_directive("sc_tracing=trace").expect("provided directive is valid") + parse_default_directive("sc_tracing=trace").expect("provided directive is valid"), ); let enable_color = atty::is(atty::Stream::Stderr); @@ -145,7 +155,8 @@ where "%Y-%m-%d %H:%M:%S%.3f".to_string() }); - let (telemetry_layer, telemetry_worker) = sc_telemetry::TelemetryLayer::new(telemetry_external_transport)?; + let (telemetry_layer, telemetry_worker) = + sc_telemetry::TelemetryLayer::new(telemetry_external_transport)?; let event_format = EventFormat { timer, display_target: !simple, @@ -153,20 +164,13 @@ where display_thread_name: !simple, enable_color, }; - let builder = FmtSubscriber::builder() - .with_env_filter(env_filter); + let builder = FmtSubscriber::builder().with_env_filter(env_filter); #[cfg(not(target_os = "unknown"))] - let builder = builder - .with_writer( - std::io::stderr as _, - ); + let builder = builder.with_writer(std::io::stderr as _); #[cfg(target_os = "unknown")] - let builder = builder - .with_writer( - std::io::sink, - ); + let builder = builder.with_writer(std::io::sink); #[cfg(not(target_os = "unknown"))] let builder = builder.event_format(event_format); @@ -227,53 +231,57 @@ impl GlobalLoggerBuilder { /// /// This sets various global logging and tracing instances and thus may only be called once. pub fn init(self) -> Result { - Ok(if let Some((tracing_receiver, profiling_targets)) = self.profiling { - if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &format!("{},{}", self.pattern, profiling_targets), - self.telemetry_external_transport, - |builder| builder, - )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - - tracing::subscriber::set_global_default(subscriber.with(profiling))?; - - telemetry_worker - } else { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &format!("{},{}", self.pattern, profiling_targets), - self.telemetry_external_transport, - |builder| disable_log_reloading!(builder), - )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - - tracing::subscriber::set_global_default(subscriber.with(profiling))?; - - telemetry_worker - } - } else { - if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &self.pattern, - self.telemetry_external_transport, - |builder| builder, - )?; - - tracing::subscriber::set_global_default(subscriber)?; - - telemetry_worker + Ok( + if let Some((tracing_receiver, profiling_targets)) = self.profiling { + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), + self.telemetry_external_transport, + |builder| builder, + )?; + let profiling = + crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + tracing::subscriber::set_global_default(subscriber.with(profiling))?; + + telemetry_worker + } else { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), + self.telemetry_external_transport, + |builder| disable_log_reloading!(builder), + )?; + let profiling = + crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + tracing::subscriber::set_global_default(subscriber.with(profiling))?; + + telemetry_worker + } } else { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &self.pattern, - self.telemetry_external_transport, - |builder| disable_log_reloading!(builder), - )?; - - tracing::subscriber::set_global_default(subscriber)?; - - telemetry_worker - } - }) + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &self.pattern, + self.telemetry_external_transport, + |builder| builder, + )?; + + tracing::subscriber::set_global_default(subscriber)?; + + telemetry_worker + } else { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &self.pattern, + self.telemetry_external_transport, + |builder| disable_log_reloading!(builder), + )?; + + tracing::subscriber::set_global_default(subscriber)?; + + telemetry_worker + } + }, + ) } } From acdf2118b5a8f399dbf04b4ddd01a3d9d8d77709 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 16:09:47 +0100 Subject: [PATCH 170/222] Fix tests --- bin/node/cli/src/chain_spec.rs | 2 +- bin/node/cli/src/service.rs | 4 +-- client/rpc/src/system/tests.rs | 2 +- client/telemetry/src/dispatcher.rs | 2 +- client/telemetry/src/endpoints.rs | 45 ++++++++++++++++++++++++++++++ client/telemetry/src/lib.rs | 45 ------------------------------ client/tracing/src/logging/mod.rs | 6 ++-- 7 files changed, 52 insertions(+), 54 deletions(-) diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 83dc95e3b64df..cf3929235c2ea 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -441,7 +441,7 @@ pub(crate) mod tests { Ok(sc_service_test::TestNetComponents::new(task_manager, client, network, transaction_pool)) }, |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + let (keep_alive, _, _, client, network, transaction_pool) = new_light_base(config)?; Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) } ); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index cec5fe59094c3..951cde53c6458 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -523,7 +523,7 @@ mod tests { Ok((node, (inherent_data_providers, setup_handles.unwrap()))) }, |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + let (keep_alive, _, _, client, network, transaction_pool) = new_light_base(config)?; Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) }, |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| { @@ -681,7 +681,7 @@ mod tests { Ok(sc_service_test::TestNetComponents::new(task_manager, client, network, transaction_pool)) }, |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + let (keep_alive, _, _, client, network, transaction_pool) = new_light_base(config)?; Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) }, vec![ diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index fa3574e9dae02..952dbf746311d 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -344,7 +344,7 @@ fn test_add_reset_log_filter() { // Enter log generation / filter reload if std::env::var("TEST_LOG_FILTER").is_ok() { - sc_cli::init_logger("test_before_add=debug", Default::default(), Default::default(), false).unwrap(); + let _ = sc_tracing::logging::GlobalLoggerBuilder::new("test_before_add=debug").init().unwrap(); for line in std::io::stdin().lock().lines() { let line = line.expect("Failed to read bytes"); if line.contains("add_reload") { diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs index 02bec8dc4834f..87633de4aec97 100644 --- a/client/telemetry/src/dispatcher.rs +++ b/client/telemetry/src/dispatcher.rs @@ -125,7 +125,7 @@ impl Sink<(Multiaddr, String)> for Dispatcher { Ok(()) } - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.try_empty_buffer(cx) } diff --git a/client/telemetry/src/endpoints.rs b/client/telemetry/src/endpoints.rs index 941bbdebd6af9..44da649249362 100644 --- a/client/telemetry/src/endpoints.rs +++ b/client/telemetry/src/endpoints.rs @@ -79,3 +79,48 @@ fn url_to_multiaddr(url: &str) -> Result { // `Multiaddr`. Err(parse_error) } + +#[cfg(test)] +mod tests { + use super::url_to_multiaddr; + use super::TelemetryEndpoints; + use libp2p::Multiaddr; + + #[test] + fn valid_endpoints() { + let endp = vec![ + ("wss://telemetry.polkadot.io/submit/".into(), 3), + ("/ip4/80.123.90.4/tcp/5432".into(), 4), + ]; + let telem = + TelemetryEndpoints::new(endp.clone()).expect("Telemetry endpoint should be valid"); + let mut res: Vec<(Multiaddr, u8)> = vec![]; + for (a, b) in endp.iter() { + res.push(( + url_to_multiaddr(a).expect("provided url should be valid"), + *b, + )) + } + assert_eq!(telem.0, res); + } + + #[test] + fn invalid_endpoints() { + let endp = vec![ + ("/ip4/...80.123.90.4/tcp/5432".into(), 3), + ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), + ]; + let telem = TelemetryEndpoints::new(endp); + assert!(telem.is_err()); + } + + #[test] + fn valid_and_invalid_endpoints() { + let endp = vec![ + ("/ip4/80.123.90.4/tcp/5432".into(), 3), + ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), + ]; + let telem = TelemetryEndpoints::new(endp); + assert!(telem.is_err()); + } +} diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 16db072f71cf0..19ab99299b26a 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -403,48 +403,3 @@ macro_rules! format_fields_to_json { )* }}; } - -#[cfg(test)] -mod telemetry_endpoints_tests { - use super::url_to_multiaddr; - use super::TelemetryEndpoints; - use libp2p::Multiaddr; - - #[test] - fn valid_endpoints() { - let endp = vec![ - ("wss://telemetry.polkadot.io/submit/".into(), 3), - ("/ip4/80.123.90.4/tcp/5432".into(), 4), - ]; - let telem = - TelemetryEndpoints::new(endp.clone()).expect("Telemetry endpoint should be valid"); - let mut res: Vec<(Multiaddr, u8)> = vec![]; - for (a, b) in endp.iter() { - res.push(( - url_to_multiaddr(a).expect("provided url should be valid"), - *b, - )) - } - assert_eq!(telem.0, res); - } - - #[test] - fn invalid_endpoints() { - let endp = vec![ - ("/ip4/...80.123.90.4/tcp/5432".into(), 3), - ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), - ]; - let telem = TelemetryEndpoints::new(endp); - assert!(telem.is_err()); - } - - #[test] - fn valid_and_invalid_endpoints() { - let endp = vec![ - ("/ip4/80.123.90.4/tcp/5432".into(), 3), - ("/ip4/no:!?;rlkqre;;::::///tcp/5432".into(), 4), - ]; - let telem = TelemetryEndpoints::new(endp); - assert!(telem.is_err()); - } -} diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index d339c0f27762c..fb24c3b6b7124 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -295,10 +295,8 @@ mod tests { const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; const EXPECTED_NODE_NAME: &'static str = "THE_NODE"; - fn init_logger(pattern: &str) -> tracing::subscriber::DefaultGuard { - let (subscriber, _telemetry_worker) = - get_default_subscriber_and_telemetry_worker(pattern, None, false).unwrap(); - tracing::subscriber::set_default(subscriber) + fn init_logger(pattern: &str) { + let _ = GlobalLoggerBuilder::new(pattern).init().unwrap(); } #[test] From fc39a08616df10faf49039ce8c25d64223469e71 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 16:52:31 +0100 Subject: [PATCH 171/222] Fix failing test --- client/tracing/src/logging/mod.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index fb24c3b6b7124..c97a6f53ae667 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -299,10 +299,24 @@ mod tests { let _ = GlobalLoggerBuilder::new(pattern).init().unwrap(); } + fn run_in_process(test_name: &str) { + if env::var("RUN_IN_PROCESS").is_err() { + let status = Command::new(env::current_exe().unwrap()) + .arg(test_name) + .env("RUN_IN_PROCESS", "true") + .status() + .unwrap(); + assert!(status.success(), "process did not ended successfully"); + std::process::exit(0); + } + } + #[test] fn test_logger_filters() { + run_in_process("test_logger_filters"); + let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; - let _guard = init_logger(&test_pattern); + init_logger(&test_pattern); tracing::dispatcher::get_default(|dispatcher| { let test_filter = |target, level| { From 9be956026a60e34d95daed5c2294d6619120f466 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 16:58:37 +0100 Subject: [PATCH 172/222] Re-export global logger builder in sc-cli --- client/cli/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 3d40a0fa1de33..4299e7dddfe77 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -37,6 +37,7 @@ pub use params::*; pub use runner::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; +pub use sc_tracing::logging::GlobalLoggerBuilder; pub use sp_version::RuntimeVersion; use std::io::Write; pub use structopt; From 28916cbc374fabb204632de65d1e958033f23c57 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 17 Dec 2020 18:04:51 +0100 Subject: [PATCH 173/222] Fix ci issue? --- .maintain/gitlab/check_polkadot_companion_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh index 4a7e9869abf5e..f2b61c6192d62 100755 --- a/.maintain/gitlab/check_polkadot_companion_build.sh +++ b/.maintain/gitlab/check_polkadot_companion_build.sh @@ -45,7 +45,7 @@ cargo install -f --version 0.2.0 diener # Merge master into our branch before building Polkadot to make sure we don't miss # any commits that are required by Polkadot. -git fetch --depth 20 origin +git fetch --depth 100 origin git merge origin/master # Clone the current Polkadot master branch into ./polkadot. From 787ecba188db5eb1dfc5137b7dae27b23b6c2542 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 18 Dec 2020 13:17:05 +0100 Subject: [PATCH 174/222] Update doc --- client/telemetry/src/layer.rs | 2 +- client/telemetry/src/lib.rs | 81 ++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 23868337ea03d..3beb7ff8227aa 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -32,7 +32,7 @@ pub const TELEMETRY_LOG_SPAN: &str = "telemetry-logger"; pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { - /// Create a new [`TelemetryLayer`] using the [`Senders`] provided in argument. + /// Create a new [`TelemetryLayer`] and [`TelemetryWorker`]. pub fn new( telemetry_external_transport: Option, ) -> super::Result<(Self, TelemetryWorker)> { diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 19ab99299b26a..5b40e1ba96c1a 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -16,26 +16,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Telemetry utilities. TODO update doc +//! To start using this module, please initialize the global logger from `sc-tracing`. This will +//! return a [`TelemetryWorker`] which can be used to register substrate node. In order to do that, +//! first call [`TelemetryWorker::handle()`] to get a handle to the worker, then use +//! [`TelemetryHandle::start_telemetry()`] to initialize the telemetry. This will also return a +//! [`TelemetryConnectionNotifier`] which can be used to create streams of events for whenever the +//! connection to a telemetry server is (re-)established. //! -//! You can collect telemetries for a substrate node by creating a `Telemetry` object. For every -//! substrate node there must be only one `Telemetry` object. This `Telemetry` object can connect to -//! multiple telemetry endpoints. The `Telemetry` object is a `Stream` that needs to be polled -//! regularly in order to function. -//! -//! The macro `telemetry!` can be used to report telemetries from anywhere in the code but a -//! `Telemetry` must have been initialized. Creating a `Telemetry` will make all the following code -//! execution (including newly created async background tasks) use this `Telemetry` when reporting -//! telemetries. If multiple `Telemetry` objects are created, the latest one (higher up in the -//! stack) will be used. If no `Telemetry` object can be found, nothing is reported. -//! -//! To re-use connections to the same server you need to use the `TelemetryWorker` object to create -//! multiple `Telemetry`. `TelemetryWorker` also manages a collection of channel `Sender` for you (see -//! `Senders`). `TelemetryWorker` should be used unless you need finer control. -//! -//! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a -//! background thread/task) in order for the telemetry to properly function. -//! The `Stream` generates [`TelemetryEvent`]s. +//! The macro [`telemetry`] can be used to report telemetries from anywhere in the code but the +//! telemetry must have been initialized through [`TelemetryHandle::start_telemetry()`]. +//! Initializing the telemetry will make all the following code execution (including newly created +//! async background tasks) report the telemetries through the endpoints provided during the +//! initialization. If multiple telemetries have been started, the latest one (higher up in the +//! stack) will be used. If no telemetry has been started, nothing will be reported. #![warn(missing_docs)] @@ -88,9 +81,11 @@ pub(crate) type InitPayload = ( mpsc::UnboundedReceiver, ); -/// An object that keeps track of all the [`Telemetry`] created by its `build_telemetry()` method. +/// Telemetry worker. /// -/// [`Telemetry`] created through this object re-use connections if possible. +/// It should be ran as a background task using the [`TelemetryWorker::run`] method. This method +/// will consume the object and any further attempts of initializing a new telemetry through its +/// handle will fail (without being fatal). #[derive(Debug)] pub struct TelemetryWorker { receiver: mpsc::Receiver<(Id, u8, String)>, @@ -113,17 +108,15 @@ pub enum Error { } impl TelemetryWorker { - /// Create a [`TelemetryWorker`] instance using an `ExtTransport`. - /// - /// This is used in WASM contexts where we need some binding between the networking provided by - /// the operating system or environment and libp2p. + /// Create a [`TelemetryWorker`] instance using an [`ExtTransport`]. /// - /// This constructor is expected to be used only when compiling for WASM. + /// The [`ExtTransport`] is used in WASM contexts where we need some binding between the + /// networking provided by the operating system or environment and libp2p. /// /// > **Important**: Each individual call to `write` corresponds to one message. There is no /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. - pub fn new(wasm_external_transport: Option) -> Result { + pub(crate) fn new(wasm_external_transport: Option) -> Result { let (sender, receiver) = mpsc::channel(16); let (init_sender, init_receiver) = mpsc::unbounded(); @@ -143,12 +136,14 @@ impl TelemetryWorker { TelemetryHandle(self.init_sender.clone()) } - /// Get a clone of the channel's `Sender` used to send telemetry event. + /// Get a clone of the channel's `Sender` used to send telemetry events. pub(crate) fn sender(&self) -> mpsc::Sender<(Id, u8, String)> { self.sender.clone() } /// Run the telemetry worker. + /// + /// This should be run in a background task. pub async fn run(self) { let Self { receiver, @@ -337,13 +332,29 @@ impl TelemetryConnectionNotifier { } } -/// Translates to `tracing::info!`, but contains an additional verbosity -/// parameter which the log record is tagged with. Additionally the verbosity -/// parameter is added to the record as a key-value pair. +/// Report a telemetry. +/// +/// Translates to [`tracing::info`], but contains an additional verbosity parameter which the log +/// record is tagged with. Additionally the verbosity parameter is added to the record as a +/// key-value pair. +/// +/// # Example +/// +/// ```no_run +/// # use sc_telemetry::*; +/// # let authority_id = 42_u64; +/// # let set_id = (43_u64, 44_u64); +/// # let authorities = vec![45_u64]; +/// telemetry!(CONSENSUS_INFO; "afg.authority_set"; +/// "authority_id" => authority_id.to_string(), +/// "authority_set_id" => ?set_id, +/// "authorities" => authorities, +/// ); +/// ``` #[macro_export(local_inner_macros)] macro_rules! telemetry { - ( $a:expr; $b:expr; $( $t:tt )* ) => {{ - let verbosity: u8 = $a; + ( $verbosity:expr; $msg:expr; $( $t:tt )* ) => {{ + let verbosity: u8 = $verbosity; match format_fields_to_json!($($t)*) { Err(err) => { $crate::tracing::error!( @@ -354,7 +365,7 @@ macro_rules! telemetry { }, Ok(mut json) => { // NOTE: the span id will be added later in the JSON for the greater good - json.insert("msg".into(), $b.into()); + json.insert("msg".into(), $msg.into()); json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); let serialized_json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed"); @@ -390,7 +401,7 @@ macro_rules! format_fields_to_json { ( $k:literal => ? $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), std::format!("{:?}", &$v).into()); - let ok_map: Result<_, $crate::serde_json::Error> = Ok(map); + let ok_map: ::std::result::Result<_, $crate::serde_json::Error> = Ok(map); ok_map $( .and_then(|mut prev_map| { From d2fcfcfa4010b5dcfbcfc9427731301c0152fbb2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 18 Dec 2020 13:17:55 +0100 Subject: [PATCH 175/222] Simplify code a tad bit --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5b40e1ba96c1a..5c083bc7239db 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -401,7 +401,7 @@ macro_rules! format_fields_to_json { ( $k:literal => ? $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), std::format!("{:?}", &$v).into()); - let ok_map: ::std::result::Result<_, $crate::serde_json::Error> = Ok(map); + let ok_map: $crate::serde_json::Result<_> = Ok(map); ok_map $( .and_then(|mut prev_map| { From 8e7d3cca19e49a502886321c1c4004ee41d19ac8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 18 Dec 2020 13:24:50 +0100 Subject: [PATCH 176/222] Update README.md --- client/telemetry/README.md | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index 2309a0ac072da..317805794dc97 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -1,24 +1,17 @@ # sc-telemetry -Telemetry utilities. +To start using this module, please initialize the global logger from `sc-tracing`. This will +return a [`TelemetryWorker`] which can be used to register substrate node. In order to do that, +first call [`TelemetryWorker::handle()`] to get a handle to the worker, then use +[`TelemetryHandle::start_telemetry()`] to initialize the telemetry. This will also return a +[`TelemetryConnectionNotifier`] which can be used to create streams of events for whenever the +connection to a telemetry server is (re-)established. -The `Telemetry` object is a `Stream` that needs to be polled regularly in order to function. -It is unregistered when the object is dropped. - -`Telemetry` objects can be created through its constructor `Telemetry::new()`, or through a -`Telemetries` instance. The difference between the two is that `Telemetries` will re-use -connections to the same server if possible and manages a collection of channel `Sender` for you -(see `Senders`). `Telemetries` should be used unless you need finer control. - -The macro `telemetry!` can be used to report telemetries from anywhere but a `Telemetry` must -have been initialized. Creating a `Telemetry` will make all the following code execution use -this `Telemetry` when reporting with the macro `telemetry!` until the `Telemetry` object is -dropped. If multiple `Telemetry` objects are created, the latest one (higher up in the stack) -will be used. If no `Telemetry` object can be found, nothing happens. - -The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a -background thread/task) in order for the telemetry to properly function. Dropping the object -will also deregister the global logger and replace it with a logger that discards messages. -The `Stream` generates [`TelemetryEvent`]s. +The macro [`telemetry`] can be used to report telemetries from anywhere in the code but the +telemetry must have been initialized through [`TelemetryHandle::start_telemetry()`]. +Initializing the telemetry will make all the following code execution (including newly created +async background tasks) report the telemetries through the endpoints provided during the +initialization. If multiple telemetries have been started, the latest one (higher up in the +stack) will be used. If no telemetry has been started, nothing will be reported. License: GPL-3.0-or-later WITH Classpath-exception-2.0 From 4d52c2ee6432882190e282210fbff5b1f8dd2d50 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 18 Dec 2020 13:30:53 +0100 Subject: [PATCH 177/222] Add comment --- client/telemetry/src/node.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 11a0ae080954d..d603473fea103 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -228,6 +228,9 @@ where } }; + // The Dispatcher blocks when the Node sinks blocks. This is why it is important that the + // Node sinks doesn't go into "Pending" state while waiting for reconnection but rather + // discard the excess of telemetry messages. Poll::Ready(Ok(())) } From d670efe00f111dae13613c4ea73215220079aa86 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 18 Dec 2020 13:39:07 +0100 Subject: [PATCH 178/222] CLEANUP --- utils/browser/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 1a3c365381375..0262b8125f30d 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -35,9 +35,6 @@ use libp2p_wasm_ext::{ExtTransport, ffi}; pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// Initialize the logger and return a `TelemetryWorker` and a wasm `ExtTransport`. -/// -/// The `TelemetryWorker` object can be use to create `Telemetry` objects and the wasm `ExtTransport` -/// can be used for network transport. pub fn init_logging_and_telemetry( pattern: &str, ) -> Result> { From 9c26aa971221c81db481336c2cc48d6c4e23fdbf Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 11:54:47 +0100 Subject: [PATCH 179/222] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/rpc/src/system/tests.rs | 2 +- client/service/Cargo.toml | 4 ---- client/service/src/builder.rs | 15 ++++----------- client/service/test/Cargo.toml | 1 - client/telemetry/src/endpoints.rs | 7 +------ utils/browser/src/lib.rs | 4 +--- 6 files changed, 7 insertions(+), 26 deletions(-) diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index 952dbf746311d..f952e9be8a05d 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -344,7 +344,7 @@ fn test_add_reset_log_filter() { // Enter log generation / filter reload if std::env::var("TEST_LOG_FILTER").is_ok() { - let _ = sc_tracing::logging::GlobalLoggerBuilder::new("test_before_add=debug").init().unwrap(); + sc_tracing::logging::GlobalLoggerBuilder::new("test_before_add=debug").init().unwrap(); for line in std::io::stdin().lock().lines() { let line = line.expect("Failed to read bytes"); if line.contains("add_reload") { diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index f5cd6ada14d83..5930bd42967de 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -24,8 +24,6 @@ wasmtime = [ test-helpers = [] [dependencies] -ansi_term = "0.12.1" -atty = "0.2.13" thiserror = "1.0.21" futures01 = { package = "futures", version = "0.1.29" } futures = { version = "0.3.4", features = ["compat"] } @@ -79,8 +77,6 @@ sc-tracing = { version = "2.0.0", path = "../tracing" } sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } tracing = "0.1.22" tracing-futures = { version = "0.2.4" } -tracing-log = "0.1.1" -tracing-subscriber = "0.2.10" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index f2b7358f7c684..a15f6ee78ac06 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -569,7 +569,7 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - let telemetry_telemetry_connection_notifier = init_telemetry( + let telemetry_connection_notifier = init_telemetry( &mut config, network.clone(), client.clone(), @@ -649,7 +649,7 @@ pub fn spawn_tasks( task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone())); - Ok((rpc_handlers, telemetry_telemetry_connection_notifier)) + Ok((rpc_handlers, telemetry_connection_notifier)) } async fn transaction_notifications( @@ -679,11 +679,7 @@ fn init_telemetry>( network: Arc::Hash>>, client: Arc, ) -> Option { - let telemetry_handle = if let Some(handle) = config.telemetry_handle.as_mut() { - handle - } else { - return None; - }; + let telemetry_handle = config.telemetry_handle.as_mut()?; let endpoints = match config.telemetry_endpoints.clone() { // Don't initialise telemetry if `telemetry_endpoints` == Some([]) @@ -691,10 +687,7 @@ fn init_telemetry>( _ => return None, }; - let genesis_hash = match client.block_hash(Zero::zero()) { - Ok(Some(hash)) => hash, - _ => Default::default(), - }; + let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default(); let is_authority = config.role.is_authority(); let network_id = network.local_peer_id().to_base58(); diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index cfb8d72240e5b..84ac84e630d00 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -29,7 +29,6 @@ sp-storage = { version = "2.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.8.0", default-features = false, path = "../../db" } futures = { version = "0.3.1", features = ["compat"] } sc-service = { version = "0.8.0", default-features = false, features = ["test-helpers"], path = "../../service" } -sc-telemetry = { version = "2.0.0", default-features = false, path = "../../telemetry" } sc-network = { version = "0.8.0", path = "../../network" } sp-consensus = { version = "0.8.0", path = "../../../primitives/consensus/common" } sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } diff --git a/client/telemetry/src/endpoints.rs b/client/telemetry/src/endpoints.rs index 44da649249362..e0565906d7924 100644 --- a/client/telemetry/src/endpoints.rs +++ b/client/telemetry/src/endpoints.rs @@ -35,12 +35,7 @@ where { Vec::<(String, u8)>::deserialize(deserializer)? .iter() - .map(|e| { - Ok(( - url_to_multiaddr(&e.0).map_err(serde::de::Error::custom)?, - e.1, - )) - }) + .map(|e| url_to_multiaddr(&e.0).map_err(serde::de::Error::custom).map(|m| (m, e.1))) .collect() } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 0262b8125f30d..30ee08fae083d 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -41,9 +41,7 @@ pub fn init_logging_and_telemetry( let transport = ExtTransport::new(ffi::websocket_transport()); let mut logger = GlobalLoggerBuilder::new(pattern); logger.with_transport(transport); - let telemetry_worker = logger.init()?; - - Ok(telemetry_worker) + logger.init() } /// Create a service configuration from a chain spec. From f4e474928a7510a6719678c580f29e533908e2b0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 12:01:32 +0100 Subject: [PATCH 180/222] Fix after suggestion --- Cargo.lock | 5 ----- utils/browser/src/lib.rs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0fe5961b1a6fc..4d513e8ab3771 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7301,9 +7301,7 @@ dependencies = [ name = "sc-service" version = "0.8.0" dependencies = [ - "ansi_term 0.12.1", "async-std", - "atty", "directories 3.0.1", "exit-future", "futures 0.1.30", @@ -7365,8 +7363,6 @@ dependencies = [ "tokio 0.2.23", "tracing", "tracing-futures", - "tracing-log", - "tracing-subscriber", "wasm-timer", ] @@ -7388,7 +7384,6 @@ dependencies = [ "sc-light", "sc-network", "sc-service", - "sc-telemetry", "sp-api", "sp-blockchain", "sp-consensus", diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 30ee08fae083d..2f634e21790a3 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -37,7 +37,7 @@ pub use console_error_panic_hook::set_once as set_console_error_panic_hook; /// Initialize the logger and return a `TelemetryWorker` and a wasm `ExtTransport`. pub fn init_logging_and_telemetry( pattern: &str, -) -> Result> { +) -> Result { let transport = ExtTransport::new(ffi::websocket_transport()); let mut logger = GlobalLoggerBuilder::new(pattern); logger.with_transport(transport); From 9ba4bffcc0313d5813d67e0d5bdf39d11153e22a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:27:00 +0100 Subject: [PATCH 181/222] Group hashmaps --- client/telemetry/src/lib.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 5c083bc7239db..d74aa5c40d494 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -154,9 +154,10 @@ impl TelemetryWorker { } = self; let mut node_map: HashMap> = HashMap::new(); - let mut connection_messages: HashMap> = HashMap::new(); - let mut connection_notifiers: HashMap> = - HashMap::new(); + let mut node_args: HashMap< + Multiaddr, + (Vec, Vec), + > = HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes @@ -178,26 +179,20 @@ impl TelemetryWorker { let mut obj = connection_message.clone(); obj.insert("msg".into(), "system.connected".into()); obj.insert("id".into(), id.into_u64().into()); - connection_messages + let (connection_messages, connection_notifiers) = node_args .entry(addr.clone()) - .or_insert_with(Vec::new) - .push(obj); - connection_notifiers - .entry(addr.clone()) - .or_insert_with(Vec::new) - .extend(connection_notifier_senders.clone()); + .or_insert_with(|| (Vec::new(), Vec::new())); + connection_messages.push(obj); + connection_notifiers.extend(connection_notifier_senders.clone()); } } let mut node_pool: Dispatcher = existing_nodes .iter() .map(|addr| { - let connection_messages = connection_messages + let (connection_messages, connection_notifiers) = node_args .remove(addr) .expect("there is a node for every connection message; qed"); - let connection_notifiers = connection_notifiers - .remove(addr) - .expect("there is a node for every connection notifier; qed"); let node = Node::new( transport.clone(), addr.clone(), From a6fce44d8bd434ca189a92f1df6e6f4c43a4b71a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:28:02 +0100 Subject: [PATCH 182/222] Indent --- client/telemetry/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index d74aa5c40d494..fc2c5b830d982 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -225,10 +225,11 @@ impl TelemetryWorker { for (node_max_verbosity, addr) in nodes { if verbosity > *node_max_verbosity { log::trace!( - target: "telemetry", - "Skipping {} for log entry with verbosity {:?}", - addr, - verbosity); + target: "telemetry", + "Skipping {} for log entry with verbosity {:?}", + addr, + verbosity, + ); continue; } From 6521813f2ae0331a35968506d3ae72f1614bfe1c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:41:20 +0100 Subject: [PATCH 183/222] Moving down --- client/tracing/src/logging/mod.rs | 96 +++++++++++++++---------------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index c97a6f53ae667..d9c43e8c0ca1a 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -231,57 +231,53 @@ impl GlobalLoggerBuilder { /// /// This sets various global logging and tracing instances and thus may only be called once. pub fn init(self) -> Result { - Ok( - if let Some((tracing_receiver, profiling_targets)) = self.profiling { - if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &format!("{},{}", self.pattern, profiling_targets), - self.telemetry_external_transport, - |builder| builder, - )?; - let profiling = - crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - - tracing::subscriber::set_global_default(subscriber.with(profiling))?; - - telemetry_worker - } else { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &format!("{},{}", self.pattern, profiling_targets), - self.telemetry_external_transport, - |builder| disable_log_reloading!(builder), - )?; - let profiling = - crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); - - tracing::subscriber::set_global_default(subscriber.with(profiling))?; - - telemetry_worker - } + if let Some((tracing_receiver, profiling_targets)) = self.profiling { + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), + self.telemetry_external_transport, + |builder| builder, + )?; + let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + tracing::subscriber::set_global_default(subscriber.with(profiling))?; + + Ok(telemetry_worker) } else { - if self.disable_log_reloading { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &self.pattern, - self.telemetry_external_transport, - |builder| builder, - )?; - - tracing::subscriber::set_global_default(subscriber)?; - - telemetry_worker - } else { - let (subscriber, telemetry_worker) = get_subscriber_internal( - &self.pattern, - self.telemetry_external_transport, - |builder| disable_log_reloading!(builder), - )?; - - tracing::subscriber::set_global_default(subscriber)?; - - telemetry_worker - } - }, - ) + let (subscriber, telemetry_worker) = get_subscriber_internal( + &format!("{},{}", self.pattern, profiling_targets), + self.telemetry_external_transport, + |builder| disable_log_reloading!(builder), + )?; + let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + tracing::subscriber::set_global_default(subscriber.with(profiling))?; + + Ok(telemetry_worker) + } + } else { + if self.disable_log_reloading { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &self.pattern, + self.telemetry_external_transport, + |builder| builder, + )?; + + tracing::subscriber::set_global_default(subscriber)?; + + Ok(telemetry_worker) + } else { + let (subscriber, telemetry_worker) = get_subscriber_internal( + &self.pattern, + self.telemetry_external_transport, + |builder| disable_log_reloading!(builder), + )?; + + tracing::subscriber::set_global_default(subscriber)?; + + Ok(telemetry_worker) + } + } } } From b1b554515ca62aa1c22d14aa6a922d9fd3519643 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:49:56 +0100 Subject: [PATCH 184/222] Simplify json object creation --- client/service/src/builder.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index a15f6ee78ac06..0923172bfd8b9 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -699,19 +699,16 @@ fn init_telemetry>( .map(|dur| dur.as_millis()) .unwrap_or(0); - let json = serde_json::json! {{ - "name": name.clone(), - "implementation": impl_name.clone(), - "version": impl_version.clone(), - "config": "", - "chain": chain_name.clone(), - "genesis_hash": format!("{:?}", genesis_hash), - "authority": is_authority, - "startup_time": startup_time.to_string(), - "network_id": network_id.clone() - }}; - - let obj = serde_json::from_value(json).expect("it's an object; qed"); + let mut obj = serde_json::Map::new(); + obj.insert("name".to_string(), name.clone().into()); + obj.insert("implementation".to_string(), impl_name.clone().into()); + obj.insert("version".to_string(), impl_version.clone().into()); + obj.insert("config".to_string(), "".into()); + obj.insert("chain".to_string(), chain_name.clone().into()); + obj.insert("genesis_hash".to_string(), format!("{:?}", genesis_hash).into()); + obj.insert("authority".to_string(), is_authority.into()); + obj.insert("startup_time".to_string(), startup_time.to_string().into()); + obj.insert("network_id".to_string(), network_id.clone().into()); Some(telemetry_handle.start_telemetry(endpoints, obj)) } From 37e045e6a923cf79854e4a10aae1bff372375db0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:55:56 +0100 Subject: [PATCH 185/222] Doc --- client/service/src/config.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 2fb9e72ab4336..3f7f6c0f3c330 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -90,6 +90,9 @@ pub struct Configuration { /// endpoint, this transport will be tried in priority before all others. pub telemetry_external_transport: Option, /// Telemetry handle. + /// + /// This is a handle to a `TelemetryWorker` instance. It is used to initialize the telemetry for + /// a substrate node. pub telemetry_handle: Option, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, From 79a04e2158a89ef424acfc2a52bfdbf9c91faf33 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:58:10 +0100 Subject: [PATCH 186/222] Ordering stuff --- client/tracing/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index a769a83246e11..ac2fd3506fbc9 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -45,11 +45,11 @@ use tracing_subscriber::{ use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; -const ZERO_DURATION: Duration = Duration::from_nanos(0); - #[doc(hidden)] pub use tracing; +const ZERO_DURATION: Duration = Duration::from_nanos(0); + /// Responsible for assigning ids to new spans, which are not re-used. pub struct ProfilingLayer { targets: Vec<(String, Level)>, From fa5ea74e32bd07f64a919bc24b984b01f4d9f2c1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 13:58:59 +0100 Subject: [PATCH 187/222] Indent --- client/tracing/src/logging/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index d9c43e8c0ca1a..d194a8f5359cc 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -72,7 +72,7 @@ macro_rules! disable_log_reloading { let handle = builder.reload_handle(); set_reload_handle(handle); builder - }}; + }}; } /// Common implementation to get the subscriber. From 0a8ca91d6f7101ae9d18831189e880630b8a111f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 6 Jan 2021 14:24:10 +0100 Subject: [PATCH 188/222] Remove TelemetryError --- Cargo.lock | 1 - client/telemetry/Cargo.toml | 1 - client/telemetry/src/layer.rs | 3 ++- client/telemetry/src/lib.rs | 15 ++------------- client/tracing/src/logging/mod.rs | 3 ++- 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d513e8ab3771..9a5718b712219 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7451,7 +7451,6 @@ dependencies = [ "serde_json", "sp-utils", "take_mut", - "thiserror", "tracing", "tracing-subscriber", "void", diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 15b76a2c54efa..1876c5734de42 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -31,4 +31,3 @@ tracing-subscriber = "0.2.13" serde_json = "1.0.41" chrono = "0.4.13" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } -thiserror = "1.0.21" diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 3beb7ff8227aa..6722a060b6753 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -21,6 +21,7 @@ use futures::channel::mpsc; use libp2p::wasm_ext::ExtTransport; use parking_lot::Mutex; use std::convert::TryInto; +use std::io; use tracing::{Event, Id, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; @@ -35,7 +36,7 @@ impl TelemetryLayer { /// Create a new [`TelemetryLayer`] and [`TelemetryWorker`]. pub fn new( telemetry_external_transport: Option, - ) -> super::Result<(Self, TelemetryWorker)> { + ) -> io::Result<(Self, TelemetryWorker)> { let worker = TelemetryWorker::new(telemetry_external_transport)?; let sender = worker.sender(); Ok((Self(Mutex::new(sender)), worker)) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index fc2c5b830d982..eb5f656ec30f6 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -38,6 +38,7 @@ use log::{error, warn}; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use std::{ collections::{HashMap, HashSet}, + io, time::Duration, }; use tracing::Id; @@ -95,18 +96,6 @@ pub struct TelemetryWorker { transport: WsTrans, } -/// Telemetry Result typedef. -pub type Result = std::result::Result; - -/// Telemetry errors. -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -#[non_exhaustive] -pub enum Error { - #[error(transparent)] - Io(#[from] std::io::Error), -} - impl TelemetryWorker { /// Create a [`TelemetryWorker`] instance using an [`ExtTransport`]. /// @@ -116,7 +105,7 @@ impl TelemetryWorker { /// > **Important**: Each individual call to `write` corresponds to one message. There is no /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. - pub(crate) fn new(wasm_external_transport: Option) -> Result { + pub(crate) fn new(wasm_external_transport: Option) -> io::Result { let (sender, receiver) = mpsc::channel(16); let (init_sender, init_receiver) = mpsc::unbounded(); diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index d194a8f5359cc..bf88624a79232 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -30,6 +30,7 @@ pub use directives::*; pub use sc_tracing_proc_macro::*; use sc_telemetry::{ExtTransport, TelemetryWorker}; +use std::io; use tracing::Subscriber; use tracing_subscriber::{ fmt::time::ChronoLocal, @@ -54,7 +55,7 @@ pub type Result = std::result::Result; #[non_exhaustive] pub enum Error { #[error(transparent)] - TelemetryError(#[from] sc_telemetry::Error), + IoError(#[from] io::Error), #[error(transparent)] SetGlobalDefaultError(#[from] tracing::subscriber::SetGlobalDefaultError), From ddb53d0518ba621a16235bc24358085e4ab31229 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 7 Jan 2021 16:40:25 +0100 Subject: [PATCH 189/222] New payload format & remove ts --- Cargo.lock | 1 - client/telemetry/Cargo.toml | 1 - client/telemetry/src/layer.rs | 39 ++++++++++++++--------------------- client/telemetry/src/lib.rs | 12 +++++------ client/telemetry/src/node.rs | 8 +------ 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23e80f41d77ad..4cc0d1bf60432 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7506,7 +7506,6 @@ dependencies = [ name = "sc-telemetry" version = "2.0.0" dependencies = [ - "chrono", "futures 0.3.8", "futures-timer 3.0.2", "libp2p", diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 0f3106b0b98b6..a6e70a114a494 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -29,5 +29,4 @@ void = "1.0.2" tracing = "0.1.10" tracing-subscriber = "0.2.13" serde_json = "1.0.41" -chrono = "0.4.13" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 5c9ff6a7db270..cef99917ffcb0 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -70,19 +70,15 @@ where .. } = attrs { - if self - .0 - .lock() - .try_send(( - id, - verbosity - .try_into() - .expect("telemetry log message verbosity are u8; qed"), - json, - )) - .is_err() - { - eprintln!("Telemetry buffer overflowed!"); + match self.0.lock().try_send(( + id, + verbosity + .try_into() + .expect("telemetry log message verbosity are u8; qed"), + json, + )) { + Err(err) if err.is_full() => eprintln!("Telemetry buffer overflowed!"), + _ => {} } } else { // NOTE: logging in this function doesn't work @@ -125,22 +121,17 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_u64(&mut self, field: &tracing::field::Field, value: u64) { if field.name() == "verbosity" { - (*self.0).verbosity = Some(value) + (*self.0).verbosity = Some(value); } } fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { - if value.chars().next() != Some('{') { - eprintln!( - "Invalid value for JSON in telemetry logging: \ - the attribute's value `json` doesn't start with the character `{{`", - ); - } - // NOTE: this is a hack to inject the span id into the json - let mut message = format!(r#"{{"id":{},"#, (*self.0).id.into_u64()); - message.push_str(&value[1..]); - (*self.0).json = Some(message) + (*self.0).json = Some(format!( + r#"{{"id":{},"payload":{}}}"#, + self.0.id.into_u64(), + value, + )); } } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index c6f4f2e567b0b..98365397b06ab 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -44,7 +44,6 @@ use std::{ use tracing::Id; use wasm_timer::Instant; -pub use chrono; pub use libp2p::wasm_ext::ExtTransport; pub use serde_json; pub use tracing; @@ -151,7 +150,7 @@ impl TelemetryWorker { // initialize the telemetry nodes init_receiver.close(); - while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = + while let Some((id, endpoints, mut connection_message, mut connection_notifiers_rx)) = init_receiver.next().await { let endpoints = endpoints.0; @@ -159,15 +158,17 @@ impl TelemetryWorker { connection_notifiers_rx.close(); let connection_notifier_senders: Vec<_> = connection_notifiers_rx.collect().await; + connection_message.insert("msg".into(), "system.connected".into()); + for (addr, verbosity) in endpoints { node_map .entry(id.clone()) .or_insert_with(Vec::new) .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); - let mut obj = connection_message.clone(); - obj.insert("msg".into(), "system.connected".into()); - obj.insert("id".into(), id.into_u64().into()); + let mut obj = serde_json::Map::new(); + obj.insert("id".to_string(), id.into_u64().into()); + obj.insert("payload".to_string(), connection_message.clone().into()); let (connection_messages, connection_notifiers) = node_args .entry(addr.clone()) .or_insert_with(|| (Vec::new(), Vec::new())); @@ -351,7 +352,6 @@ macro_rules! telemetry { Ok(mut json) => { // NOTE: the span id will be added later in the JSON for the greater good json.insert("msg".into(), $msg.into()); - json.insert("ts".into(), $crate::chrono::Local::now().to_rfc3339().into()); let serialized_json = $crate::serde_json::to_string(&json) .expect("contains only string keys; qed"); $crate::tracing::info!(target: $crate::TELEMETRY_LOG_SPAN, diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 86081d107201d..bb75565d5b64a 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -172,17 +172,11 @@ where let _ = sender.send(()); } - fn generate_message(mut obj: ConnectionMessage) -> Result, String> { - obj.insert("ts".into(), chrono::Local::now().to_rfc3339().into()); - serde_json::to_vec(&obj) - .map_err(|err| format!("Could not serialize JSON message: {}", err)) - } - let buf = self .connection_messages .iter() .cloned() - .filter_map(|json| match generate_message(json) { + .filter_map(|json| match serde_json::to_vec(&json) { Ok(message) => Some(message), Err(err) => { log::error!( From 966fd4ce2a0664769a2d80a8cff2cf3cd3718ff4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 7 Jan 2021 17:03:18 +0100 Subject: [PATCH 190/222] Replace dispatcher with a simple loop --- client/telemetry/src/dispatcher.rs | 153 ----------------------------- client/telemetry/src/lib.rs | 25 +++-- 2 files changed, 16 insertions(+), 162 deletions(-) delete mode 100644 client/telemetry/src/dispatcher.rs diff --git a/client/telemetry/src/dispatcher.rs b/client/telemetry/src/dispatcher.rs deleted file mode 100644 index 59737dfa191e3..0000000000000 --- a/client/telemetry/src/dispatcher.rs +++ /dev/null @@ -1,153 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use crate::node::{Infallible, Node}; -use crate::transport::WsTrans; -use futures::prelude::*; -use libp2p::Multiaddr; -use std::collections::HashMap; -use std::iter::FromIterator; -use std::pin::Pin; -use std::task::{Context, Poll}; - -#[derive(Debug)] -pub(crate) struct Dispatcher { - pool: HashMap>, - item: Option<(Multiaddr, String)>, - flush_node: Option, -} - -impl FromIterator<(Multiaddr, Node)> for Dispatcher { - fn from_iter)>>(iter: I) -> Self { - let pool: HashMap<_, _> = FromIterator::from_iter(iter); - Dispatcher { - pool, - item: None, - flush_node: None, - } - } -} - -impl Dispatcher { - fn try_empty_buffer( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - if let Some(addr) = self.flush_node.take() { - let node = self - .pool - .get_mut(&addr) - .expect("we added the address ourselves; qed"); - match node.poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(x)) => match x {}, - Poll::Pending => { - self.flush_node = Some(addr); - return Poll::Pending; - } - } - } - - if let Some((addr, message)) = self.item.take() { - let node = if let Some(node) = self.pool.get_mut(&addr) { - node - } else { - log::error!( - target: "telemetry", - "Received message for unknown node ({}). This is a bug. Message sent: {}", - addr, - message, - ); - return Poll::Ready(Ok(())); - }; - - match node.poll_ready_unpin(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(x)) => match x {}, - Poll::Pending => { - self.item = Some((addr, message)); - return Poll::Pending; - } - } - - match node.start_send_unpin(message) { - Ok(()) => {} - Err(x) => match x {}, - } - - match node.poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(x)) => match x {}, - Poll::Pending => { - self.flush_node = Some(addr); - return Poll::Pending; - } - } - } - - Poll::Ready(Ok(())) - } -} - -impl Sink<(Multiaddr, String)> for Dispatcher { - type Error = Infallible; - - fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - self.try_empty_buffer(cx) - } - - fn start_send(mut self: Pin<&mut Self>, item: (Multiaddr, String)) -> Result<(), Self::Error> { - let overrun = self.item.replace(item).is_some(); - - if overrun { - log::error!( - target: "telemetry", - "Received another message while the previous one has not finished processing. \ - This is a bug", - ); - } - - Ok(()) - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.try_empty_buffer(cx) - } - - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let mut new_pool = HashMap::with_capacity(self.pool.len()); - - for (addr, mut node) in self.pool.drain() { - match node.poll_close_unpin(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(x)) => match x {}, - Poll::Pending => { - new_pool.insert(addr, node); - } - } - } - - let _ = std::mem::replace(&mut self.pool, new_pool); - - if self.pool.is_empty() { - Poll::Ready(Ok(())) - } else { - Poll::Pending - } - } -} diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 98365397b06ab..76bb4a878ee4b 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -48,13 +48,11 @@ pub use libp2p::wasm_ext::ExtTransport; pub use serde_json; pub use tracing; -mod dispatcher; mod endpoints; mod layer; mod node; mod transport; -use dispatcher::*; pub use endpoints::*; pub use layer::*; use node::*; @@ -177,7 +175,7 @@ impl TelemetryWorker { } } - let mut node_pool: Dispatcher = existing_nodes + let mut node_pool: HashMap = existing_nodes .iter() .map(|addr| { let (connection_messages, connection_notifiers) = node_args @@ -193,7 +191,7 @@ impl TelemetryWorker { }) .collect(); - let _ = receiver + let mut stream = receiver .filter_map(|(id, verbosity, message): (Id, u8, String)| { if let Some(nodes) = node_map.get(&id) { future::ready(Some((verbosity, message, nodes))) @@ -235,11 +233,20 @@ impl TelemetryWorker { stream::iter(to_send) }, - ) - .map(|x| Ok(x)) - .boxed() - .forward(&mut node_pool) - .await; + ); + + while let Some((addr, message)) = stream.next().await { + if let Some(node) = node_pool.get_mut(&addr) { + let _ = node.send(message).await; + } else { + log::error!( + target: "telemetry", + "Received message for unknown node ({}). This is a bug. Message sent: {}", + addr, + message, + ); + } + } log::error!( target: "telemetry", From 5c733cc299ed65052dfff9dc2ddb2cec10c4c052 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 11:41:25 +0100 Subject: [PATCH 191/222] Re-introduce ts field as suggested --- Cargo.lock | 1 + client/telemetry/Cargo.toml | 1 + client/telemetry/src/layer.rs | 3 ++- client/telemetry/src/node.rs | 8 +++++++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4cc0d1bf60432..23e80f41d77ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7506,6 +7506,7 @@ dependencies = [ name = "sc-telemetry" version = "2.0.0" dependencies = [ + "chrono", "futures 0.3.8", "futures-timer 3.0.2", "libp2p", diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index a6e70a114a494..e43456cdf0fc4 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -30,3 +30,4 @@ tracing = "0.1.10" tracing-subscriber = "0.2.13" serde_json = "1.0.41" sp-utils = { version = "2.0.0", path = "../../primitives/utils" } +chrono = "0.4.19" diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index cef99917ffcb0..9cc47e91bdfd0 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -128,8 +128,9 @@ impl<'a> tracing::field::Visit for TelemetryAttrsVisitor<'a> { fn record_str(&mut self, field: &tracing::field::Field, value: &str) { if field.name() == "json" { (*self.0).json = Some(format!( - r#"{{"id":{},"payload":{}}}"#, + r#"{{"id":{},"ts":{:?},"payload":{}}}"#, self.0.id.into_u64(), + chrono::Local::now().to_rfc3339().to_string(), value, )); } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index bb75565d5b64a..296b71b1afdb7 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -172,11 +172,17 @@ where let _ = sender.send(()); } + fn with_ts(json: &ConnectionMessage) -> ConnectionMessage { + let mut json = json.clone(); + json.insert("ts".to_string(), chrono::Local::now().to_rfc3339().into()); + json + } + let buf = self .connection_messages .iter() .cloned() - .filter_map(|json| match serde_json::to_vec(&json) { + .filter_map(|json| match serde_json::to_vec(&with_ts(&json)) { Ok(message) => Some(message), Err(err) => { log::error!( From f6fa4a1c377e3f17aa9ae4e7cfc41829da19272a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 12:59:33 +0100 Subject: [PATCH 192/222] Separate span from TelemetryHandle so we can re-enter at will --- bin/node/cli/src/browser.rs | 7 ++++- client/cli/src/config.rs | 5 +++- client/cli/src/lib.rs | 6 ++-- client/cli/src/runner.rs | 5 +++- client/service/src/builder.rs | 6 ++-- client/service/src/config.rs | 2 ++ client/service/src/task_manager/mod.rs | 16 +++++++++-- client/telemetry/src/lib.rs | 39 +++++++++++++++++--------- utils/browser/src/lib.rs | 5 +++- 9 files changed, 66 insertions(+), 25 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index e035f364bd41d..9c838e06847ab 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -41,7 +41,12 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu None => crate::chain_spec::development_config(), }; - let mut config = browser_configuration(chain_spec, Some(telemetry_worker.handle())).await?; + let (telemetry_handle, telemetry_span) = telemetry_worker.handle(); + let mut config = browser_configuration( + chain_spec, + Some(telemetry_handle), + Some(telemetry_span), + ).await?; config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 7ccfa815f69fe..a7b483d006539 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -33,6 +33,7 @@ use sc_service::config::{ TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; use sc_service::{ChainSpec, TracingReceiver}; +use sc_telemetry::{TelemetryHandle, TelemetrySpan}; use sc_tracing::logging::GlobalLoggerBuilder; use std::net::SocketAddr; use std::path::PathBuf; @@ -452,7 +453,8 @@ pub trait CliConfiguration: Sized { &self, cli: &C, task_executor: TaskExecutor, - telemetry_handle: Option, + telemetry_handle: Option, + telemetry_span: Option, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; @@ -523,6 +525,7 @@ pub trait CliConfiguration: Sized { base_path: Some(base_path), informant_output_format: Default::default(), telemetry_handle, + telemetry_span, }) } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index aba06548054dc..4818355b49b4b 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -37,6 +37,7 @@ pub use params::*; pub use runner::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; +use sc_telemetry::{TelemetryHandle, TelemetrySpan}; pub use sc_tracing::logging::GlobalLoggerBuilder; pub use sp_version::RuntimeVersion; use std::io::Write; @@ -209,9 +210,10 @@ pub trait SubstrateCli: Sized { &self, command: &T, task_executor: TaskExecutor, - telemetry_handle: Option, + telemetry_handle: Option, + telemetry_span: Option, ) -> error::Result { - command.create_configuration(self, task_executor, telemetry_handle) + command.create_configuration(self, task_executor, telemetry_handle, telemetry_span) } /// Create a runner for the command provided in argument. This will create a Configuration and diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index d04058a2b6aee..c9bc9b79702b8 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -135,11 +135,14 @@ impl Runner { } }; + let (telemetry_handle, telemetry_span) = telemetry_worker.handle(); + Ok(Runner { config: command.create_configuration( cli, task_executor.into(), - Some(telemetry_worker.handle()), + Some(telemetry_handle), + Some(telemetry_span), )?, tokio_runtime, telemetry_worker, diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 7228f103af4ad..ae02eb2dc20dc 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -302,7 +302,7 @@ pub fn new_full_parts( let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - TaskManager::new(config.task_executor.clone(), registry)? + TaskManager::new(config.task_executor.clone(), registry, config.telemetry_span.clone())? }; let executor = NativeExecutor::::new( @@ -369,7 +369,7 @@ pub fn new_light_parts( let keystore_container = KeystoreContainer::new(&config.keystore)?; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - TaskManager::new(config.task_executor.clone(), registry)? + TaskManager::new(config.task_executor.clone(), registry, config.telemetry_span.clone())? }; let executor = NativeExecutor::::new( @@ -680,7 +680,7 @@ fn init_telemetry>( network: Arc::Hash>>, client: Arc, ) -> Option { - let telemetry_handle = config.telemetry_handle.as_mut()?; + let telemetry_handle = config.telemetry_handle.take()?; let endpoints = match config.telemetry_endpoints.clone() { // Don't initialise telemetry if `telemetry_endpoints` == Some([]) diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 911a6350128ba..250ff50e92bb4 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -94,6 +94,8 @@ pub struct Configuration { /// This is a handle to a `TelemetryWorker` instance. It is used to initialize the telemetry for /// a substrate node. pub telemetry_handle: Option, + /// A handle representing a telemetry span, with the capability to enter the span if it exists. + pub telemetry_span: Option, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index d1ab8c9c2a7ee..4d9e16d900327 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -34,6 +34,7 @@ use prometheus_endpoint::{ use sp_utils::mpsc::{TracingUnboundedSender, TracingUnboundedReceiver, tracing_unbounded}; use tracing_futures::Instrument; use crate::{config::{TaskExecutor, TaskType, JoinFuture}, Error}; +use sc_telemetry::TelemetrySpan; mod prometheus_future; #[cfg(test)] @@ -46,6 +47,7 @@ pub struct SpawnTaskHandle { executor: TaskExecutor, metrics: Option, task_notifier: TracingUnboundedSender, + telemetry_span: Option, } impl SpawnTaskHandle { @@ -89,7 +91,10 @@ impl SpawnTaskHandle { metrics.tasks_ended.with_label_values(&[name, "finished"]).inc_by(0); } + let telemetry_span = self.telemetry_span.clone(); let future = async move { + let _telemetry_entered = telemetry_span.as_ref().map(|x| x.enter()); + if let Some(metrics) = metrics { // Add some wrappers around `task`. let task = { @@ -228,14 +233,17 @@ pub struct TaskManager { /// terminates and gracefully shutdown. Also ends the parent `future()` if a child's essential /// task fails. children: Vec, + /// A telemetry handle used to enter the telemetry span when a task is spawned. + telemetry_span: Option, } impl TaskManager { - /// If a Prometheus registry is passed, it will be used to report statistics about the - /// service tasks. + /// If a Prometheus registry is passed, it will be used to report statistics about the + /// service tasks. pub(super) fn new( executor: TaskExecutor, - prometheus_registry: Option<&Registry> + prometheus_registry: Option<&Registry>, + telemetry_span: Option, ) -> Result { let (signal, on_exit) = exit_future::signal(); @@ -264,6 +272,7 @@ impl TaskManager { task_notifier, completion_future, children: Vec::new(), + telemetry_span, }) } @@ -274,6 +283,7 @@ impl TaskManager { executor: self.executor.clone(), metrics: self.metrics.clone(), task_notifier: self.task_notifier.clone(), + telemetry_span: self.telemetry_span.clone(), } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 76bb4a878ee4b..6d956070068c1 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -79,6 +79,9 @@ pub(crate) type InitPayload = ( mpsc::UnboundedReceiver, ); +/// A handle representing a telemetry span, with the capability to enter the span if it exists. +pub type TelemetrySpan = tracing::Span; + /// Telemetry worker. /// /// It should be ran as a background task using the [`TelemetryWorker::run`] method. This method @@ -118,8 +121,15 @@ impl TelemetryWorker { /// Get a handle to this [`TelemetryWorker`]. /// /// This is used when you want to register a new telemetry for a Substrate node. - pub fn handle(&self) -> TelemetryHandle { - TelemetryHandle(self.init_sender.clone()) + pub fn handle(&self) -> (TelemetryHandle, TelemetrySpan) { + let span = tracing::info_span!(TELEMETRY_LOG_SPAN); + ( + TelemetryHandle { + span: span.clone(), + sender: self.init_sender.clone(), + }, + span, + ) } /// Get a clone of the channel's `Sender` used to send telemetry events. @@ -256,8 +266,11 @@ impl TelemetryWorker { } /// Handle to the [`TelemetryWorker`] thats allows initializing the telemetry for a Substrate node. -#[derive(Clone, Debug)] -pub struct TelemetryHandle(mpsc::UnboundedSender); +#[derive(Debug)] +pub struct TelemetryHandle { + span: tracing::Span, + sender: mpsc::UnboundedSender, +} impl TelemetryHandle { /// Initialize the telemetry with the endpoints provided in argument for the current substrate @@ -271,21 +284,21 @@ impl TelemetryHandle { /// The `connection_message` argument is a JSON object that is sent every time the connection /// (re-)establishes. pub fn start_telemetry( - &mut self, + self, endpoints: TelemetryEndpoints, connection_message: ConnectionMessage, ) -> TelemetryConnectionNotifier { - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - let (sender, receiver) = mpsc::unbounded(); - let connection_notifier = TelemetryConnectionNotifier(sender); + let Self { span, sender } = self; + + let (connection_notifier, receiver) = { + let (sender, receiver) = mpsc::unbounded(); + (TelemetryConnectionNotifier(sender), receiver) + }; match span.id() { Some(id) => { - match self - .0 - .unbounded_send((id.clone(), endpoints, connection_message, receiver)) - { - Ok(()) => tracing::dispatcher::get_default(move |dispatch| dispatch.enter(&id)), + match sender.unbounded_send((id.clone(), endpoints, connection_message, receiver)) { + Ok(()) => {} Err(err) => error!( target: "telemetry", "Could not initialize telemetry: \ diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 64ede13331b53..28e0f6cf44d24 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -23,6 +23,7 @@ use sc_service::{ config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration}, GenericChainSpec, RuntimeGenesis }; +use sc_telemetry::{TelemetryHandle, TelemetrySpan}; use sc_tracing::logging::GlobalLoggerBuilder; use wasm_bindgen::prelude::*; use futures::{ @@ -49,7 +50,8 @@ pub fn init_logging_and_telemetry( /// This configuration contains good defaults for a browser light client. pub async fn browser_configuration( chain_spec: GenericChainSpec, - telemetry_handle: Option, + telemetry_handle: Option, + telemetry_span: Option, ) -> Result> where G: RuntimeGenesis + 'static, @@ -81,6 +83,7 @@ where }).into(), telemetry_external_transport: Some(transport), telemetry_handle, + telemetry_span, role: Role::Light, database: { info!("Opening Indexed DB database '{}'...", name); From 494c02486c8010670c840582aa8e60ebedcded47 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:02:51 +0100 Subject: [PATCH 193/222] Fix: replace std Instant not working in WASM --- client/network/src/request_responses.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index fbdb1432379ed..d30e398916419 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -52,8 +52,9 @@ use libp2p::{ }; use std::{ borrow::Cow, collections::{hash_map::Entry, HashMap}, convert::TryFrom as _, io, iter, - pin::Pin, task::{Context, Poll}, time::{Duration, Instant}, + pin::Pin, task::{Context, Poll}, time::Duration, }; +use wasm_timer::Instant; pub use libp2p::request_response::{InboundFailure, OutboundFailure, RequestId}; From 280a5b66e52cdc88f1bfe00b1ccb5b4f21e9c046 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:03:13 +0100 Subject: [PATCH 194/222] Revert test on browser --- bin/node/cli/browser-demo/build.sh | 2 +- bin/node/cli/src/browser.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh index 544b16333aeb2..8840106daeb5c 100755 --- a/bin/node/cli/browser-demo/build.sh +++ b/bin/node/cli/browser-demo/build.sh @@ -2,4 +2,4 @@ set -e -x cargo +nightly build --release -p node-cli --target wasm32-unknown-unknown --no-default-features --features browser -Z features=itarget wasm-bindgen ../../../../target/wasm32-unknown-unknown/release/node_cli.wasm --out-dir pkg --target web -python -m http.server 8080 +python -m http.server 8000 diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 9c838e06847ab..3dc4390568a82 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -42,12 +42,11 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu }; let (telemetry_handle, telemetry_span) = telemetry_worker.handle(); - let mut config = browser_configuration( + let config = browser_configuration( chain_spec, Some(telemetry_handle), Some(telemetry_span), ).await?; - config.telemetry_endpoints = Some(sc_telemetry::TelemetryEndpoints::new(vec![("ws://127.0.0.1:8000/submit".to_owned(), 10)]).unwrap()); info!("Substrate browser node"); info!("✌️ version {}", config.impl_version); From d4d11354c9a057530c9bd3f2655f25f48f38079f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:05:07 +0100 Subject: [PATCH 195/222] Revert "Revert "Spawn 2 nodes instead of one"" This reverts commit 00f34bdd3f36a3dfe8eddd6c5a7f62b7a762f22e. --- bin/node/cli/src/command.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index ed3aff88c75de..fe8613a0b5f1a 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -73,10 +73,18 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } + // TODO revert after test + let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetries.clone()).unwrap(); + let mut task_manager = match config.role { + Role::Light => service::new_light(config).unwrap(), + _ => service::new_full(config).unwrap(), + }; + let task_manager2 = match config2.role { + Role::Light => service::new_light(config2).unwrap(), + _ => service::new_full(config2).unwrap(), + }; + task_manager.add_child(task_manager2); + Ok(task_manager) }) } Some(Subcommand::Inspect(cmd)) => { From 351e3f17575d63ac9acefe403546d60f6d232c98 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:15:48 +0100 Subject: [PATCH 196/222] Allows getting a new telemetry handle from the runner --- client/cli/src/runner.rs | 12 ++++++++++-- client/telemetry/src/lib.rs | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index c9bc9b79702b8..f17e5f0189809 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -25,6 +25,7 @@ use futures::select; use futures::{future, future::FutureExt, Future}; use log::info; use sc_service::{Configuration, TaskType, TaskManager}; +use sc_telemetry::{TelemetryHandle, TelemetrySpan, TelemetryWorker}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; @@ -112,7 +113,7 @@ where pub struct Runner { config: Configuration, tokio_runtime: tokio::runtime::Runtime, - telemetry_worker: sc_telemetry::TelemetryWorker, + telemetry_worker: TelemetryWorker, phantom: PhantomData, } @@ -121,7 +122,7 @@ impl Runner { pub fn new( cli: &C, command: &T, - telemetry_worker: sc_telemetry::TelemetryWorker, + telemetry_worker: TelemetryWorker, ) -> Result> { let tokio_runtime = build_runtime()?; let runtime_handle = tokio_runtime.handle().clone(); @@ -223,4 +224,11 @@ impl Runner { pub fn config_mut(&mut self) -> &mut Configuration { &mut self.config } + + /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. + /// + /// This is used when you want to register a new telemetry for a Substrate node. + pub fn telemetry_handle(&self) -> (TelemetryHandle, TelemetrySpan) { + self.telemetry_worker.handle() + } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6d956070068c1..39bcd15d765a7 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -118,7 +118,7 @@ impl TelemetryWorker { }) } - /// Get a handle to this [`TelemetryWorker`]. + /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. /// /// This is used when you want to register a new telemetry for a Substrate node. pub fn handle(&self) -> (TelemetryHandle, TelemetrySpan) { From 47132f91217f3f193b3cc772f205ec27f26510eb Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:16:20 +0100 Subject: [PATCH 197/222] Fix test code --- bin/node/cli/src/command.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index fe8613a0b5f1a..51ff929ce2d5e 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -72,9 +72,10 @@ pub fn run() -> Result<()> { match &cli.subcommand { None => { let runner = cli.create_runner(&cli.run)?; + let (telemetry_handle, telemetry_span) = runner.telemetry_handle(); runner.run_node_until_exit(|config| async move { // TODO revert after test - let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetries.clone()).unwrap(); + let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), Some(telemetry_handle), Some(telemetry_span)).unwrap(); let mut task_manager = match config.role { Role::Light => service::new_light(config).unwrap(), _ => service::new_full(config).unwrap(), From 8295bc1e3f222b07c9adced8e98840fd35e586c6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 14:17:15 +0100 Subject: [PATCH 198/222] Revert test code --- bin/node/cli/src/command.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index 51ff929ce2d5e..ed3aff88c75de 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -72,20 +72,11 @@ pub fn run() -> Result<()> { match &cli.subcommand { None => { let runner = cli.create_runner(&cli.run)?; - let (telemetry_handle, telemetry_span) = runner.telemetry_handle(); runner.run_node_until_exit(|config| async move { - // TODO revert after test - let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), Some(telemetry_handle), Some(telemetry_span)).unwrap(); - let mut task_manager = match config.role { - Role::Light => service::new_light(config).unwrap(), - _ => service::new_full(config).unwrap(), - }; - let task_manager2 = match config2.role { - Role::Light => service::new_light(config2).unwrap(), - _ => service::new_full(config2).unwrap(), - }; - task_manager.add_child(task_manager2); - Ok(task_manager) + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } }) } Some(Subcommand::Inspect(cmd)) => { From 8f77aa0da9a1e2519fa8185796d80fbbb0c8d3b7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 15:11:46 +0100 Subject: [PATCH 199/222] Fix tests --- client/service/src/task_manager/tests.rs | 34 +++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index 0509392ce3888..f0ede1fc389a5 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -81,13 +81,17 @@ async fn run_background_task_blocking(duration: Duration, _keep_alive: impl Any) } } +fn new_task_manager(task_executor: TaskExecutor) -> TaskManager { + TaskManager::new(task_executor, None, None).unwrap() +} + #[test] fn ensure_tasks_are_awaited_on_shutdown() { let mut runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let task_manager = TaskManager::new(task_executor, None).unwrap(); + let task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -106,7 +110,7 @@ fn ensure_keep_alive_during_shutdown() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor, None).unwrap(); + let mut task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); task_manager.keep_alive(drop_tester.new_ref()); @@ -125,7 +129,7 @@ fn ensure_blocking_futures_are_awaited_on_shutdown() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let task_manager = TaskManager::new(task_executor, None).unwrap(); + let task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn( @@ -150,7 +154,7 @@ fn ensure_no_task_can_be_spawn_after_terminate() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor, None).unwrap(); + let mut task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -171,7 +175,7 @@ fn ensure_task_manager_future_ends_when_task_manager_terminated() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor, None).unwrap(); + let mut task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -192,7 +196,7 @@ fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor, None).unwrap(); + let mut task_manager = new_task_manager(task_executor); let spawn_handle = task_manager.spawn_handle(); let spawn_essential_handle = task_manager.spawn_essential_handle(); let drop_tester = DropTester::new(); @@ -215,10 +219,10 @@ fn ensure_children_tasks_ends_when_task_manager_terminated() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor.clone(), None).unwrap(); - let child_1 = TaskManager::new(task_executor.clone(), None).unwrap(); + let mut task_manager = new_task_manager(task_executor.clone()); + let child_1 = new_task_manager(task_executor.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = TaskManager::new(task_executor.clone(), None).unwrap(); + let child_2 = new_task_manager(task_executor.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); @@ -244,11 +248,11 @@ fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails() let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor.clone(), None).unwrap(); - let child_1 = TaskManager::new(task_executor.clone(), None).unwrap(); + let mut task_manager = new_task_manager(task_executor.clone()); + let child_1 = new_task_manager(task_executor.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); let spawn_essential_handle_child_1 = child_1.spawn_essential_handle(); - let child_2 = TaskManager::new(task_executor.clone(), None).unwrap(); + let child_2 = new_task_manager(task_executor.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); @@ -275,10 +279,10 @@ fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() { let handle = runtime.handle().clone(); let task_executor: TaskExecutor = (move |future, _| handle.spawn(future).map(|_| ())).into(); - let mut task_manager = TaskManager::new(task_executor.clone(), None).unwrap(); - let child_1 = TaskManager::new(task_executor.clone(), None).unwrap(); + let mut task_manager = new_task_manager(task_executor.clone()); + let child_1 = new_task_manager(task_executor.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = TaskManager::new(task_executor.clone(), None).unwrap(); + let child_2 = new_task_manager(task_executor.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); From 0bd4ce7a5e0e4a2b3897be62ecc7b47f6f1804e8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 8 Jan 2021 15:20:35 +0100 Subject: [PATCH 200/222] Fix more tests --- client/service/test/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index a5e0067640239..c34995962a4f1 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -265,6 +265,7 @@ fn node_config Date: Thu, 14 Jan 2021 11:49:05 +0100 Subject: [PATCH 201/222] Doc & warn missing doc --- client/tracing/src/lib.rs | 7 +++++++ client/tracing/src/logging/layers/console_log.rs | 2 ++ 2 files changed, 9 insertions(+) diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index 75a31c91a1bfc..ebec8f2a8716a 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -26,6 +26,8 @@ //! //! Currently we provide `Log` (default), `Telemetry` variants for `Receiver` +#![warn(missing_docs)] + pub mod logging; use rustc_hash::FxHashMap; @@ -86,10 +88,15 @@ pub trait TraceHandler: Send + Sync { /// Represents a tracing event, complete with values #[derive(Debug)] pub struct TraceEvent { + /// Name of the event. pub name: &'static str, + /// Target of the event. pub target: String, + /// Level of the event. pub level: Level, + /// Values for this event. pub values: Values, + /// Id of the parent tracing event, if any. pub parent_id: Option, } diff --git a/client/tracing/src/logging/layers/console_log.rs b/client/tracing/src/logging/layers/console_log.rs index bb702dc912bc2..be992ae814235 100644 --- a/client/tracing/src/logging/layers/console_log.rs +++ b/client/tracing/src/logging/layers/console_log.rs @@ -30,6 +30,7 @@ use tracing_subscriber::{ }; use wasm_bindgen::prelude::*; +/// A `Layer` that display logs in the browser's console. pub struct ConsoleLogLayer { event_format: EventFormat, fmt_fields: N, @@ -37,6 +38,7 @@ pub struct ConsoleLogLayer ConsoleLogLayer { + /// Create a new [`ConsoleLogLayer`] using the `EventFormat` provided in argument. pub fn new(event_format: EventFormat) -> Self { Self { event_format, From 7770d461c42320fd6c659b7df5b7def371963fa8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 11:51:35 +0100 Subject: [PATCH 202/222] Update client/tracing/src/logging/directives.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/tracing/src/logging/directives.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 2a966ae693b1d..50861797c0d67 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -98,12 +98,14 @@ pub fn reload_filter() -> Result<(), String> { /// /// Includes substrate defaults and CLI supplied directives. pub fn reset_log_filter() -> Result<(), String> { - *CURRENT_DIRECTIVES - .get_or_init(|| Mutex::new(Vec::new())) - .lock() = DEFAULT_DIRECTIVES + let directive = DEFAULT_DIRECTIVES .get_or_init(|| Mutex::new(Vec::new())) .lock() .clone(); + + *CURRENT_DIRECTIVES + .get_or_init(|| Mutex::new(Vec::new())) + .lock() = directive; reload_filter() } From b33628b09a87f55e34913ca440956e4e057d78de Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:35:56 +0100 Subject: [PATCH 203/222] Specialized struct for the connection message --- client/service/src/builder.rs | 40 +++++++++++------------- client/telemetry/src/lib.rs | 57 ++++++++++++++++++++++++++++++----- client/telemetry/src/node.rs | 22 +++++++------- 3 files changed, 77 insertions(+), 42 deletions(-) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index ae02eb2dc20dc..d9355c90dfb97 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -51,7 +51,7 @@ use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{telemetry, TelemetryConnectionNotifier, SUBSTRATE_INFO}; +use sc_telemetry::{telemetry, ConnectionMessage, TelemetryConnectionNotifier, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; @@ -690,28 +690,22 @@ fn init_telemetry>( let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default(); - let is_authority = config.role.is_authority(); - let network_id = network.local_peer_id().to_base58(); - let name = config.network.node_name.clone(); - let impl_name = config.impl_name.clone(); - let impl_version = config.impl_version.clone(); - let chain_name = config.chain_spec.name().to_owned(); - let startup_time = SystemTime::UNIX_EPOCH.elapsed() - .map(|dur| dur.as_millis()) - .unwrap_or(0); - - let mut obj = serde_json::Map::new(); - obj.insert("name".to_string(), name.clone().into()); - obj.insert("implementation".to_string(), impl_name.clone().into()); - obj.insert("version".to_string(), impl_version.clone().into()); - obj.insert("config".to_string(), "".into()); - obj.insert("chain".to_string(), chain_name.clone().into()); - obj.insert("genesis_hash".to_string(), format!("{:?}", genesis_hash).into()); - obj.insert("authority".to_string(), is_authority.into()); - obj.insert("startup_time".to_string(), startup_time.to_string().into()); - obj.insert("network_id".to_string(), network_id.clone().into()); - - Some(telemetry_handle.start_telemetry(endpoints, obj)) + Some(telemetry_handle.start_telemetry( + endpoints, + ConnectionMessage { + name: config.network.node_name.to_owned(), + implementation: config.impl_name.to_owned(), + version: config.impl_version.to_owned(), + config: String::new(), + chain: config.chain_spec.name().to_owned(), + genesis_hash: format!("{:?}", genesis_hash), + authority: config.role.is_authority(), + startup_time: SystemTime::UNIX_EPOCH.elapsed() + .map(|dur| dur.as_millis()) + .unwrap_or(0).to_string(), + network_id: network.local_peer_id().to_base58(), + }, + )) } fn gen_handler( diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 39bcd15d765a7..f6fa92399aa76 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -35,6 +35,7 @@ use futures::{channel::mpsc, prelude::*}; use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; +use serde::Serialize; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use std::{ collections::{HashMap, HashSet}, @@ -82,6 +83,29 @@ pub(crate) type InitPayload = ( /// A handle representing a telemetry span, with the capability to enter the span if it exists. pub type TelemetrySpan = tracing::Span; +/// Message sent when the connection (re-)establishes. +#[derive(Debug, Serialize)] +pub struct ConnectionMessage { + /// Node's name. + pub name: String, + /// Node's implementation. + pub implementation: String, + /// Node's version. + pub version: String, + /// Node's configuration. + pub config: String, + /// Node's chain. + pub chain: String, + /// Node's genesis hash. + pub genesis_hash: String, + /// Node is an authority. + pub authority: bool, + /// Node's startup time. + pub startup_time: String, + /// Node's network ID. + pub network_id: String, +} + /// Telemetry worker. /// /// It should be ran as a background task using the [`TelemetryWorker::run`] method. This method @@ -152,13 +176,16 @@ impl TelemetryWorker { let mut node_map: HashMap> = HashMap::new(); let mut node_args: HashMap< Multiaddr, - (Vec, Vec), + ( + Vec>, + Vec, + ), > = HashMap::new(); let mut existing_nodes: HashSet = HashSet::new(); // initialize the telemetry nodes init_receiver.close(); - while let Some((id, endpoints, mut connection_message, mut connection_notifiers_rx)) = + while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = init_receiver.next().await { let endpoints = endpoints.0; @@ -166,21 +193,35 @@ impl TelemetryWorker { connection_notifiers_rx.close(); let connection_notifier_senders: Vec<_> = connection_notifiers_rx.collect().await; - connection_message.insert("msg".into(), "system.connected".into()); - for (addr, verbosity) in endpoints { node_map .entry(id.clone()) .or_insert_with(Vec::new) .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); - let mut obj = serde_json::Map::new(); - obj.insert("id".to_string(), id.into_u64().into()); - obj.insert("payload".to_string(), connection_message.clone().into()); + let (connection_messages, connection_notifiers) = node_args .entry(addr.clone()) .or_insert_with(|| (Vec::new(), Vec::new())); - connection_messages.push(obj); + + match serde_json::to_value(&connection_message) { + Ok(serde_json::Value::Object(mut value)) => { + value.insert("msg".into(), "system.connected".into()); + let mut obj = serde_json::Map::new(); + obj.insert("id".to_string(), id.into_u64().into()); + obj.insert("payload".to_string(), value.into()); + connection_messages.push(obj); + } + Ok(_) => unreachable!("ConnectionMessage always serialize to an object; qed"), + Err(err) => { + log::error!( + target: "telemetry", + "Could not serialize connection message: {}", + err, + ); + } + } + connection_notifiers.extend(connection_notifier_senders.clone()); } } diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 296b71b1afdb7..fdaedb70d3c37 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -23,7 +23,6 @@ use libp2p::Multiaddr; use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; -pub(crate) type ConnectionMessage = serde_json::Map; pub(crate) type ConnectionNotifierSender = sp_utils::mpsc::TracingUnboundedSender<()>; /// Handler for a single telemetry node. @@ -46,7 +45,7 @@ pub(crate) struct Node { /// Transport used to establish new connections. transport: TTrans, /// Messages that are sent when the connection (re-)establishes. - connection_messages: Vec, + connection_messages: Vec>, /// Notifier for when the connection (re-)establishes. telemetry_connection_notifier: Vec, } @@ -84,7 +83,7 @@ impl Node { pub(crate) fn new( transport: TTrans, addr: Multiaddr, - connection_messages: Vec, + connection_messages: Vec>, telemetry_connection_notifier: Vec, ) -> Self { Node { @@ -172,17 +171,18 @@ where let _ = sender.send(()); } - fn with_ts(json: &ConnectionMessage) -> ConnectionMessage { - let mut json = json.clone(); - json.insert("ts".to_string(), chrono::Local::now().to_rfc3339().into()); - json - } - let buf = self .connection_messages .iter() - .cloned() - .filter_map(|json| match serde_json::to_vec(&with_ts(&json)) { + .map(|json| { + let mut json = json.clone(); + json.insert( + "ts".to_string(), + chrono::Local::now().to_rfc3339().into(), + ); + json + }) + .filter_map(|json| match serde_json::to_vec(&json) { Ok(message) => Some(message), Err(err) => { log::error!( From 853eb42a931cbb065e479860d88b1a52801f0855 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:38:15 +0100 Subject: [PATCH 204/222] Update client/telemetry/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index f6fa92399aa76..cbe060ac9018c 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -196,7 +196,7 @@ impl TelemetryWorker { for (addr, verbosity) in endpoints { node_map .entry(id.clone()) - .or_insert_with(Vec::new) + .or_default() .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); From a6fdb285b58c218775a66f7d1bb5bbe1d0816015 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:38:42 +0100 Subject: [PATCH 205/222] Update client/telemetry/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index cbe060ac9018c..8a5fca5bda87f 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -222,7 +222,7 @@ impl TelemetryWorker { } } - connection_notifiers.extend(connection_notifier_senders.clone()); + connection_notifiers.extend(connection_notifier_senders); } } From ab0e78df7d712244b256afde6ec4290e4a0a1d7a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:39:51 +0100 Subject: [PATCH 206/222] Update client/telemetry/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 8a5fca5bda87f..803f6f031bd15 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -447,7 +447,7 @@ macro_rules! format_fields_to_json { ( $k:literal => ? $v:expr $(,)? $(, $($t:tt)+ )? ) => {{ let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), std::format!("{:?}", &$v).into()); - let ok_map: $crate::serde_json::Result<_> = Ok(map); + $crate::serde_json::Result::Ok(map) ok_map $( .and_then(|mut prev_map| { From 007a41afb7942b3403774f3835b1045e793c26b3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:39:59 +0100 Subject: [PATCH 207/222] Update client/telemetry/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/telemetry/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 803f6f031bd15..45404ed0e22c3 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -448,7 +448,6 @@ macro_rules! format_fields_to_json { let mut map = $crate::serde_json::Map::new(); map.insert($k.into(), std::format!("{:?}", &$v).into()); $crate::serde_json::Result::Ok(map) - ok_map $( .and_then(|mut prev_map| { format_fields_to_json!($($t)*) From 36791405d17da654fea1b7fe35568cb9ac43ee7a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:41:54 +0100 Subject: [PATCH 208/222] Removed unneeded code --- client/telemetry/src/lib.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 45404ed0e22c3..23805a38745ba 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -196,7 +196,7 @@ impl TelemetryWorker { for (addr, verbosity) in endpoints { node_map .entry(id.clone()) - .or_default() + .or_default() .push((verbosity, addr.clone())); existing_nodes.insert(addr.clone()); @@ -259,7 +259,6 @@ impl TelemetryWorker { .flat_map( |(verbosity, message, nodes): (u8, String, &Vec<(u8, Multiaddr)>)| { let mut to_send = Vec::with_capacity(nodes.len()); - let before = Instant::now(); for (node_max_verbosity, addr) in nodes { if verbosity > *node_max_verbosity { @@ -275,13 +274,6 @@ impl TelemetryWorker { to_send.push((addr.clone(), message.clone())); } - if before.elapsed() > Duration::from_millis(200) { - log::warn!( - target: "telemetry", - "Processing one telemetry message took more than 200ms", - ); - } - stream::iter(to_send) }, ); From 0cbf0b832f357816af8f62ab361498d690b9d843 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:42:15 +0100 Subject: [PATCH 209/222] Revert "Update client/telemetry/src/lib.rs" This reverts commit a6fdb285b58c218775a66f7d1bb5bbe1d0816015. --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 23805a38745ba..13a2e7a1005f1 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -222,7 +222,7 @@ impl TelemetryWorker { } } - connection_notifiers.extend(connection_notifier_senders); + connection_notifiers.extend(connection_notifier_senders.clone()); } } From f1aa1a4f37ffff1f6fe6d11b899815c61ab3484c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:44:15 +0100 Subject: [PATCH 210/222] CLEANUP --- Cargo.lock | 1 - client/telemetry/Cargo.toml | 1 - client/telemetry/src/lib.rs | 2 -- client/telemetry/src/node.rs | 2 +- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bdb514f9b443..47d11cdbdcb26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7508,7 +7508,6 @@ version = "2.0.0" dependencies = [ "chrono", "futures 0.3.9", - "futures-timer 3.0.2", "libp2p", "log", "parking_lot 0.11.1", diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index d59a08a677e85..2c11bc62d00cd 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -17,7 +17,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = "0.11.1" futures = "0.3.9" -futures-timer = "3.0.1" wasm-timer = "0.2.5" libp2p = { version = "0.33.0", default-features = false, features = ["dns", "tcp-async-std", "wasm-ext", "websocket"] } log = "0.4.8" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 13a2e7a1005f1..8cbc2877f00bd 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -40,10 +40,8 @@ use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use std::{ collections::{HashMap, HashSet}, io, - time::Duration, }; use tracing::Id; -use wasm_timer::Instant; pub use libp2p::wasm_ext::ExtTransport; pub use serde_json; diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index fdaedb70d3c37..03df6c86afe23 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -17,11 +17,11 @@ // along with this program. If not, see . use futures::prelude::*; -use futures_timer::Delay; use libp2p::core::transport::Transport; use libp2p::Multiaddr; use rand::Rng as _; use std::{fmt, mem, pin::Pin, task::Context, task::Poll, time::Duration}; +use wasm_timer::Delay; pub(crate) type ConnectionNotifierSender = sp_utils::mpsc::TracingUnboundedSender<()>; From a626cecd42ad06b44a2b6642db6572ad07b56648 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 14 Jan 2021 12:57:36 +0100 Subject: [PATCH 211/222] Simplify stream --- client/telemetry/src/lib.rs | 71 ++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 8cbc2877f00bd..287efcdf4fccc 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -164,7 +164,7 @@ impl TelemetryWorker { /// This should be run in a background task. pub async fn run(self) { let Self { - receiver, + mut receiver, sender: _sender, mut init_receiver, init_sender: _init_sender, @@ -240,52 +240,41 @@ impl TelemetryWorker { }) .collect(); - let mut stream = receiver - .filter_map(|(id, verbosity, message): (Id, u8, String)| { - if let Some(nodes) = node_map.get(&id) { - future::ready(Some((verbosity, message, nodes))) + while let Some((id, verbosity, message)) = receiver.next().await { + let nodes = if let Some(nodes) = node_map.get(&id) { + nodes + } else { + log::error!( + target: "telemetry", + "Received telemetry log for unknown id ({:?}): {}", + id, + message, + ); + continue; + }; + + for (node_max_verbosity, addr) in nodes { + if verbosity > *node_max_verbosity { + log::trace!( + target: "telemetry", + "Skipping {} for log entry with verbosity {:?}", + addr, + verbosity, + ); + continue; + } + + if let Some(node) = node_pool.get_mut(&addr) { + let _ = node.send(message.clone()).await; } else { log::error!( target: "telemetry", - "Received telemetry log for unknown id ({:?}): {}", - id, + "Received message for unknown node ({}). This is a bug. \ + Message sent: {}", + addr, message, ); - future::ready(None) } - }) - .flat_map( - |(verbosity, message, nodes): (u8, String, &Vec<(u8, Multiaddr)>)| { - let mut to_send = Vec::with_capacity(nodes.len()); - - for (node_max_verbosity, addr) in nodes { - if verbosity > *node_max_verbosity { - log::trace!( - target: "telemetry", - "Skipping {} for log entry with verbosity {:?}", - addr, - verbosity, - ); - continue; - } - - to_send.push((addr.clone(), message.clone())); - } - - stream::iter(to_send) - }, - ); - - while let Some((addr, message)) = stream.next().await { - if let Some(node) = node_pool.get_mut(&addr) { - let _ = node.send(message).await; - } else { - log::error!( - target: "telemetry", - "Received message for unknown node ({}). This is a bug. Message sent: {}", - addr, - message, - ); } } From 09be76a4f31451c302d2e1036dfe09f8d4f0e431 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 12:56:33 +0100 Subject: [PATCH 212/222] WIP --- bin/node/cli/src/browser.rs | 3 +- bin/node/cli/src/service.rs | 13 +- client/cli/src/config.rs | 4 +- client/cli/src/lib.rs | 5 +- client/cli/src/runner.rs | 9 +- client/service/src/builder.rs | 101 ++++++----- client/service/src/config.rs | 17 +- client/service/src/lib.rs | 2 +- client/telemetry/src/layer.rs | 2 +- client/telemetry/src/lib.rs | 306 +++++++++++++++++++++------------- client/telemetry/src/node.rs | 4 +- utils/browser/src/lib.rs | 4 +- 12 files changed, 281 insertions(+), 189 deletions(-) diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 3dc4390568a82..93b6c55b1790c 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -41,11 +41,10 @@ async fn start_inner(chain_spec: Option, log_directives: String) -> Resu None => crate::chain_spec::development_config(), }; - let (telemetry_handle, telemetry_span) = telemetry_worker.handle(); + let telemetry_handle = telemetry_worker.handle(); let config = browser_configuration( chain_spec, Some(telemetry_handle), - Some(telemetry_span), ).await?; info!("Substrate browser node"); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 5e347f94e6d33..230b4ae35b266 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -34,7 +34,7 @@ use sp_runtime::traits::Block as BlockT; use futures::prelude::*; use sc_client_api::{ExecutorProvider, RemoteBackend}; use node_executor::Executor; -use sc_telemetry::TelemetryConnectionNotifier; +use sc_telemetry::{TelemetryConnectionNotifier, TelemetrySpan}; type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; @@ -58,9 +58,10 @@ pub fn new_partial(config: &Configuration) -> Result, ), grandpa::SharedVoterState, + Option, ) >, ServiceError> { - let (client, backend, keystore_container, task_manager) = + let (client, backend, keystore_container, task_manager, telemetry_span) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -156,7 +157,7 @@ pub fn new_partial(config: &Configuration) -> Result Result<( Arc::Hash>>, Arc>> ), ServiceError> { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = sc_service::new_light_parts::(&config)?; config.network.extra_sets.push(grandpa::grandpa_peers_set_config()); @@ -434,6 +436,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<( config, backend, network_status_sinks, system_rpc_tx, network: network.clone(), task_manager: &mut task_manager, + telemetry_span, })?; Ok((task_manager, rpc_handlers, telemetry_telemetry_connection_notifier, client, network, transaction_pool)) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index a7b483d006539..db4de9fe30f72 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -33,7 +33,7 @@ use sc_service::config::{ TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }; use sc_service::{ChainSpec, TracingReceiver}; -use sc_telemetry::{TelemetryHandle, TelemetrySpan}; +use sc_telemetry::TelemetryHandle; use sc_tracing::logging::GlobalLoggerBuilder; use std::net::SocketAddr; use std::path::PathBuf; @@ -454,7 +454,6 @@ pub trait CliConfiguration: Sized { cli: &C, task_executor: TaskExecutor, telemetry_handle: Option, - telemetry_span: Option, ) -> Result { let is_dev = self.is_dev()?; let chain_id = self.chain_id(is_dev)?; @@ -525,7 +524,6 @@ pub trait CliConfiguration: Sized { base_path: Some(base_path), informant_output_format: Default::default(), telemetry_handle, - telemetry_span, }) } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 55e8f92676a37..a4b0bd45727e2 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -37,7 +37,7 @@ pub use params::*; pub use runner::*; pub use sc_service::{ChainSpec, Role}; use sc_service::{Configuration, TaskExecutor}; -use sc_telemetry::{TelemetryHandle, TelemetrySpan}; +use sc_telemetry::TelemetryHandle; pub use sc_tracing::logging::GlobalLoggerBuilder; pub use sp_version::RuntimeVersion; use std::io::Write; @@ -215,9 +215,8 @@ pub trait SubstrateCli: Sized { command: &T, task_executor: TaskExecutor, telemetry_handle: Option, - telemetry_span: Option, ) -> error::Result { - command.create_configuration(self, task_executor, telemetry_handle, telemetry_span) + command.create_configuration(self, task_executor, telemetry_handle) } /// Create a runner for the command provided in argument. This will create a Configuration and diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index f17e5f0189809..0afe879641b4d 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -25,7 +25,7 @@ use futures::select; use futures::{future, future::FutureExt, Future}; use log::info; use sc_service::{Configuration, TaskType, TaskManager}; -use sc_telemetry::{TelemetryHandle, TelemetrySpan, TelemetryWorker}; +use sc_telemetry::{TelemetryHandle, TelemetryWorker}; use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; use std::marker::PhantomData; @@ -136,14 +136,13 @@ impl Runner { } }; - let (telemetry_handle, telemetry_span) = telemetry_worker.handle(); + let telemetry_handle = telemetry_worker.handle(); Ok(Runner { config: command.create_configuration( cli, task_executor.into(), Some(telemetry_handle), - Some(telemetry_span), )?, tokio_runtime, telemetry_worker, @@ -225,10 +224,10 @@ impl Runner { &mut self.config } - /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. + /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. TODO /// /// This is used when you want to register a new telemetry for a Substrate node. - pub fn telemetry_handle(&self) -> (TelemetryHandle, TelemetrySpan) { + pub fn telemetry_handle(&self) -> TelemetryHandle { self.telemetry_worker.handle() } } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index d9355c90dfb97..7a90d323c44f7 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -45,13 +45,19 @@ use sc_network::NetworkService; use sc_network::block_request_handler::{self, BlockRequestHandler}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ - Block as BlockT, SaturatedConversion, HashFor, Zero, BlockIdTo, + Block as BlockT, HashFor, Zero, BlockIdTo, }; use sp_api::{ProvideRuntimeApi, CallApiAt}; use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; use std::sync::Arc; use wasm_timer::SystemTime; -use sc_telemetry::{telemetry, ConnectionMessage, TelemetryConnectionNotifier, SUBSTRATE_INFO}; +use sc_telemetry::{ + telemetry, + ConnectionMessage, + TelemetryConnectionNotifier, + TelemetrySpan, + SUBSTRATE_INFO, +}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; @@ -178,6 +184,7 @@ type TFullParts = ( Arc>, KeystoreContainer, TaskManager, + Option, ); type TLightParts = ( @@ -186,6 +193,7 @@ type TLightParts = ( KeystoreContainer, TaskManager, Arc>, + Option, ); /// Light client backend type with a specific hash type. @@ -300,9 +308,14 @@ pub fn new_full_parts( { let keystore_container = KeystoreContainer::new(&config.keystore)?; + let telemetry_span = if config.telemetry_endpoints.is_some() { + Some(TelemetrySpan::new()) + } else { + None + }; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - TaskManager::new(config.task_executor.clone(), registry, config.telemetry_span.clone())? + TaskManager::new(config.task_executor.clone(), registry, telemetry_span.clone())? }; let executor = NativeExecutor::::new( @@ -356,6 +369,7 @@ pub fn new_full_parts( backend, keystore_container, task_manager, + telemetry_span, )) } @@ -367,9 +381,14 @@ pub fn new_light_parts( TExecDisp: NativeExecutionDispatch + 'static, { let keystore_container = KeystoreContainer::new(&config.keystore)?; + let telemetry_span = if config.telemetry_endpoints.is_some() { + Some(TelemetrySpan::new()) + } else { + None + }; let task_manager = { let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - TaskManager::new(config.task_executor.clone(), registry, config.telemetry_span.clone())? + TaskManager::new(config.task_executor.clone(), registry, telemetry_span.clone())? }; let executor = NativeExecutor::::new( @@ -406,7 +425,7 @@ pub fn new_light_parts( config.prometheus_config.as_ref().map(|config| config.registry.clone()), )?); - Ok((client, backend, keystore_container, task_manager, on_demand)) + Ok((client, backend, keystore_container, task_manager, on_demand, telemetry_span)) } /// Create an instance of db-backed client. @@ -458,6 +477,8 @@ pub fn new_client( pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { /// The service configuration. pub config: Configuration, + /// Telemetry span, if any. + pub telemetry_span: Option, /// A shared client returned by `new_full_parts`/`new_light_parts`. pub client: Arc, /// A shared backend returned by `new_full_parts`/`new_light_parts`. @@ -550,6 +571,7 @@ pub fn spawn_tasks( let SpawnTasksParams { mut config, task_manager, + telemetry_span, client, on_demand, backend, @@ -570,19 +592,15 @@ pub fn spawn_tasks( config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - let telemetry_connection_notifier = init_telemetry( - &mut config, - network.clone(), - client.clone(), - ); + let telemetry_connection_notifier = telemetry_span + .and_then(|span| init_telemetry( + &mut config, + span, + network.clone(), + client.clone(), + )); info!("📦 Highest known block at #{}", chain_info.best_number); - telemetry!( - SUBSTRATE_INFO; - "node.start"; - "height" => chain_info.best_number.saturated_into::(), - "best" => ?chain_info.best_hash - ); let spawn_handle = task_manager.spawn_handle(); @@ -662,7 +680,8 @@ async fn transaction_notifications( TExPool: MaintainedTransactionPool::Hash>, { // transaction notifications - transaction_pool.import_notification_stream() + transaction_pool + .import_notification_stream() .for_each(move |hash| { network.propagate_transaction(hash); let status = transaction_pool.status(); @@ -677,35 +696,33 @@ async fn transaction_notifications( fn init_telemetry>( config: &mut Configuration, + telemetry_span: TelemetrySpan, network: Arc::Hash>>, client: Arc, -) -> Option { - let telemetry_handle = config.telemetry_handle.take()?; - - let endpoints = match config.telemetry_endpoints.clone() { - // Don't initialise telemetry if `telemetry_endpoints` == Some([]) - Some(endpoints) if !endpoints.is_empty() => endpoints, - _ => return None, - }; - +) -> Option { + let endpoints = config.telemetry_endpoints()?.clone(); let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default(); + let connection_message = ConnectionMessage { + name: config.network.node_name.to_owned(), + implementation: config.impl_name.to_owned(), + version: config.impl_version.to_owned(), + config: String::new(), + chain: config.chain_spec.name().to_owned(), + genesis_hash: format!("{:?}", genesis_hash), + authority: config.role.is_authority(), + startup_time: SystemTime::UNIX_EPOCH.elapsed() + .map(|dur| dur.as_millis()) + .unwrap_or(0).to_string(), + network_id: network.local_peer_id().to_base58(), + }; - Some(telemetry_handle.start_telemetry( - endpoints, - ConnectionMessage { - name: config.network.node_name.to_owned(), - implementation: config.impl_name.to_owned(), - version: config.impl_version.to_owned(), - config: String::new(), - chain: config.chain_spec.name().to_owned(), - genesis_hash: format!("{:?}", genesis_hash), - authority: config.role.is_authority(), - startup_time: SystemTime::UNIX_EPOCH.elapsed() - .map(|dur| dur.as_millis()) - .unwrap_or(0).to_string(), - network_id: network.local_peer_id().to_base58(), - }, - )) + config.telemetry_handle + .as_mut() + .map(|handle| handle.start_telemetry( + telemetry_span, + endpoints, + connection_message, + )) } fn gen_handler( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 250ff50e92bb4..786968f286a8b 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -94,8 +94,6 @@ pub struct Configuration { /// This is a handle to a `TelemetryWorker` instance. It is used to initialize the telemetry for /// a substrate node. pub telemetry_handle: Option, - /// A handle representing a telemetry span, with the capability to enter the span if it exists. - pub telemetry_span: Option, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. @@ -198,9 +196,22 @@ impl Configuration { } /// Returns the prometheus metrics registry, if available. - pub fn prometheus_registry<'a>(&'a self) -> Option<&'a Registry> { + pub fn prometheus_registry(&self) -> Option<&Registry> { self.prometheus_config.as_ref().map(|config| &config.registry) } + + /// TODO + pub(crate) fn telemetry_endpoints(&self) -> Option<&TelemetryEndpoints> { + if self.telemetry_handle.is_none() { + return None; + } + + match self.telemetry_endpoints.as_ref() { + // Don't initialise telemetry if `telemetry_endpoints` == Some([]) + Some(endpoints) if !endpoints.is_empty() => Some(endpoints), + _ => None, + } + } } /// Available RPC methods. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 953f2095ca43a..2389a247abc10 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -159,7 +159,7 @@ impl NetworkStatusSinks { } -/// An imcomplete set of chain components, but enough to run the chain ops subcommands. +/// An incomplete set of chain components, but enough to run the chain ops subcommands. pub struct PartialComponents { /// A shared client instance. pub client: Arc, diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 9cc47e91bdfd0..2e86d86644da2 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -38,7 +38,7 @@ impl TelemetryLayer { telemetry_external_transport: Option, ) -> io::Result<(Self, TelemetryWorker)> { let worker = TelemetryWorker::new(telemetry_external_transport)?; - let sender = worker.sender(); + let sender = worker.message_sender(); Ok((Self(Mutex::new(sender)), worker)) } } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 287efcdf4fccc..b2d2aedc4e557 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -37,10 +37,7 @@ use libp2p::{wasm_ext, Multiaddr}; use log::{error, warn}; use serde::Serialize; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; -use std::{ - collections::{HashMap, HashSet}, - io, -}; +use std::{collections::HashMap, io}; use tracing::Id; pub use libp2p::wasm_ext::ExtTransport; @@ -71,15 +68,23 @@ pub const CONSENSUS_WARN: u8 = 4; /// Consensus INFO log level. pub const CONSENSUS_INFO: u8 = 1; -pub(crate) type InitPayload = ( - Id, - TelemetryEndpoints, - ConnectionMessage, - mpsc::UnboundedReceiver, -); +pub(crate) type TelemetryMessage = (Id, u8, String); /// A handle representing a telemetry span, with the capability to enter the span if it exists. -pub type TelemetrySpan = tracing::Span; +#[derive(Debug, Clone)] +pub struct TelemetrySpan(tracing::Span); + +impl TelemetrySpan { + /// TODO + pub fn enter(&self) -> tracing::span::Entered { + self.0.enter() + } + + /// TODO + pub fn new() -> Self { + Self(tracing::info_span!(TELEMETRY_LOG_SPAN)) + } +} /// Message sent when the connection (re-)establishes. #[derive(Debug, Serialize)] @@ -111,10 +116,10 @@ pub struct ConnectionMessage { /// handle will fail (without being fatal). #[derive(Debug)] pub struct TelemetryWorker { - receiver: mpsc::Receiver<(Id, u8, String)>, - sender: mpsc::Sender<(Id, u8, String)>, - init_receiver: mpsc::UnboundedReceiver, - init_sender: mpsc::UnboundedSender, + message_receiver: mpsc::Receiver, + message_sender: mpsc::Sender, + register_receiver: mpsc::UnboundedReceiver, + register_sender: mpsc::UnboundedSender, transport: WsTrans, } @@ -128,35 +133,30 @@ impl TelemetryWorker { /// > internal buffering going on. In the context of WebSockets, each `write` /// > must be one individual WebSockets frame. pub(crate) fn new(wasm_external_transport: Option) -> io::Result { - let (sender, receiver) = mpsc::channel(16); - let (init_sender, init_receiver) = mpsc::unbounded(); + let (message_sender, message_receiver) = mpsc::channel(16); + let (register_sender, register_receiver) = mpsc::unbounded(); Ok(Self { - receiver, - sender, - init_receiver, - init_sender, + message_receiver, + message_sender, + register_receiver, + register_sender, transport: initialize_transport(wasm_external_transport)?, }) } - /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. + /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. TODO /// /// This is used when you want to register a new telemetry for a Substrate node. - pub fn handle(&self) -> (TelemetryHandle, TelemetrySpan) { - let span = tracing::info_span!(TELEMETRY_LOG_SPAN); - ( - TelemetryHandle { - span: span.clone(), - sender: self.init_sender.clone(), - }, - span, - ) + pub fn handle(&self) -> TelemetryHandle { + TelemetryHandle { + message_sender: self.register_sender.clone(), + } } /// Get a clone of the channel's `Sender` used to send telemetry events. - pub(crate) fn sender(&self) -> mpsc::Sender<(Id, u8, String)> { - self.sender.clone() + pub(crate) fn message_sender(&self) -> mpsc::Sender { + self.message_sender.clone() } /// Run the telemetry worker. @@ -164,93 +164,124 @@ impl TelemetryWorker { /// This should be run in a background task. pub async fn run(self) { let Self { - mut receiver, - sender: _sender, - mut init_receiver, - init_sender: _init_sender, + mut message_receiver, + message_sender: _, + mut register_receiver, + register_sender: _, transport, } = self; let mut node_map: HashMap> = HashMap::new(); - let mut node_args: HashMap< - Multiaddr, - ( - Vec>, - Vec, - ), - > = HashMap::new(); - let mut existing_nodes: HashSet = HashSet::new(); - - // initialize the telemetry nodes - init_receiver.close(); - while let Some((id, endpoints, connection_message, mut connection_notifiers_rx)) = - init_receiver.next().await - { - let endpoints = endpoints.0; - - connection_notifiers_rx.close(); - let connection_notifier_senders: Vec<_> = connection_notifiers_rx.collect().await; - - for (addr, verbosity) in endpoints { - node_map - .entry(id.clone()) - .or_default() - .push((verbosity, addr.clone())); - existing_nodes.insert(addr.clone()); - - let (connection_messages, connection_notifiers) = node_args - .entry(addr.clone()) - .or_insert_with(|| (Vec::new(), Vec::new())); - - match serde_json::to_value(&connection_message) { - Ok(serde_json::Value::Object(mut value)) => { - value.insert("msg".into(), "system.connected".into()); - let mut obj = serde_json::Map::new(); - obj.insert("id".to_string(), id.into_u64().into()); - obj.insert("payload".to_string(), value.into()); - connection_messages.push(obj); + let mut node_pool: HashMap = HashMap::new(); + + // initialize the telemetry nodes and register new notifiers + async fn process_register( + input: Option, + node_pool: &mut HashMap>, + node_map: &mut HashMap>, + transport: WsTrans, + ) { + let input = if let Some(x) = input { + x + } else { + log::error!( + target: "telemetry", + "Unexpected end of stream. This is a bug.", + ); + return; + }; + + match input { + Register::Telemetry { + id, + endpoints, + connection_message, + } => { + let endpoints = endpoints.0; + + let connection_message = match serde_json::to_value(&connection_message) { + Ok(serde_json::Value::Object(mut value)) => { + value.insert("msg".into(), "system.connected".into()); + let mut obj = serde_json::Map::new(); + obj.insert("id".to_string(), id.into_u64().into()); + obj.insert("payload".to_string(), value.into()); + Some(obj) + } + Ok(_) => { + unreachable!("ConnectionMessage always serialize to an object; qed") + } + Err(err) => { + log::error!( + target: "telemetry", + "Could not serialize connection message: {}", + err, + ); + None + } + }; + + for (addr, verbosity) in endpoints { + node_map + .entry(id.clone()) + .or_default() + .push((verbosity, addr.clone())); + + let node = node_pool.entry(addr.clone()).or_insert_with(|| { + Node::new(transport.clone(), addr.clone(), Vec::new(), Vec::new()) + }); + + node.connection_messages.extend(connection_message.clone()); } - Ok(_) => unreachable!("ConnectionMessage always serialize to an object; qed"), - Err(err) => { - log::error!( - target: "telemetry", - "Could not serialize connection message: {}", - err, - ); + } + Register::Notifier { + addresses, + connection_notifier, + } => { + for addr in addresses { + if let Some(node) = node_pool.get_mut(&addr) { + node.telemetry_connection_notifier + .push(connection_notifier.clone()); + } else { + log::error!( + target: "telemetry", + "Received connection notifier for unknown node ({}). This is a bug.", + addr, + ); + } } } - - connection_notifiers.extend(connection_notifier_senders.clone()); } } - let mut node_pool: HashMap = existing_nodes - .iter() - .map(|addr| { - let (connection_messages, connection_notifiers) = node_args - .remove(addr) - .expect("there is a node for every connection message; qed"); - let node = Node::new( - transport.clone(), - addr.clone(), - connection_messages, - connection_notifiers, + // dispatch messages to the telemetry nodes + async fn process_message( + input: Option, + node_pool: &mut HashMap>, + node_map: &HashMap>, + ) { + let (id, verbosity, message) = if let Some(x) = input { + x + } else { + log::error!( + target: "telemetry", + "Unexpected end of stream. This is a bug.", ); - (addr.clone(), node) - }) - .collect(); + return; + }; - while let Some((id, verbosity, message)) = receiver.next().await { let nodes = if let Some(nodes) = node_map.get(&id) { nodes } else { - log::error!( + // This is a normal error because the telemetry span is entered before the telemetry + // is initialized so it is possible that some messages in the beginning don't get + // through. + log::trace!( target: "telemetry", "Received telemetry log for unknown id ({:?}): {}", id, message, ); - continue; + return; }; for (node_max_verbosity, addr) in nodes { @@ -261,7 +292,7 @@ impl TelemetryWorker { addr, verbosity, ); - continue; + return; } if let Some(node) = node_pool.get_mut(&addr) { @@ -278,18 +309,28 @@ impl TelemetryWorker { } } - log::error!( - target: "telemetry", - "Unexpected end of stream. This is a bug.", - ); + loop { + futures::select! { + message = message_receiver.next() => process_message( + message, + &mut node_pool, + &node_map, + ).await, + init_payload = register_receiver.next() => process_register( + init_payload, + &mut node_pool, + &mut node_map, + transport.clone(), + ).await, + } + } } } /// Handle to the [`TelemetryWorker`] thats allows initializing the telemetry for a Substrate node. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TelemetryHandle { - span: tracing::Span, - sender: mpsc::UnboundedSender, + message_sender: mpsc::UnboundedSender, } impl TelemetryHandle { @@ -304,20 +345,25 @@ impl TelemetryHandle { /// The `connection_message` argument is a JSON object that is sent every time the connection /// (re-)establishes. pub fn start_telemetry( - self, + &mut self, + span: TelemetrySpan, endpoints: TelemetryEndpoints, connection_message: ConnectionMessage, ) -> TelemetryConnectionNotifier { - let Self { span, sender } = self; + let Self { message_sender } = self; - let (connection_notifier, receiver) = { - let (sender, receiver) = mpsc::unbounded(); - (TelemetryConnectionNotifier(sender), receiver) + let connection_notifier = TelemetryConnectionNotifier { + message_sender: message_sender.clone(), + addresses: endpoints.0.iter().map(|(addr, _)| addr.clone()).collect(), }; - match span.id() { + match span.0.id() { Some(id) => { - match sender.unbounded_send((id.clone(), endpoints, connection_message, receiver)) { + match message_sender.unbounded_send(Register::Telemetry { + id, + endpoints, + connection_message, + }) { Ok(()) => {} Err(err) => error!( target: "telemetry", @@ -340,13 +386,22 @@ impl TelemetryHandle { /// Used to create a stream of events with only one event: when a telemetry connection /// (re-)establishes. #[derive(Clone, Debug)] -pub struct TelemetryConnectionNotifier(mpsc::UnboundedSender); +pub struct TelemetryConnectionNotifier { + message_sender: mpsc::UnboundedSender, + addresses: Vec, +} impl TelemetryConnectionNotifier { /// Get event stream for telemetry connection established events. + /// + /// This function will return an error if the telemetry has already been started by + /// [`TelemetryHandle::start_telemetry`]. pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { - let (sender, receiver) = tracing_unbounded("mpsc_telemetry_on_connect"); - if let Err(err) = self.0.unbounded_send(sender) { + let (message_sender, message_receiver) = tracing_unbounded("mpsc_telemetry_on_connect"); + if let Err(err) = self.message_sender.unbounded_send(Register::Notifier { + addresses: self.addresses.clone(), + connection_notifier: message_sender, + }) { error!( target: "telemetry", "Could not create a telemetry connection notifier: \ @@ -354,10 +409,23 @@ impl TelemetryConnectionNotifier { err, ); } - receiver + message_receiver } } +#[derive(Debug)] +enum Register { + Telemetry { + id: Id, + endpoints: TelemetryEndpoints, + connection_message: ConnectionMessage, + }, + Notifier { + addresses: Vec, + connection_notifier: ConnectionNotifierSender, + }, +} + /// Report a telemetry. /// /// Translates to [`tracing::info`], but contains an additional verbosity parameter which the log diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 03df6c86afe23..e47bc2f9634f7 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -45,9 +45,9 @@ pub(crate) struct Node { /// Transport used to establish new connections. transport: TTrans, /// Messages that are sent when the connection (re-)establishes. - connection_messages: Vec>, + pub(crate) connection_messages: Vec>, /// Notifier for when the connection (re-)establishes. - telemetry_connection_notifier: Vec, + pub(crate) telemetry_connection_notifier: Vec, } enum NodeSocket { diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 28e0f6cf44d24..797cbde70594b 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -23,7 +23,7 @@ use sc_service::{ config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration}, GenericChainSpec, RuntimeGenesis }; -use sc_telemetry::{TelemetryHandle, TelemetrySpan}; +use sc_telemetry::TelemetryHandle; use sc_tracing::logging::GlobalLoggerBuilder; use wasm_bindgen::prelude::*; use futures::{ @@ -51,7 +51,6 @@ pub fn init_logging_and_telemetry( pub async fn browser_configuration( chain_spec: GenericChainSpec, telemetry_handle: Option, - telemetry_span: Option, ) -> Result> where G: RuntimeGenesis + 'static, @@ -83,7 +82,6 @@ where }).into(), telemetry_external_transport: Some(transport), telemetry_handle, - telemetry_span, role: Role::Light, database: { info!("Opening Indexed DB database '{}'...", name); From 4501e8be9a126049745535487afc1069d6c9b915 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 13:09:51 +0100 Subject: [PATCH 213/222] Test code --- bin/node/cli/src/command.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index ed3aff88c75de..fef30387b0806 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -73,10 +73,18 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } + // TODO revert after test + let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetry_handle.clone()).unwrap(); + let mut task_manager = match config.role { + Role::Light => service::new_light(config).unwrap(), + _ => service::new_full(config).unwrap(), + }; + let task_manager2 = match config2.role { + Role::Light => service::new_light(config2).unwrap(), + _ => service::new_full(config2).unwrap(), + }; + task_manager.add_child(task_manager2); + Ok(task_manager) }) } Some(Subcommand::Inspect(cmd)) => { From 3d35251af803b202ce1f1936322b7ec96677f6a4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 15:49:40 +0100 Subject: [PATCH 214/222] Doc & cleanup --- client/cli/src/runner.rs | 2 +- client/service/src/config.rs | 2 +- client/service/test/src/lib.rs | 1 - client/telemetry/README.md | 17 ++++----- client/telemetry/src/endpoints.rs | 6 +++- client/telemetry/src/layer.rs | 15 ++++++-- client/telemetry/src/lib.rs | 45 ++++++++++-------------- client/tracing/src/logging/directives.rs | 2 +- client/tracing/src/logging/mod.rs | 15 +++++++- 9 files changed, 63 insertions(+), 42 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 0afe879641b4d..e3efc065d9fdb 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -224,7 +224,7 @@ impl Runner { &mut self.config } - /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. TODO + /// Get a new [`TelemetryHandle`]. /// /// This is used when you want to register a new telemetry for a Substrate node. pub fn telemetry_handle(&self) -> TelemetryHandle { diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 786968f286a8b..8888df5be503b 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -200,7 +200,7 @@ impl Configuration { self.prometheus_config.as_ref().map(|config| &config.registry) } - /// TODO + /// Returns the telemetry endpoints if any and if the telemetry handle exists. pub(crate) fn telemetry_endpoints(&self) -> Option<&TelemetryEndpoints> { if self.telemetry_handle.is_none() { return None; diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index c34995962a4f1..a5e0067640239 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -265,7 +265,6 @@ fn node_config::deserialize(deserializer)? .iter() - .map(|e| url_to_multiaddr(&e.0).map_err(serde::de::Error::custom).map(|m| (m, e.1))) + .map(|e| { + url_to_multiaddr(&e.0) + .map_err(serde::de::Error::custom) + .map(|m| (m, e.1)) + }) .collect() } diff --git a/client/telemetry/src/layer.rs b/client/telemetry/src/layer.rs index 2e86d86644da2..eb5eee197770b 100644 --- a/client/telemetry/src/layer.rs +++ b/client/telemetry/src/layer.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::TelemetryWorker; +use crate::{initialize_transport, TelemetryWorker}; use futures::channel::mpsc; use libp2p::wasm_ext::ExtTransport; use parking_lot::Mutex; @@ -34,10 +34,21 @@ pub struct TelemetryLayer(Mutex>); impl TelemetryLayer { /// Create a new [`TelemetryLayer`] and [`TelemetryWorker`]. + /// + /// If not provided, the `buffer_size` will be 16 by default. + /// + /// The [`ExtTransport`] is used in WASM contexts where we need some binding between the + /// networking provided by the operating system or environment and libp2p. + /// + /// > **Important**: Each individual call to `write` corresponds to one message. There is no + /// > internal buffering going on. In the context of WebSockets, each `write` + /// > must be one individual WebSockets frame. pub fn new( + buffer_size: Option, telemetry_external_transport: Option, ) -> io::Result<(Self, TelemetryWorker)> { - let worker = TelemetryWorker::new(telemetry_external_transport)?; + let transport = initialize_transport(telemetry_external_transport)?; + let worker = TelemetryWorker::new(buffer_size.unwrap_or(16), transport); let sender = worker.message_sender(); Ok((Self(Mutex::new(sender)), worker)) } diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index b2d2aedc4e557..cdbf96ec8c80c 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -18,26 +18,27 @@ //! To start using this module, please initialize the global logger from `sc-tracing`. This will //! return a [`TelemetryWorker`] which can be used to register substrate node. In order to do that, -//! first call [`TelemetryWorker::handle()`] to get a handle to the worker, then use -//! [`TelemetryHandle::start_telemetry()`] to initialize the telemetry. This will also return a -//! [`TelemetryConnectionNotifier`] which can be used to create streams of events for whenever the -//! connection to a telemetry server is (re-)established. +//! first call [`TelemetryWorker::handle()`] to get a handle to the worker, then call +//! [`TelemetrySpan::new()`] to create a new span, then use [`TelemetryHandle::start_telemetry()`] +//! to initialize the telemetry. This will also return a [`TelemetryConnectionNotifier`] which can +//! be used to create streams of events for whenever the connection to a telemetry server is +//! (re-)established. //! //! The macro [`telemetry`] can be used to report telemetries from anywhere in the code but the //! telemetry must have been initialized through [`TelemetryHandle::start_telemetry()`]. -//! Initializing the telemetry will make all the following code execution (including newly created -//! async background tasks) report the telemetries through the endpoints provided during the -//! initialization. If multiple telemetries have been started, the latest one (higher up in the -//! stack) will be used. If no telemetry has been started, nothing will be reported. +//! +//! The telemetry span needs to be passed to the [`sc_service::TaskManager`] in order to make all +//! the async background tasks report the telemetries through the endpoints provided during the +//! initialization. #![warn(missing_docs)] use futures::{channel::mpsc, prelude::*}; -use libp2p::{wasm_ext, Multiaddr}; +use libp2p::Multiaddr; use log::{error, warn}; use serde::Serialize; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; -use std::{collections::HashMap, io}; +use std::collections::HashMap; use tracing::Id; pub use libp2p::wasm_ext::ExtTransport; @@ -75,12 +76,12 @@ pub(crate) type TelemetryMessage = (Id, u8, String); pub struct TelemetrySpan(tracing::Span); impl TelemetrySpan { - /// TODO + /// Enters this span, returning a guard that will exit the span when dropped. pub fn enter(&self) -> tracing::span::Entered { self.0.enter() } - /// TODO + /// Constructs a new [`TelemetrySpan`]. pub fn new() -> Self { Self(tracing::info_span!(TELEMETRY_LOG_SPAN)) } @@ -124,28 +125,20 @@ pub struct TelemetryWorker { } impl TelemetryWorker { - /// Create a [`TelemetryWorker`] instance using an [`ExtTransport`]. - /// - /// The [`ExtTransport`] is used in WASM contexts where we need some binding between the - /// networking provided by the operating system or environment and libp2p. - /// - /// > **Important**: Each individual call to `write` corresponds to one message. There is no - /// > internal buffering going on. In the context of WebSockets, each `write` - /// > must be one individual WebSockets frame. - pub(crate) fn new(wasm_external_transport: Option) -> io::Result { - let (message_sender, message_receiver) = mpsc::channel(16); + pub(crate) fn new(buffer_size: usize, transport: WsTrans) -> Self { + let (message_sender, message_receiver) = mpsc::channel(buffer_size); let (register_sender, register_receiver) = mpsc::unbounded(); - Ok(Self { + Self { message_receiver, message_sender, register_receiver, register_sender, - transport: initialize_transport(wasm_external_transport)?, - }) + transport, + } } - /// Get a new [`TelemetryHandle`] and its associated [`TelemetrySpan`]. TODO + /// Get a new [`TelemetryHandle`]. /// /// This is used when you want to register a new telemetry for a Substrate node. pub fn handle(&self) -> TelemetryHandle { diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 50861797c0d67..b108566bf2bce 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -102,7 +102,7 @@ pub fn reset_log_filter() -> Result<(), String> { .get_or_init(|| Mutex::new(Vec::new())) .lock() .clone(); - + *CURRENT_DIRECTIVES .get_or_init(|| Mutex::new(Vec::new())) .lock() = directive; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 1e8dcd63586b6..ca4f74194bcc6 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -81,6 +81,7 @@ fn get_subscriber_internal( pattern: &str, max_level: Option, force_colors: Option, + telemetry_buffer_size: Option, telemetry_external_transport: Option, builder_hook: impl Fn( SubscriberBuilder< @@ -164,7 +165,7 @@ where }); let (telemetry_layer, telemetry_worker) = - sc_telemetry::TelemetryLayer::new(telemetry_external_transport)?; + sc_telemetry::TelemetryLayer::new(telemetry_buffer_size, telemetry_external_transport)?; let event_format = EventFormat { timer, display_target: !simple, @@ -198,6 +199,7 @@ where pub struct GlobalLoggerBuilder { pattern: String, profiling: Option<(crate::TracingReceiver, String)>, + telemetry_buffer_size: Option, telemetry_external_transport: Option, disable_log_reloading: bool, force_colors: Option, @@ -209,6 +211,7 @@ impl GlobalLoggerBuilder { Self { pattern: pattern.into(), profiling: None, + telemetry_buffer_size: None, telemetry_external_transport: None, disable_log_reloading: false, force_colors: None, @@ -231,6 +234,12 @@ impl GlobalLoggerBuilder { self } + /// Set a custom buffer size for the telemetry. + pub fn with_telemetry_buffer_size(&mut self, buffer_size: usize) -> &mut Self { + self.telemetry_buffer_size = Some(buffer_size); + self + } + /// Set a custom network transport (used for the telemetry). pub fn with_transport(&mut self, transport: ExtTransport) -> &mut Self { self.telemetry_external_transport = Some(transport); @@ -256,6 +265,7 @@ impl GlobalLoggerBuilder { &format!("{},{},sc_tracing=trace", self.pattern, profiling_targets), max_level, self.force_colors, + self.telemetry_buffer_size, self.telemetry_external_transport, |builder| builder, )?; @@ -269,6 +279,7 @@ impl GlobalLoggerBuilder { &format!("{},{},sc_tracing=trace", self.pattern, profiling_targets), max_level, self.force_colors, + self.telemetry_buffer_size, self.telemetry_external_transport, |builder| disable_log_reloading!(builder), )?; @@ -284,6 +295,7 @@ impl GlobalLoggerBuilder { &self.pattern, None, self.force_colors, + self.telemetry_buffer_size, self.telemetry_external_transport, |builder| builder, )?; @@ -296,6 +308,7 @@ impl GlobalLoggerBuilder { &self.pattern, None, self.force_colors, + self.telemetry_buffer_size, self.telemetry_external_transport, |builder| disable_log_reloading!(builder), )?; From eb866c10e0e6752313a54248e19e8a4ff0225871 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 16:16:15 +0100 Subject: [PATCH 215/222] Revert "Test code" This reverts commit 4501e8be9a126049745535487afc1069d6c9b915. --- bin/node/cli/src/command.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index fef30387b0806..ed3aff88c75de 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -73,18 +73,10 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - // TODO revert after test - let config2 = cli.create_configuration(&cli.run, config.task_executor.clone(), config.telemetry_handle.clone()).unwrap(); - let mut task_manager = match config.role { - Role::Light => service::new_light(config).unwrap(), - _ => service::new_full(config).unwrap(), - }; - let task_manager2 = match config2.role { - Role::Light => service::new_light(config2).unwrap(), - _ => service::new_full(config2).unwrap(), - }; - task_manager.add_child(task_manager2); - Ok(task_manager) + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } }) } Some(Subcommand::Inspect(cmd)) => { From cd716e4af1a932c4c7ba3b6352c3573b27df12f1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 16:38:23 +0100 Subject: [PATCH 216/222] Fix line width --- bin/node-template/node/src/service.rs | 32 ++++++++++--------- bin/node/cli/src/browser.rs | 5 ++- bin/node/cli/src/service.rs | 45 ++++++++++++++++----------- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index e60859b5fc9a4..52978b4238d2c 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -161,20 +161,22 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - let (_rpc_handlers, telemetry_telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), - client: client.clone(), - keystore: keystore_container.sync_keystore(), - task_manager: &mut task_manager, - transaction_pool: transaction_pool.clone(), - rpc_extensions_builder, - on_demand: None, - remote_blockchain: None, - backend, - network_status_sinks, - system_rpc_tx, - config, - })?; + let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks( + sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore_container.sync_keystore(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + rpc_extensions_builder, + on_demand: None, + remote_blockchain: None, + backend, + network_status_sinks, + system_rpc_tx, + config, + }, + )?; if role.is_authority() { let proposer = sc_basic_authorship::ProposerFactory::new( @@ -235,7 +237,7 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: telemetry_telemetry_connection_notifier.map(|x| x.on_connect_stream()), + telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 93b6c55b1790c..6c0a2f10d95e5 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -32,7 +32,10 @@ pub async fn start_client(chain_spec: Option, log_level: String) -> Resu .map_err(|err| JsValue::from_str(&err.to_string())) } -async fn start_inner(chain_spec: Option, log_directives: String) -> Result> { +async fn start_inner( + chain_spec: Option, + log_directives: String, +) -> Result> { set_console_error_panic_hook(); let telemetry_worker = init_logging_and_telemetry(&log_directives)?; let chain_spec = match chain_spec { diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 230b4ae35b266..c3061b88709ab 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -219,21 +219,23 @@ pub fn new_full_base( let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let (_rpc_handlers, telemetry_telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - config, - backend: backend.clone(), - client: client.clone(), - keystore: keystore_container.sync_keystore(), - network: network.clone(), - rpc_extensions_builder: Box::new(rpc_extensions_builder), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - on_demand: None, - remote_blockchain: None, - network_status_sinks: network_status_sinks.clone(), - system_rpc_tx, - telemetry_span, - })?; + let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks( + sc_service::SpawnTasksParams { + config, + backend: backend.clone(), + client: client.clone(), + keystore: keystore_container.sync_keystore(), + network: network.clone(), + rpc_extensions_builder: Box::new(rpc_extensions_builder), + transaction_pool: transaction_pool.clone(), + task_manager: &mut task_manager, + on_demand: None, + remote_blockchain: None, + network_status_sinks: network_status_sinks.clone(), + system_rpc_tx, + telemetry_span, + }, + )?; let (block_import, grandpa_link, babe_link) = import_setup; @@ -318,7 +320,7 @@ pub fn new_full_base( config, link: grandpa_link, network: network.clone(), - telemetry_on_connect: telemetry_telemetry_connection_notifier.map(|x| x.on_connect_stream()), + telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state, @@ -425,7 +427,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<( let rpc_extensions = node_rpc::create_light(light_deps); - let (rpc_handlers, telemetry_telemetry_connection_notifier) = + let (rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { on_demand: Some(on_demand), remote_blockchain: Some(backend.remote_blockchain()), @@ -439,7 +441,14 @@ pub fn new_light_base(mut config: Configuration) -> Result<( telemetry_span, })?; - Ok((task_manager, rpc_handlers, telemetry_telemetry_connection_notifier, client, network, transaction_pool)) + Ok(( + task_manager, + rpc_handlers, + telemetry_connection_notifier, + client, + network, + transaction_pool, + )) } /// Builds a new service for a light client. From 36ec61b7cf5b7189bca94af2c5ec7bc76680cf90 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 15 Jan 2021 16:38:39 +0100 Subject: [PATCH 217/222] Added missing code adaptation --- Cargo.lock | 1 + bin/node-template/node/Cargo.toml | 1 + bin/node-template/node/src/service.rs | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dcaa1aa1619b1..0a0f3a9bce57a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4017,6 +4017,7 @@ dependencies = [ "sc-rpc", "sc-rpc-api", "sc-service", + "sc-telemetry", "sc-transaction-pool", "sp-api", "sp-block-builder", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 38cdaa1eea48c..878e49fe9b1f0 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -22,6 +22,7 @@ sc-cli = { version = "0.8.0", path = "../../../client/cli", features = ["wasmtim sp-core = { version = "2.0.0", path = "../../../primitives/core" } sc-executor = { version = "0.8.0", path = "../../../client/executor", features = ["wasmtime"] } sc-service = { version = "0.8.0", path = "../../../client/service", features = ["wasmtime"] } +sc-telemetry = { version = "2.0.0", path = "../../../client/telemetry" } sc-keystore = { version = "2.0.0", path = "../../../client/keystore" } sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } sc-transaction-pool = { version = "2.0.0", path = "../../../client/transaction-pool" } diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 52978b4238d2c..b9e5705333e70 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -11,6 +11,7 @@ pub use sc_executor::NativeExecutor; use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; +use sc_telemetry::TelemetrySpan; // Our native executor instance. native_executor_instance!( @@ -35,7 +36,8 @@ pub fn new_partial(config: &Configuration) -> Result, AuraPair >, - sc_finality_grandpa::LinkHalf + sc_finality_grandpa::LinkHalf, + Option, ) >, ServiceError> { if config.keystore_remote.is_some() { @@ -44,7 +46,7 @@ pub fn new_partial(config: &Configuration) -> Result(&config)?; let client = Arc::new(client); @@ -85,7 +87,7 @@ pub fn new_partial(config: &Configuration) -> Result Result select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link), + other: (block_import, grandpa_link, telemetry_span), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -175,6 +177,7 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, + telemetry_span, }, )?; @@ -257,7 +260,7 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = sc_service::new_light_parts::(&config)?; config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); @@ -324,9 +327,10 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, - })?; + telemetry_span, + })?; - network_starter.start_network(); + network_starter.start_network(); - Ok(task_manager) + Ok(task_manager) } From 24596be78ae1a153a077a5938c38cff02588875b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 20 Jan 2021 10:01:00 +0100 Subject: [PATCH 218/222] Move inner functions out of run function --- client/telemetry/src/lib.rs | 263 ++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 132 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index cdbf96ec8c80c..fb9db68e78875 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -167,154 +167,153 @@ impl TelemetryWorker { let mut node_map: HashMap> = HashMap::new(); let mut node_pool: HashMap = HashMap::new(); - // initialize the telemetry nodes and register new notifiers - async fn process_register( - input: Option, - node_pool: &mut HashMap>, - node_map: &mut HashMap>, - transport: WsTrans, - ) { - let input = if let Some(x) = input { - x - } else { - log::error!( - target: "telemetry", - "Unexpected end of stream. This is a bug.", - ); - return; - }; + loop { + futures::select! { + message = message_receiver.next() => Self::process_message( + message, + &mut node_pool, + &node_map, + ).await, + init_payload = register_receiver.next() => Self::process_register( + init_payload, + &mut node_pool, + &mut node_map, + transport.clone(), + ).await, + } + } + } - match input { - Register::Telemetry { - id, - endpoints, - connection_message, - } => { - let endpoints = endpoints.0; - - let connection_message = match serde_json::to_value(&connection_message) { - Ok(serde_json::Value::Object(mut value)) => { - value.insert("msg".into(), "system.connected".into()); - let mut obj = serde_json::Map::new(); - obj.insert("id".to_string(), id.into_u64().into()); - obj.insert("payload".to_string(), value.into()); - Some(obj) - } - Ok(_) => { - unreachable!("ConnectionMessage always serialize to an object; qed") - } - Err(err) => { - log::error!( - target: "telemetry", - "Could not serialize connection message: {}", - err, - ); - None - } - }; - - for (addr, verbosity) in endpoints { - node_map - .entry(id.clone()) - .or_default() - .push((verbosity, addr.clone())); - - let node = node_pool.entry(addr.clone()).or_insert_with(|| { - Node::new(transport.clone(), addr.clone(), Vec::new(), Vec::new()) - }); - - node.connection_messages.extend(connection_message.clone()); + async fn process_register( + input: Option, + node_pool: &mut HashMap>, + node_map: &mut HashMap>, + transport: WsTrans, + ) { + let input = if let Some(x) = input { + x + } else { + log::error!( + target: "telemetry", + "Unexpected end of stream. This is a bug.", + ); + return; + }; + + match input { + Register::Telemetry { + id, + endpoints, + connection_message, + } => { + let endpoints = endpoints.0; + + let connection_message = match serde_json::to_value(&connection_message) { + Ok(serde_json::Value::Object(mut value)) => { + value.insert("msg".into(), "system.connected".into()); + let mut obj = serde_json::Map::new(); + obj.insert("id".to_string(), id.into_u64().into()); + obj.insert("payload".to_string(), value.into()); + Some(obj) + } + Ok(_) => { + unreachable!("ConnectionMessage always serialize to an object; qed") } + Err(err) => { + log::error!( + target: "telemetry", + "Could not serialize connection message: {}", + err, + ); + None + } + }; + + for (addr, verbosity) in endpoints { + node_map + .entry(id.clone()) + .or_default() + .push((verbosity, addr.clone())); + + let node = node_pool.entry(addr.clone()).or_insert_with(|| { + Node::new(transport.clone(), addr.clone(), Vec::new(), Vec::new()) + }); + + node.connection_messages.extend(connection_message.clone()); } - Register::Notifier { - addresses, - connection_notifier, - } => { - for addr in addresses { - if let Some(node) = node_pool.get_mut(&addr) { - node.telemetry_connection_notifier - .push(connection_notifier.clone()); - } else { - log::error!( - target: "telemetry", - "Received connection notifier for unknown node ({}). This is a bug.", - addr, - ); - } + } + Register::Notifier { + addresses, + connection_notifier, + } => { + for addr in addresses { + if let Some(node) = node_pool.get_mut(&addr) { + node.telemetry_connection_notifier + .push(connection_notifier.clone()); + } else { + log::error!( + target: "telemetry", + "Received connection notifier for unknown node ({}). This is a bug.", + addr, + ); } } } } + } - // dispatch messages to the telemetry nodes - async fn process_message( - input: Option, - node_pool: &mut HashMap>, - node_map: &HashMap>, - ) { - let (id, verbosity, message) = if let Some(x) = input { - x - } else { - log::error!( - target: "telemetry", - "Unexpected end of stream. This is a bug.", - ); - return; - }; + // dispatch messages to the telemetry nodes + async fn process_message( + input: Option, + node_pool: &mut HashMap>, + node_map: &HashMap>, + ) { + let (id, verbosity, message) = if let Some(x) = input { + x + } else { + log::error!( + target: "telemetry", + "Unexpected end of stream. This is a bug.", + ); + return; + }; - let nodes = if let Some(nodes) = node_map.get(&id) { - nodes - } else { - // This is a normal error because the telemetry span is entered before the telemetry - // is initialized so it is possible that some messages in the beginning don't get - // through. + let nodes = if let Some(nodes) = node_map.get(&id) { + nodes + } else { + // This is a normal error because the telemetry span is entered before the telemetry + // is initialized so it is possible that some messages in the beginning don't get + // through. + log::trace!( + target: "telemetry", + "Received telemetry log for unknown id ({:?}): {}", + id, + message, + ); + return; + }; + + for (node_max_verbosity, addr) in nodes { + if verbosity > *node_max_verbosity { log::trace!( target: "telemetry", - "Received telemetry log for unknown id ({:?}): {}", - id, - message, + "Skipping {} for log entry with verbosity {:?}", + addr, + verbosity, ); return; - }; - - for (node_max_verbosity, addr) in nodes { - if verbosity > *node_max_verbosity { - log::trace!( - target: "telemetry", - "Skipping {} for log entry with verbosity {:?}", - addr, - verbosity, - ); - return; - } - - if let Some(node) = node_pool.get_mut(&addr) { - let _ = node.send(message.clone()).await; - } else { - log::error!( - target: "telemetry", - "Received message for unknown node ({}). This is a bug. \ - Message sent: {}", - addr, - message, - ); - } } - } - loop { - futures::select! { - message = message_receiver.next() => process_message( + if let Some(node) = node_pool.get_mut(&addr) { + let _ = node.send(message.clone()).await; + } else { + log::error!( + target: "telemetry", + "Received message for unknown node ({}). This is a bug. \ + Message sent: {}", + addr, message, - &mut node_pool, - &node_map, - ).await, - init_payload = register_receiver.next() => process_register( - init_payload, - &mut node_pool, - &mut node_map, - transport.clone(), - ).await, + ); } } } From f6ec36d04d1cd6784a04a1b22efba16a69c73433 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 20 Jan 2021 10:04:43 +0100 Subject: [PATCH 219/222] Fixed incorrect return of function --- client/telemetry/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index fb9db68e78875..ef228b63515c2 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -301,7 +301,7 @@ impl TelemetryWorker { addr, verbosity, ); - return; + continue; } if let Some(node) = node_pool.get_mut(&addr) { From f462418e20603906b8b26624373157fe3568961e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 20 Jan 2021 10:06:47 +0100 Subject: [PATCH 220/222] Change error to expect --- client/telemetry/src/lib.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ef228b63515c2..726428d034e60 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -190,15 +190,7 @@ impl TelemetryWorker { node_map: &mut HashMap>, transport: WsTrans, ) { - let input = if let Some(x) = input { - x - } else { - log::error!( - target: "telemetry", - "Unexpected end of stream. This is a bug.", - ); - return; - }; + let input = input.expect("the stream is never closed; qed"); match input { Register::Telemetry { @@ -268,15 +260,7 @@ impl TelemetryWorker { node_pool: &mut HashMap>, node_map: &HashMap>, ) { - let (id, verbosity, message) = if let Some(x) = input { - x - } else { - log::error!( - target: "telemetry", - "Unexpected end of stream. This is a bug.", - ); - return; - }; + let (id, verbosity, message) = input.expect("the stream is never closed; qed"); let nodes = if let Some(nodes) = node_map.get(&id) { nodes From acf1ec852f89a094ddd77f344a8dcbc58be6ba14 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 20 Jan 2021 10:28:42 +0100 Subject: [PATCH 221/222] Another attempt to have a higher level doc --- client/telemetry/README.md | 22 ++++++++++------------ client/telemetry/src/lib.rs | 22 ++++++++++------------ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index 1c21ca436a35b..e0542a4865ea2 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -1,18 +1,16 @@ # sc-telemetry -To start using this module, please initialize the global logger from `sc-tracing`. This will -return a [`TelemetryWorker`] which can be used to register substrate node. In order to do that, -first call [`TelemetryWorker::handle()`] to get a handle to the worker, then call -[`TelemetrySpan::new()`] to create a new span, then use [`TelemetryHandle::start_telemetry()`] -to initialize the telemetry. This will also return a [`TelemetryConnectionNotifier`] which can -be used to create streams of events for whenever the connection to a telemetry server is -(re-)established. +Substrate's client telemetry is a part of substrate that allows logging telemetry information +with a [Polkadot telemetry](https://github.com/paritytech/substrate-telemetry). -The macro [`telemetry`] can be used to report telemetries from anywhere in the code but the -telemetry must have been initialized through [`TelemetryHandle::start_telemetry()`]. +It works using Tokio's [tracing](https://github.com/tokio-rs/tracing/). The telemetry +information uses tracing's logging to report the telemetry which is then retrieved by a +tracing's `Layer`. This layer will then send the data through an asynchronous channel and to a +background task called [`TelemetryWorker`] which will send the information to the telemetry +server. -The telemetry span needs to be passed to the [`sc_service::TaskManager`] in order to make all -the async background tasks report the telemetries through the endpoints provided during the -initialization. +If multiple substrate nodes are running, it uses a tracing's `Span` to identify which substrate +node is reporting the telemetry. Every task spawned using sc-service's `TaskManager` +automatically inherit this span. License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 726428d034e60..ebaea85657286 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -16,20 +16,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! To start using this module, please initialize the global logger from `sc-tracing`. This will -//! return a [`TelemetryWorker`] which can be used to register substrate node. In order to do that, -//! first call [`TelemetryWorker::handle()`] to get a handle to the worker, then call -//! [`TelemetrySpan::new()`] to create a new span, then use [`TelemetryHandle::start_telemetry()`] -//! to initialize the telemetry. This will also return a [`TelemetryConnectionNotifier`] which can -//! be used to create streams of events for whenever the connection to a telemetry server is -//! (re-)established. +//! Substrate's client telemetry is a part of substrate that allows logging telemetry information +//! with a [Polkadot telemetry](https://github.com/paritytech/substrate-telemetry). //! -//! The macro [`telemetry`] can be used to report telemetries from anywhere in the code but the -//! telemetry must have been initialized through [`TelemetryHandle::start_telemetry()`]. +//! It works using Tokio's [tracing](https://github.com/tokio-rs/tracing/). The telemetry +//! information uses tracing's logging to report the telemetry which is then retrieved by a +//! tracing's `Layer`. This layer will then send the data through an asynchronous channel and to a +//! background task called [`TelemetryWorker`] which will send the information to the telemetry +//! server. //! -//! The telemetry span needs to be passed to the [`sc_service::TaskManager`] in order to make all -//! the async background tasks report the telemetries through the endpoints provided during the -//! initialization. +//! If multiple substrate nodes are running, it uses a tracing's `Span` to identify which substrate +//! node is reporting the telemetry. Every task spawned using sc-service's `TaskManager` +//! automatically inherit this span. #![warn(missing_docs)] From bc361362837999cbfe2c628dbe7c2ea91a17ae36 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 20 Jan 2021 10:37:32 +0100 Subject: [PATCH 222/222] More doc --- client/telemetry/README.md | 5 +++++ client/telemetry/src/lib.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/client/telemetry/README.md b/client/telemetry/README.md index e0542a4865ea2..a6b7b654508ae 100644 --- a/client/telemetry/README.md +++ b/client/telemetry/README.md @@ -13,4 +13,9 @@ If multiple substrate nodes are running, it uses a tracing's `Span` to identify node is reporting the telemetry. Every task spawned using sc-service's `TaskManager` automatically inherit this span. +Substrate's nodes initialize/register to the [`TelemetryWorker`] using a [`TelemetryHandle`]. +This handle can be cloned and passed around. It uses an asynchronous channel to communicate with +the running [`TelemetryWorker`] dedicated to registration. Registering a telemetry can happen at +any point in time during the execution. + License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index ebaea85657286..6a4533bb7bc40 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -28,6 +28,11 @@ //! If multiple substrate nodes are running, it uses a tracing's `Span` to identify which substrate //! node is reporting the telemetry. Every task spawned using sc-service's `TaskManager` //! automatically inherit this span. +//! +//! Substrate's nodes initialize/register to the [`TelemetryWorker`] using a [`TelemetryHandle`]. +//! This handle can be cloned and passed around. It uses an asynchronous channel to communicate with +//! the running [`TelemetryWorker`] dedicated to registration. Registering a telemetry can happen at +//! any point in time during the execution. #![warn(missing_docs)]