Rework telemetry to replace the use of tracing with an object we pass around (#8143)

polkadot companion: paritytech/polkadot#2535
This commit is contained in:
Cecile Tonglet
2021-03-11 11:05:45 +01:00
committed by GitHub
parent 7aaba0c154
commit 8031b6eacb
55 changed files with 1028 additions and 838 deletions
+4 -7
View File
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "Inflector"
version = "0.11.4"
@@ -3971,6 +3973,7 @@ dependencies = [
"frame-system",
"futures 0.3.12",
"hex-literal",
"libp2p-wasm-ext",
"log",
"nix",
"node-executor",
@@ -7780,8 +7783,6 @@ dependencies = [
"tokio 0.2.25",
"tracing",
"tracing-futures",
"tracing-log",
"tracing-subscriber",
"wasm-timer",
]
@@ -7867,10 +7868,8 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_json",
"sp-utils",
"take_mut",
"tracing",
"tracing-subscriber",
"thiserror",
"void",
"wasm-timer",
]
@@ -7888,7 +7887,6 @@ dependencies = [
"parking_lot 0.11.1",
"regex",
"rustc-hash",
"sc-telemetry",
"sc-tracing-proc-macro",
"serde",
"serde_json",
@@ -9267,7 +9265,6 @@ dependencies = [
"sc-informant",
"sc-network",
"sc-service",
"sc-telemetry",
"sc-tracing",
"sp-database",
"wasm-bindgen",
+56 -16
View File
@@ -12,7 +12,7 @@ use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use sc_consensus_aura::{ImportQueueParams, StartAuraParams, SlotProportion};
use sc_finality_grandpa::SharedVoterState;
use sc_keystore::LocalKeystore;
use sc_telemetry::TelemetrySpan;
use sc_telemetry::{Telemetry, TelemetryWorker};
// Our native executor instance.
native_executor_instance!(
@@ -38,6 +38,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
AuraPair
>,
sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
Option<Telemetry>,
)
>, ServiceError> {
if config.keystore_remote.is_some() {
@@ -46,10 +47,28 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
}
let inherent_data_providers = InherentDataProviders::new();
let telemetry = config.telemetry_endpoints.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(&config)?;
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let client = Arc::new(client);
let telemetry = telemetry
.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
@@ -61,7 +80,10 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
);
let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(
client.clone(), &(client.clone() as Arc<_>), select_chain.clone(),
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
@@ -79,6 +101,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
slot_duration: sc_consensus_aura::slot_duration(&*client)?,
registry: config.prometheus_registry(),
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
},
)?;
@@ -91,7 +114,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
select_chain,
transaction_pool,
inherent_data_providers,
other: (aura_block_import, grandpa_link),
other: (aura_block_import, grandpa_link, telemetry),
})
}
@@ -113,7 +136,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
select_chain,
transaction_pool,
inherent_data_providers,
other: (block_import, grandpa_link),
other: (block_import, grandpa_link, mut telemetry),
} = new_partial(&config)?;
if let Some(url) = &config.keystore_remote {
@@ -167,10 +190,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
})
};
let telemetry_span = TelemetrySpan::new();
let _telemetry_span_entered = telemetry_span.enter();
let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(
let _rpc_handlers = sc_service::spawn_tasks(
sc_service::SpawnTasksParams {
network: network.clone(),
client: client.clone(),
@@ -184,7 +204,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
network_status_sinks,
system_rpc_tx,
config,
telemetry_span: Some(telemetry_span.clone()),
telemetry: telemetry.as_mut(),
},
)?;
@@ -194,6 +214,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
client.clone(),
transaction_pool,
prometheus_registry.as_ref(),
telemetry.as_ref().map(|x| x.handle()),
);
let can_author_with =
@@ -213,6 +234,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
can_author_with,
sync_oracle: network.clone(),
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
telemetry: telemetry.as_ref().map(|x| x.handle()),
},
)?;
@@ -237,6 +259,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
observer_enabled: false,
keystore,
is_authority: role.is_authority(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
if enable_grandpa {
@@ -250,10 +273,10 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
config: grandpa_config,
link: grandpa_link,
network,
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(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
// the GRANDPA voter task is considered infallible, i.e.
@@ -270,8 +293,26 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
/// Builds a new service for a light client.
pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError> {
let telemetry = config.telemetry_endpoints.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(&config)?;
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let mut telemetry = telemetry
.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
@@ -289,6 +330,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
@@ -307,6 +349,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
slot_duration: sc_consensus_aura::slot_duration(&*client)?,
registry: config.prometheus_registry(),
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
},
)?;
@@ -327,9 +370,6 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
);
}
let telemetry_span = TelemetrySpan::new();
let _telemetry_span_entered = telemetry_span.enter();
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
remote_blockchain: Some(backend.remote_blockchain()),
transaction_pool,
@@ -343,7 +383,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
network,
network_status_sinks,
system_rpc_tx,
telemetry_span: Some(telemetry_span.clone()),
telemetry: telemetry.as_mut(),
})?;
network_starter.start_network();
@@ -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
+2
View File
@@ -105,6 +105,7 @@ try-runtime-cli = { version = "0.9.0", optional = true, path = "../../../utils/f
wasm-bindgen = { version = "0.2.57", optional = true }
wasm-bindgen-futures = { version = "0.4.18", optional = true }
browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.9.0"}
libp2p-wasm-ext = { version = "0.27", features = ["websocket"], optional = true }
[target.'cfg(target_arch="x86_64")'.dependencies]
node-executor = { version = "2.0.0", path = "../executor", features = [ "wasmtime" ] }
@@ -148,6 +149,7 @@ browser = [
"browser-utils",
"wasm-bindgen",
"wasm-bindgen-futures",
"libp2p-wasm-ext",
]
cli = [
"node-executor/wasmi-errno",
+4 -10
View File
@@ -21,7 +21,7 @@ use log::info;
use wasm_bindgen::prelude::*;
use browser_utils::{
Client,
browser_configuration, init_logging_and_telemetry, set_console_error_panic_hook,
browser_configuration, init_logging, set_console_error_panic_hook,
};
/// Starts the client.
@@ -37,18 +37,14 @@ async fn start_inner(
log_directives: String,
) -> Result<Client, Box<dyn std::error::Error>> {
set_console_error_panic_hook();
let telemetry_worker = init_logging_and_telemetry(&log_directives)?;
init_logging(&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 telemetry_handle = telemetry_worker.handle();
let config = browser_configuration(
chain_spec,
Some(telemetry_handle),
).await?;
let config = browser_configuration(chain_spec).await?;
info!("Substrate browser node");
info!("✌️ version {}", config.impl_version);
@@ -60,10 +56,8 @@ async fn start_inner(
// 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))?;
task_manager.spawn_handle().spawn("telemetry", telemetry_worker.run());
Ok(browser_utils::start_client(task_manager, rpc_handlers))
}
+1 -1
View File
@@ -443,7 +443,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))
}
);
+83 -27
View File
@@ -33,7 +33,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, TelemetrySpan};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sc_consensus_babe::SlotProportion;
type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;
@@ -43,7 +43,9 @@ type FullGrandpaBlockImport =
grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>;
type LightClient = sc_service::TLightClient<Block, RuntimeApi, Executor>;
pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponents<
pub fn new_partial(
config: &Configuration,
) -> Result<sc_service::PartialComponents<
FullClient, FullBackend, FullSelectChain,
sp_consensus::DefaultImportQueue<Block, FullClient>,
sc_transaction_pool::FullPool<Block, FullClient>,
@@ -58,12 +60,31 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
sc_consensus_babe::BabeLink<Block>,
),
grandpa::SharedVoterState,
Option<Telemetry>,
)
>, ServiceError> {
let telemetry = config.telemetry_endpoints.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(&config)?;
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let client = Arc::new(client);
let telemetry = telemetry
.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
@@ -75,7 +96,10 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
);
let (grandpa_block_import, grandpa_link) = grandpa::block_import(
client.clone(), &(client.clone() as Arc<_>), select_chain.clone(),
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let justification_import = grandpa_block_import.clone();
@@ -97,6 +121,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
telemetry.as_ref().map(|x| x.handle()),
)?;
let import_setup = (block_import, grandpa_link, babe_link);
@@ -159,7 +184,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
import_queue,
transaction_pool,
inherent_data_providers,
other: (rpc_extensions_builder, import_setup, rpc_setup),
other: (rpc_extensions_builder, import_setup, rpc_setup, telemetry),
})
}
@@ -189,7 +214,7 @@ pub fn new_full_base(
select_chain,
transaction_pool,
inherent_data_providers,
other: (rpc_extensions_builder, import_setup, rpc_setup),
other: (rpc_extensions_builder, import_setup, rpc_setup, mut telemetry),
} = new_partial(&config)?;
let shared_voter_state = rpc_setup;
@@ -231,10 +256,7 @@ pub fn new_full_base(
let enable_grandpa = !config.disable_grandpa;
let prometheus_registry = config.prometheus_registry().cloned();
let telemetry_span = TelemetrySpan::new();
let _telemetry_span_entered = telemetry_span.enter();
let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(
let _rpc_handlers = sc_service::spawn_tasks(
sc_service::SpawnTasksParams {
config,
backend: backend.clone(),
@@ -248,7 +270,7 @@ pub fn new_full_base(
remote_blockchain: None,
network_status_sinks: network_status_sinks.clone(),
system_rpc_tx,
telemetry_span: Some(telemetry_span.clone()),
telemetry: telemetry.as_mut(),
},
)?;
@@ -262,6 +284,7 @@ pub fn new_full_base(
client.clone(),
transaction_pool.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|x| x.handle()),
);
let can_author_with =
@@ -280,6 +303,7 @@ pub fn new_full_base(
babe_link,
can_author_with,
block_proposal_slot_portion: SlotProportion::new(0.5),
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
let babe = sc_consensus_babe::start_babe(babe_config)?;
@@ -323,6 +347,7 @@ pub fn new_full_base(
observer_enabled: false,
keystore,
is_authority: role.is_authority(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
if enable_grandpa {
@@ -336,7 +361,7 @@ pub fn new_full_base(
config,
link: grandpa_link,
network: network.clone(),
telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()),
telemetry: telemetry.as_ref().map(|x| x.handle()),
voting_rule: grandpa::VotingRulesBuilder::default().build(),
prometheus_registry,
shared_voter_state,
@@ -362,20 +387,50 @@ pub fn new_full_base(
}
/// Builds a new service for a full client.
pub fn new_full(config: Configuration)
-> Result<TaskManager, ServiceError> {
pub fn new_full(
config: Configuration,
) -> Result<TaskManager, ServiceError> {
new_full_base(config, |_, _| ()).map(|NewFullBase { task_manager, .. }| {
task_manager
})
}
pub fn new_light_base(mut config: Configuration) -> Result<(
TaskManager, RpcHandlers, Option<TelemetryConnectionNotifier>, Arc<LightClient>,
pub fn new_light_base(
mut config: Configuration,
) -> Result<(
TaskManager,
RpcHandlers,
Arc<LightClient>,
Arc<NetworkService<Block, <Block as BlockT>::Hash>>,
Arc<sc_transaction_pool::LightPool<Block, LightClient, sc_network::config::OnDemand<Block>>>
), ServiceError> {
let telemetry = config.telemetry_endpoints.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
#[cfg(feature = "browser")]
let transport = Some(
sc_telemetry::ExtTransport::new(libp2p_wasm_ext::ffi::websocket_transport())
);
#[cfg(not(feature = "browser"))]
let transport = None;
let worker = TelemetryWorker::with_transport(16, transport)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(&config)?;
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let mut telemetry = telemetry
.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
config.network.extra_sets.push(grandpa::grandpa_peers_set_config());
@@ -393,6 +448,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let justification_import = grandpa_block_import.clone();
@@ -414,6 +470,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
sp_consensus::NeverCanAuthor,
telemetry.as_ref().map(|x| x.handle()),
)?;
let (network, network_status_sinks, system_rpc_tx, network_starter) =
@@ -443,10 +500,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
let rpc_extensions = node_rpc::create_light(light_deps);
let telemetry_span = TelemetrySpan::new();
let _telemetry_span_entered = telemetry_span.enter();
let (rpc_handlers, telemetry_connection_notifier) =
let rpc_handlers =
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
on_demand: Some(on_demand),
remote_blockchain: Some(backend.remote_blockchain()),
@@ -457,13 +511,12 @@ 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: Some(telemetry_span.clone()),
telemetry: telemetry.as_mut(),
})?;
Ok((
task_manager,
rpc_handlers,
telemetry_connection_notifier,
client,
network,
transaction_pool,
@@ -471,8 +524,10 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
}
/// Builds a new service for a light client.
pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
new_light_base(config).map(|(task_manager, _, _, _, _, _)| {
pub fn new_light(
config: Configuration,
) -> Result<TaskManager, ServiceError> {
new_light_base(config).map(|(task_manager, _, _, _, _)| {
task_manager
})
}
@@ -553,7 +608,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))| {
@@ -580,6 +635,7 @@ mod tests {
service.client(),
service.transaction_pool(),
None,
None,
);
let epoch_descriptor = babe_link.epoch_changes().lock().epoch_descriptor_for_child_of(
@@ -708,7 +764,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![
+1 -1
View File
@@ -34,7 +34,7 @@ impl InspectCmd {
RA: Send + Sync + 'static,
EX: NativeExecutionDispatch + 'static,
{
let client = new_full_client::<B, RA, EX>(&config)?;
let client = new_full_client::<B, RA, EX>(&config, None)?;
let inspect = Inspector::<B>::new(client);
match &self.command {
+1
View File
@@ -427,6 +427,7 @@ impl BenchDb {
ExecutionExtensions::new(profile.into_execution_strategies(), None, None),
Box::new(task_executor.clone()),
None,
None,
Default::default(),
).expect("Should not fail");
@@ -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::{telemetry, TelemetryHandle, CONSENSUS_INFO};
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
use sp_api::{ProvideRuntimeApi, ApiExt};
use futures::{future, future::{Future, FutureExt}, channel::oneshot, select};
@@ -60,9 +60,10 @@ pub struct ProposerFactory<A, B, C, PR> {
transaction_pool: Arc<A>,
/// Prometheus Link,
metrics: PrometheusMetrics,
max_block_size: usize,
telemetry: Option<TelemetryHandle>,
/// phantom member to pin the `Backend`/`ProofRecording` type.
_phantom: PhantomData<(B, PR)>,
max_block_size: usize,
}
impl<A, B, C> ProposerFactory<A, B, C, DisableProofRecording> {
@@ -74,14 +75,16 @@ impl<A, B, C> ProposerFactory<A, B, C, DisableProofRecording> {
client: Arc<C>,
transaction_pool: Arc<A>,
prometheus: Option<&PrometheusRegistry>,
telemetry: Option<TelemetryHandle>,
) -> Self {
ProposerFactory {
spawn_handle: Box::new(spawn_handle),
client,
transaction_pool,
metrics: PrometheusMetrics::new(prometheus),
_phantom: PhantomData,
max_block_size: DEFAULT_MAX_BLOCK_SIZE,
telemetry,
client,
_phantom: PhantomData,
}
}
}
@@ -95,14 +98,16 @@ impl<A, B, C> ProposerFactory<A, B, C, EnableProofRecording> {
client: Arc<C>,
transaction_pool: Arc<A>,
prometheus: Option<&PrometheusRegistry>,
telemetry: Option<TelemetryHandle>,
) -> Self {
ProposerFactory {
spawn_handle: Box::new(spawn_handle),
client,
transaction_pool,
metrics: PrometheusMetrics::new(prometheus),
_phantom: PhantomData,
max_block_size: DEFAULT_MAX_BLOCK_SIZE,
telemetry,
_phantom: PhantomData,
}
}
}
@@ -147,8 +152,9 @@ impl<B, Block, C, A, PR> ProposerFactory<A, B, C, PR>
transaction_pool: self.transaction_pool.clone(),
now,
metrics: self.metrics.clone(),
_phantom: PhantomData,
max_block_size: self.max_block_size,
telemetry: self.telemetry.clone(),
_phantom: PhantomData,
};
proposer
@@ -189,8 +195,9 @@ pub struct Proposer<B, Block: BlockT, C, A: TransactionPool, PR> {
transaction_pool: Arc<A>,
now: Box<dyn Fn() -> time::Instant + Send + Sync>,
metrics: PrometheusMetrics,
_phantom: PhantomData<(B, PR)>,
max_block_size: usize,
telemetry: Option<TelemetryHandle>,
_phantom: PhantomData<(B, PR)>,
}
impl<A, B, Block, C, PR> sp_consensus::Proposer<Block> for
@@ -371,7 +378,10 @@ impl<A, B, Block, C, PR> Proposer<B, Block, C, A, PR>
.collect::<Vec<_>>()
.join(", ")
);
telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing";
telemetry!(
self.telemetry;
CONSENSUS_INFO;
"prepared_block_for_proposing";
"number" => ?block.header().number(),
"hash" => ?<Block as BlockT>::Hash::from(block.header().hash()),
);
@@ -461,6 +471,7 @@ mod tests {
client.clone(),
txpool.clone(),
None,
None,
);
let cell = Mutex::new((false, time::Instant::now()));
@@ -508,6 +519,7 @@ mod tests {
client.clone(),
txpool.clone(),
None,
None,
);
let cell = Mutex::new((false, time::Instant::now()));
@@ -564,6 +576,7 @@ mod tests {
client.clone(),
txpool.clone(),
None,
None,
);
let proposer = proposer_factory.init_with_now(
@@ -639,6 +652,7 @@ mod tests {
client.clone(),
txpool.clone(),
None,
None,
);
let mut propose_block = |
client: &TestClient,
@@ -45,6 +45,7 @@
//! client.clone(),
//! txpool.clone(),
//! None,
//! None,
//! );
//!
//! // From this factory, we create a `Proposer`.
-2
View File
@@ -64,7 +64,6 @@ arg_enum! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TracingReceiver {
Log,
Telemetry,
}
}
@@ -72,7 +71,6 @@ impl Into<sc_tracing::TracingReceiver> for TracingReceiver {
fn into(self) -> sc_tracing::TracingReceiver {
match self {
TracingReceiver::Log => sc_tracing::TracingReceiver::Log,
TracingReceiver::Telemetry => sc_tracing::TracingReceiver::Telemetry,
}
}
}
+4 -16
View File
@@ -33,7 +33,6 @@ use sc_service::config::{
TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod,
};
use sc_service::{ChainSpec, TracingReceiver, KeepBlocks, TransactionStorageMode};
use sc_telemetry::TelemetryHandle;
use sc_tracing::logging::LoggerBuilder;
use std::net::SocketAddr;
use std::path::PathBuf;
@@ -470,7 +469,6 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
&self,
cli: &C,
task_executor: TaskExecutor,
telemetry_handle: Option<TelemetryHandle>,
) -> Result<Configuration> {
let is_dev = self.is_dev()?;
let chain_id = self.chain_id(is_dev)?;
@@ -488,12 +486,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8);
let is_validator = role.is_authority();
let (keystore_remote, keystore) = self.keystore_config(&config_dir)?;
let telemetry_endpoints = telemetry_handle
.as_ref()
.and_then(|_| self.telemetry_endpoints(&chain_spec).transpose())
.transpose()?
// Don't initialise telemetry if `telemetry_endpoints` == Some([])
.filter(|x| !x.is_empty());
let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?;
let unsafe_pruning = self
.import_params()
@@ -548,7 +541,6 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
role,
base_path: Some(base_path),
informant_output_format: Default::default(),
telemetry_handle,
})
}
@@ -579,16 +571,12 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
/// 1. Sets the panic handler
/// 2. Initializes the logger
/// 3. Raises the FD limit
fn init<C: SubstrateCli>(&self) -> Result<sc_telemetry::TelemetryWorker> {
fn init<C: SubstrateCli>(&self) -> Result<()> {
sp_panic_handler::set(&C::support_url(), &C::impl_version());
let mut logger = LoggerBuilder::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);
@@ -598,7 +586,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
logger.with_colors(false);
}
let telemetry_worker = logger.init()?;
logger.init()?;
if let Some(new_limit) = fdlimit::raise_fd_limit() {
if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT {
@@ -610,7 +598,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
}
}
Ok(telemetry_worker)
Ok(())
}
}
+3 -5
View File
@@ -37,7 +37,6 @@ pub use params::*;
pub use runner::*;
pub use sc_service::{ChainSpec, Role};
use sc_service::{Configuration, TaskExecutor};
use sc_telemetry::TelemetryHandle;
pub use sc_tracing::logging::LoggerBuilder;
pub use sp_version::RuntimeVersion;
use std::io::Write;
@@ -214,16 +213,15 @@ pub trait SubstrateCli: Sized {
&self,
command: &T,
task_executor: TaskExecutor,
telemetry_handle: Option<TelemetryHandle>,
) -> error::Result<Configuration> {
command.create_configuration(self, task_executor, telemetry_handle)
command.create_configuration(self, task_executor)
}
/// Create a runner for the command provided in argument. This will create a Configuration and
/// a tokio runtime
fn create_runner<T: CliConfiguration>(&self, command: &T) -> error::Result<Runner<Self>> {
let telemetry_worker = command.init::<Self>()?;
Runner::new(self, command, telemetry_worker)
command.init::<Self>()?;
Runner::new(self, command)
}
/// Native runtime version.
-15
View File
@@ -25,7 +25,6 @@ use futures::select;
use futures::{future, future::FutureExt, Future};
use log::info;
use sc_service::{Configuration, TaskType, TaskManager};
use sc_telemetry::{TelemetryHandle, TelemetryWorker};
use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL};
use std::marker::PhantomData;
use sc_service::Error as ServiceError;
@@ -115,7 +114,6 @@ where
pub struct Runner<C: SubstrateCli> {
config: Configuration,
tokio_runtime: tokio::runtime::Runtime,
telemetry_worker: TelemetryWorker,
phantom: PhantomData<C>,
}
@@ -124,7 +122,6 @@ impl<C: SubstrateCli> Runner<C> {
pub fn new<T: CliConfiguration>(
cli: &C,
command: &T,
telemetry_worker: TelemetryWorker,
) -> Result<Runner<C>> {
let tokio_runtime = build_runtime()?;
let runtime_handle = tokio_runtime.handle().clone();
@@ -138,16 +135,12 @@ impl<C: SubstrateCli> Runner<C> {
}
};
let telemetry_handle = telemetry_worker.handle();
Ok(Runner {
config: command.create_configuration(
cli,
task_executor.into(),
Some(telemetry_handle),
)?,
tokio_runtime,
telemetry_worker,
phantom: PhantomData,
})
}
@@ -197,7 +190,6 @@ impl<C: SubstrateCli> Runner<C> {
{
self.print_node_infos();
let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?;
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());
Ok(res?)
@@ -236,11 +228,4 @@ impl<C: SubstrateCli> Runner<C> {
pub fn config_mut(&mut self) -> &mut Configuration {
&mut self.config
}
/// Get a new [`TelemetryHandle`].
///
/// This is used when you want to register with the [`TelemetryWorker`].
pub fn telemetry_handle(&self) -> TelemetryHandle {
self.telemetry_worker.handle()
}
}
@@ -45,7 +45,7 @@ use sp_api::ProvideRuntimeApi;
use sp_core::crypto::Pair;
use sp_inherents::{InherentDataProviders, InherentData};
use sp_timestamp::InherentError as TIError;
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO};
use sc_consensus_slots::{CheckedHeader, SlotCompatible, check_equivocation};
use sp_consensus_slots::Slot;
use sp_api::ApiExt;
@@ -129,6 +129,7 @@ pub struct AuraVerifier<C, P, CAW> {
inherent_data_providers: InherentDataProviders,
can_author_with: CAW,
check_for_equivocation: CheckForEquivocation,
telemetry: Option<TelemetryHandle>,
}
impl<C, P, CAW> AuraVerifier<C, P, CAW> {
@@ -137,12 +138,14 @@ impl<C, P, CAW> AuraVerifier<C, P, CAW> {
inherent_data_providers: InherentDataProviders,
can_author_with: CAW,
check_for_equivocation: CheckForEquivocation,
telemetry: Option<TelemetryHandle>,
) -> Self {
Self {
client,
inherent_data_providers,
can_author_with,
check_for_equivocation,
telemetry,
phantom: PhantomData,
}
}
@@ -197,7 +200,10 @@ impl<C, P, CAW> AuraVerifier<C, P, CAW> where
"halting for block {} seconds in the future",
diff
);
telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block";
telemetry!(
self.telemetry;
CONSENSUS_INFO;
"aura.halting_for_future_block";
"diff" => ?diff
);
thread::sleep(Duration::from_secs(diff));
@@ -287,7 +293,12 @@ impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
}
trace!(target: "aura", "Checked {:?}; importing.", pre_header);
telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header);
telemetry!(
self.telemetry;
CONSENSUS_TRACE;
"aura.checked_and_importing";
"pre_header" => ?pre_header,
);
// Look for an authorities-change log.
let maybe_keys = pre_header.digest()
@@ -314,8 +325,13 @@ impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
}
CheckedHeader::Deferred(a, b) => {
debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
telemetry!(CONSENSUS_DEBUG; "aura.header_too_far_in_future";
"hash" => ?hash, "a" => ?a, "b" => ?b
telemetry!(
self.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))
}
@@ -485,6 +501,8 @@ pub struct ImportQueueParams<'a, Block, I, C, S, CAW> {
pub check_for_equivocation: CheckForEquivocation,
/// The duration of one slot.
pub slot_duration: SlotDuration,
/// Telemetry instance used to report telemetry metrics.
pub telemetry: Option<TelemetryHandle>,
}
/// Start an import queue for the Aura consensus algorithm.
@@ -499,6 +517,7 @@ pub fn import_queue<'a, P, Block, I, C, S, CAW>(
can_author_with,
check_for_equivocation,
slot_duration,
telemetry,
}: ImportQueueParams<'a, Block, I, C, S, CAW>
) -> Result<DefaultImportQueue<Block, C>, sp_consensus::Error> where
Block: BlockT,
@@ -530,6 +549,7 @@ pub fn import_queue<'a, P, Block, I, C, S, CAW>(
inherent_data_providers,
can_author_with,
check_for_equivocation,
telemetry,
);
Ok(BasicQueue::new(
+15 -1
View File
@@ -56,6 +56,7 @@ use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use sp_inherents::{InherentDataProviders, InherentData};
use sp_timestamp::{TimestampInherentData, InherentType as TimestampInherent};
use sc_consensus_slots::{SlotInfo, SlotCompatible, StorageChanges, BackoffAuthoringBlocksStrategy};
use sc_telemetry::TelemetryHandle;
use sp_consensus_slots::Slot;
mod import_queue;
@@ -149,6 +150,8 @@ pub struct StartAuraParams<C, SC, I, PF, SO, BS, CAW> {
/// slot. However, the proposing can still take longer when there is some lenience factor applied,
/// because there were no blocks produced for some slots.
pub block_proposal_slot_portion: SlotProportion,
/// Telemetry instance used to report telemetry metrics.
pub telemetry: Option<TelemetryHandle>,
}
/// Start the aura worker. The returned future should be run in a futures executor.
@@ -166,6 +169,7 @@ pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error>(
keystore,
can_author_with,
block_proposal_slot_portion,
telemetry,
}: StartAuraParams<C, SC, I, PF, SO, BS, CAW>,
) -> Result<impl Future<Output = ()>, sp_consensus::Error> where
B: BlockT,
@@ -184,13 +188,14 @@ pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error>(
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
{
let worker = AuraWorker {
client,
client: client.clone(),
block_import: Arc::new(Mutex::new(block_import)),
env,
keystore,
sync_oracle: sync_oracle.clone(),
force_authoring,
backoff_authoring_blocks,
telemetry,
_key_type: PhantomData::<P>,
block_proposal_slot_portion,
};
@@ -218,6 +223,7 @@ struct AuraWorker<C, E, I, P, SO, BS> {
force_authoring: bool,
backoff_authoring_blocks: Option<BS>,
block_proposal_slot_portion: SlotProportion,
telemetry: Option<TelemetryHandle>,
_key_type: PhantomData<P>,
}
@@ -371,6 +377,10 @@ where
}))
}
fn telemetry(&self) -> Option<TelemetryHandle> {
self.telemetry.clone()
}
fn proposing_remaining_duration(
&self,
head: &B::Header,
@@ -595,6 +605,7 @@ mod tests {
inherent_data_providers,
AlwaysCanAuthor,
CheckForEquivocation::Yes,
None,
)
},
PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"),
@@ -670,6 +681,7 @@ mod tests {
keystore,
can_author_with: sp_consensus::AlwaysCanAuthor,
block_proposal_slot_portion: SlotProportion::new(0.5),
telemetry: None,
}).expect("Starts aura"));
}
@@ -729,6 +741,7 @@ mod tests {
sync_oracle: DummyOracle.clone(),
force_authoring: false,
backoff_authoring_blocks: Some(BackoffAuthoringOnFinalizedHeadLagging::default()),
telemetry: None,
_key_type: PhantomData::<AuthorityPair>,
block_proposal_slot_portion: SlotProportion::new(0.5),
};
@@ -777,6 +790,7 @@ mod tests {
sync_oracle: DummyOracle.clone(),
force_authoring: false,
backoff_authoring_blocks: Option::<()>::None,
telemetry: None,
_key_type: PhantomData::<AuthorityPair>,
block_proposal_slot_portion: SlotProportion::new(0.5),
};
+25 -6
View File
@@ -90,7 +90,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::{telemetry, TelemetryHandle, CONSENSUS_TRACE, CONSENSUS_DEBUG};
use sp_consensus::{
BlockImport, Environment, Proposer, BlockCheckParams,
ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError,
@@ -402,6 +402,9 @@ pub struct BabeParams<B: BlockT, C, E, I, SO, SC, CAW, BS> {
/// slot. However, the proposing can still take longer when there is some lenience factor applied,
/// because there were no blocks produced for some slots.
pub block_proposal_slot_portion: SlotProportion,
/// Handle use to report telemetries.
pub telemetry: Option<TelemetryHandle>,
}
/// Start the babe worker.
@@ -418,13 +421,15 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error>(BabeParams {
babe_link,
can_author_with,
block_proposal_slot_portion,
telemetry,
}: BabeParams<B, C, E, I, SO, SC, CAW, BS>) -> Result<
BabeWorker<B>,
sp_consensus::Error,
> where
B: BlockT,
C: ProvideRuntimeApi<B> + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
+ HeaderBackend<B> + HeaderMetadata<B, Error = ClientError> + Send + Sync + 'static,
+ HeaderBackend<B> + HeaderMetadata<B, Error = ClientError>
+ Send + Sync + 'static,
C::Api: BabeApi<B>,
SC: SelectChain<B> + 'static,
E: Environment<B, Error = Error> + Send + Sync + 'static,
@@ -453,6 +458,7 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error>(BabeParams {
slot_notification_sinks: slot_notification_sinks.clone(),
config: config.clone(),
block_proposal_slot_portion,
telemetry,
};
register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?;
@@ -609,6 +615,7 @@ struct BabeSlotWorker<B: BlockT, C, E, I, SO, BS> {
slot_notification_sinks: SlotNotificationSinks<B>,
config: Config,
block_proposal_slot_portion: SlotProportion,
telemetry: Option<TelemetryHandle>,
}
impl<B, C, E, I, Error, SO, BS> sc_consensus_slots::SimpleSlotWorker<B>
@@ -799,6 +806,10 @@ where
}))
}
fn telemetry(&self) -> Option<TelemetryHandle> {
self.telemetry.clone()
}
fn proposing_remaining_duration(
&self,
parent_head: &B::Header,
@@ -947,6 +958,7 @@ pub struct BabeVerifier<Block: BlockT, Client, SelectChain, CAW> {
epoch_changes: SharedEpochChanges<Block, Epoch>,
time_source: TimeSource,
can_author_with: CAW,
telemetry: Option<TelemetryHandle>,
}
impl<Block, Client, SelectChain, CAW> BabeVerifier<Block, Client, SelectChain, CAW>
@@ -1174,6 +1186,7 @@ where
trace!(target: "babe", "Checked {:?}; importing.", pre_header);
telemetry!(
self.telemetry;
CONSENSUS_TRACE;
"babe.checked_and_importing";
"pre_header" => ?pre_header);
@@ -1192,7 +1205,10 @@ where
}
CheckedHeader::Deferred(a, b) => {
debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future";
telemetry!(
self.telemetry;
CONSENSUS_DEBUG;
"babe.header_too_far_in_future";
"hash" => ?hash, "a" => ?a, "b" => ?b
);
Err(Error::<Block>::TooFarInFuture(hash).into())
@@ -1599,11 +1615,13 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
spawner: &impl sp_core::traits::SpawnEssentialNamed,
registry: Option<&Registry>,
can_author_with: CAW,
telemetry: Option<TelemetryHandle>,
) -> ClientResult<DefaultImportQueue<Block, Client>> where
Inner: BlockImport<Block, Error = ConsensusError, Transaction = sp_api::TransactionFor<Client, Block>>
+ Send + Sync + 'static,
Client: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
Client: HeaderBackend<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error>,
Client: ProvideRuntimeApi<Block> + ProvideCache<Block> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + AuxStore
+ Send + Sync + 'static,
Client::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block>,
SelectChain: sp_consensus::SelectChain<Block> + 'static,
CAW: CanAuthorWith<Block> + Send + Sync + 'static,
@@ -1611,13 +1629,14 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?;
let verifier = BabeVerifier {
client,
select_chain,
inherent_data_providers,
config: babe_link.config,
epoch_changes: babe_link.epoch_changes,
time_source: babe_link.time_source,
can_author_with,
telemetry,
client,
};
Ok(BasicQueue::new(
@@ -320,6 +320,7 @@ impl TestNetFactory for BabeTestNet {
epoch_changes: data.link.epoch_changes.clone(),
time_source: data.link.time_source.clone(),
can_author_with: AlwaysCanAuthor,
telemetry: None,
},
mutator: MUTATOR.with(|m| m.borrow().clone()),
}
@@ -432,6 +433,7 @@ fn run_one_test(
keystore,
can_author_with: sp_consensus::AlwaysCanAuthor,
block_proposal_slot_portion: SlotProportion::new(0.5),
telemetry: None,
}).expect("Starts babe"));
}
futures::executor::block_on(future::select(
@@ -300,6 +300,7 @@ mod tests {
client.clone(),
pool.clone(),
None,
None,
);
// this test checks that blocks are created as soon as transactions are imported into the pool.
let (sender, receiver) = futures::channel::oneshot::channel();
@@ -371,6 +372,7 @@ mod tests {
client.clone(),
pool.clone(),
None,
None,
);
// this test checks that blocks are created as soon as an engine command is sent over the stream.
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
@@ -446,6 +448,7 @@ mod tests {
client.clone(),
pool.clone(),
None,
None,
);
// this test checks that blocks are created as soon as an engine command is sent over the stream.
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
+38 -17
View File
@@ -47,7 +47,7 @@ use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header, HashFor, NumberFor}
};
use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
/// The changes that need to applied to the storage to create the state for a block.
///
@@ -180,6 +180,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
/// Returns a `Proposer` to author on top of the given block.
fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer;
/// Returns a [`TelemetryHandle`] if any.
fn telemetry(&self) -> Option<TelemetryHandle>;
/// Remaining duration for proposing.
fn proposing_remaining_duration(
&self,
@@ -197,6 +200,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
<Self::Proposer as Proposer<B>>::Proposal: Unpin + Send + 'static,
{
let (timestamp, slot) = (slot_info.timestamp, slot_info.slot);
let telemetry = self.telemetry();
let proposing_remaining_duration = self.proposing_remaining_duration(&chain_head, &slot_info);
@@ -219,7 +223,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err);
telemetry!(
CONSENSUS_WARN; "slots.unable_fetching_authorities";
telemetry;
CONSENSUS_WARN;
"slots.unable_fetching_authorities";
"slot" => ?chain_head.hash(),
"err" => ?err,
);
@@ -238,6 +244,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
{
debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network.");
telemetry!(
telemetry;
CONSENSUS_DEBUG;
"slots.skipping_proposal_slot";
"authorities_len" => authorities_len,
@@ -263,24 +270,29 @@ pub trait SimpleSlotWorker<B: BlockT> {
);
telemetry!(
telemetry;
CONSENSUS_DEBUG;
"slots.starting_authorship";
"slot_num" => *slot,
"timestamp" => timestamp,
);
let awaiting_proposer = self.proposer(&chain_head).map_err(move |err| {
warn!("Unable to author block in slot {:?}: {:?}", slot, err);
let awaiting_proposer = {
let telemetry = telemetry.clone();
self.proposer(&chain_head).map_err(move |err| {
warn!("Unable to author block in slot {:?}: {:?}", slot, err);
telemetry!(
CONSENSUS_WARN;
"slots.unable_authoring_block";
"slot" => *slot,
"err" => ?err
);
telemetry!(
telemetry;
CONSENSUS_WARN;
"slots.unable_authoring_block";
"slot" => *slot,
"err" => ?err
);
err
});
err
})
};
let logs = self.pre_digest_data(slot, &claim);
@@ -295,7 +307,8 @@ pub trait SimpleSlotWorker<B: BlockT> {
proposing_remaining_duration.mul_f32(0.98),
).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))));
let proposal_work =
let proposal_work = {
let telemetry = telemetry.clone();
futures::future::select(proposing, proposing_remaining).map(move |v| match v {
Either::Left((b, _)) => b.map(|b| (b, claim)),
Either::Right(_) => {
@@ -307,6 +320,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
#[cfg(build_type="debug")]
info!("👉 Recompile your node in `--release` mode to mitigate this problem.");
telemetry!(
telemetry;
CONSENSUS_INFO;
"slots.discarding_proposal_took_too_long";
"slot" => *slot,
@@ -314,7 +328,8 @@ pub trait SimpleSlotWorker<B: BlockT> {
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();
@@ -343,7 +358,10 @@ pub trait SimpleSlotWorker<B: BlockT> {
header_hash,
);
telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block";
telemetry!(
telemetry;
CONSENSUS_INFO;
"slots.pre_sealed_block";
"header_num" => ?header_num,
"hash_now" => ?block_import_params.post_hash(),
"hash_previously" => ?header_hash,
@@ -359,7 +377,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
);
telemetry!(
CONSENSUS_WARN; "slots.err_with_block_built_on";
telemetry;
CONSENSUS_WARN;
"slots.err_with_block_built_on";
"hash" => ?parent_hash,
"err" => ?err,
);
@@ -449,7 +469,8 @@ where
Either::Right(future::ready(Ok(())))
} else {
Either::Left(
worker.on_slot(chain_head, slot_info).then(|_| future::ready(Ok(())))
worker.on_slot(chain_head, slot_info)
.then(|_| future::ready(Ok(())))
)
}
}).then(|res| {
@@ -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::{telemetry, TelemetryHandle, CONSENSUS_INFO};
use sp_finality_grandpa::{AuthorityId, AuthorityList};
use std::cmp::Ord;
@@ -43,8 +43,8 @@ pub enum Error<N, E> {
#[display(fmt = "Multiple pending forced authority set changes are not allowed.")]
MultiplePendingForcedAuthoritySetChanges,
#[display(
fmt = "A pending forced authority set change could not be applied since it must be applied after \
the pending standard change at #{}",
fmt = "A pending forced authority set change could not be applied since it must be applied \
after the pending standard change at #{}",
_0
)]
ForcedAuthoritySetChangeDependencyUnsatisfied(N),
@@ -278,9 +278,13 @@ where
let hash = pending.canon_hash.clone();
let number = pending.canon_height.clone();
debug!(target: "afg", "Inserting potential standard set change signaled at block {:?} \
(delayed by {:?} blocks).",
(&number, &hash), pending.delay);
debug!(
target: "afg",
"Inserting potential standard set change signaled at block {:?} (delayed by {:?}
blocks).",
(&number, &hash),
pending.delay,
);
self.pending_standard_changes.import(
hash,
@@ -289,8 +293,10 @@ where
is_descendent_of,
)?;
debug!(target: "afg", "There are now {} alternatives for the next pending standard change (roots), \
and a total of {} pending standard changes (across all forks).",
debug!(
target: "afg",
"There are now {} alternatives for the next pending standard change (roots), and a
total of {} pending standard changes (across all forks).",
self.pending_standard_changes.roots().count(),
self.pending_standard_changes.iter().count(),
);
@@ -326,9 +332,12 @@ where
))
.unwrap_or_else(|i| i);
debug!(target: "afg", "Inserting potential forced set change at block {:?} \
(delayed by {:?} blocks).",
(&pending.canon_height, &pending.canon_hash), pending.delay);
debug!(
target: "afg",
"Inserting potential forced set change at block {:?} (delayed by {:?} blocks).",
(&pending.canon_height, &pending.canon_hash),
pending.delay,
);
self.pending_forced_changes.insert(idx, pending);
@@ -409,6 +418,7 @@ where
best_number: N,
is_descendent_of: &F,
initial_sync: bool,
telemetry: Option<TelemetryHandle>,
) -> Result<Option<(N, Self)>, Error<N, E>>
where
F: Fn(&H, &H) -> Result<bool, E>,
@@ -461,6 +471,7 @@ where
);
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.applying_forced_authority_set_change";
"block" => ?change.canon_height
@@ -505,6 +516,7 @@ where
finalized_number: N,
is_descendent_of: &F,
initial_sync: bool,
telemetry: Option<&TelemetryHandle>,
) -> Result<Status<H, N>, Error<N, E>>
where
F: Fn(&H, &H) -> Result<bool, E>,
@@ -544,7 +556,10 @@ where
"👴 Applying authority set change scheduled at block #{:?}",
change.canon_height,
);
telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change";
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.applying_scheduled_authority_set_change";
"block" => ?change.canon_height
);
@@ -894,6 +909,7 @@ mod tests {
_ => unreachable!(),
}),
false,
None,
).unwrap();
assert!(status.changed);
@@ -913,6 +929,7 @@ mod tests {
_ => unreachable!(),
}),
false,
None,
).unwrap();
assert!(status.changed);
@@ -971,7 +988,7 @@ mod tests {
// trying to finalize past `change_c` without finalizing `change_a` first
assert!(matches!(
authorities.apply_standard_changes("hash_d", 40, &is_descendent_of, false),
authorities.apply_standard_changes("hash_d", 40, &is_descendent_of, false, None),
Err(Error::ForkTree(fork_tree::Error::UnfinalizedAncestor))
));
assert_eq!(authorities.authority_set_changes, AuthoritySetChanges::empty());
@@ -981,6 +998,7 @@ mod tests {
15,
&is_descendent_of,
false,
None,
).unwrap();
assert!(status.changed);
@@ -996,6 +1014,7 @@ mod tests {
40,
&is_descendent_of,
false,
None,
).unwrap();
assert!(status.changed);
@@ -1138,7 +1157,7 @@ mod tests {
// too early and there's no forced changes to apply.
assert!(
authorities
.apply_forced_changes("hash_a10", 10, &static_is_descendent_of(true), false)
.apply_forced_changes("hash_a10", 10, &static_is_descendent_of(true), false, None)
.unwrap()
.is_none()
);
@@ -1146,7 +1165,7 @@ mod tests {
// too late.
assert!(
authorities
.apply_forced_changes("hash_a16", 16, &is_descendent_of_a, false)
.apply_forced_changes("hash_a16", 16, &is_descendent_of_a, false, None)
.unwrap()
.is_none()
);
@@ -1154,7 +1173,7 @@ mod tests {
// on time -- chooses the right change for this fork.
assert_eq!(
authorities
.apply_forced_changes("hash_a15", 15, &is_descendent_of_a, false)
.apply_forced_changes("hash_a15", 15, &is_descendent_of_a, false, None)
.unwrap()
.unwrap(),
(
@@ -1202,7 +1221,7 @@ mod tests {
// it should be enacted at the same block that signaled it
assert!(
authorities
.apply_forced_changes("hash_a", 5, &static_is_descendent_of(false), false)
.apply_forced_changes("hash_a", 5, &static_is_descendent_of(false), false, None)
.unwrap()
.is_some()
);
@@ -1269,27 +1288,27 @@ mod tests {
// the forced change cannot be applied since the pending changes it depends on
// have not been applied yet.
assert!(matches!(
authorities.apply_forced_changes("hash_d45", 45, &static_is_descendent_of(true), false),
authorities.apply_forced_changes("hash_d45", 45, &static_is_descendent_of(true), false, None),
Err(Error::ForcedAuthoritySetChangeDependencyUnsatisfied(15))
));
assert_eq!(authorities.authority_set_changes, AuthoritySetChanges::empty());
// we apply the first pending standard change at #15
authorities
.apply_standard_changes("hash_a15", 15, &static_is_descendent_of(true), false)
.apply_standard_changes("hash_a15", 15, &static_is_descendent_of(true), false, None)
.unwrap();
assert_eq!(authorities.authority_set_changes, AuthoritySetChanges(vec![(0, 15)]));
// but the forced change still depends on the next standard change
assert!(matches!(
authorities.apply_forced_changes("hash_d", 45, &static_is_descendent_of(true), false),
authorities.apply_forced_changes("hash_d", 45, &static_is_descendent_of(true), false, None),
Err(Error::ForcedAuthoritySetChangeDependencyUnsatisfied(20))
));
assert_eq!(authorities.authority_set_changes, AuthoritySetChanges(vec![(0, 15)]));
// we apply the pending standard change at #20
authorities
.apply_standard_changes("hash_b", 20, &static_is_descendent_of(true), false)
.apply_standard_changes("hash_b", 20, &static_is_descendent_of(true), false, None)
.unwrap();
assert_eq!(authorities.authority_set_changes, AuthoritySetChanges(vec![(0, 15), (1, 20)]));
@@ -1298,7 +1317,7 @@ mod tests {
// at #35. subsequent forced changes on the same branch must be kept
assert_eq!(
authorities
.apply_forced_changes("hash_d", 45, &static_is_descendent_of(true), false)
.apply_forced_changes("hash_d", 45, &static_is_descendent_of(true), false, None)
.unwrap()
.unwrap(),
(
@@ -1395,7 +1414,7 @@ mod tests {
// we apply the change at A0 which should prune it and the fork at B
authorities
.apply_standard_changes("hash_a0", 5, &is_descendent_of, false)
.apply_standard_changes("hash_a0", 5, &is_descendent_of, false, None)
.unwrap();
// the next change is now at A1 (#10)
@@ -1583,14 +1602,14 @@ mod tests {
// applying the standard change at A should not prune anything
// other then the change that was applied
authorities
.apply_standard_changes("A", 5, &is_descendent_of, false)
.apply_standard_changes("A", 5, &is_descendent_of, false, None)
.unwrap();
assert_eq!(authorities.pending_changes().count(), 6);
// same for B
authorities
.apply_standard_changes("B", 10, &is_descendent_of, false)
.apply_standard_changes("B", 10, &is_descendent_of, false, None)
.unwrap();
assert_eq!(authorities.pending_changes().count(), 5);
@@ -1599,7 +1618,7 @@ mod tests {
// finalizing C2 should clear all forced changes
authorities
.apply_standard_changes("C2", 15, &is_descendent_of, false)
.apply_standard_changes("C2", 15, &is_descendent_of, false, None)
.unwrap();
assert_eq!(authorities.pending_forced_changes.len(), 0);
@@ -1607,7 +1626,7 @@ mod tests {
// finalizing C0 should clear all forced changes but D
let mut authorities = authorities2;
authorities
.apply_standard_changes("C0", 15, &is_descendent_of, false)
.apply_standard_changes("C0", 15, &is_descendent_of, false, None)
.unwrap();
assert_eq!(authorities.pending_forced_changes.len(), 1);
@@ -137,7 +137,7 @@ struct V2AuthoritySet<H, N> {
}
pub(crate) fn load_decode<B: AuxStore, T: Decode>(
backend: &B,
backend: &B,
key: &[u8]
) -> ClientResult<Option<T>> {
match backend.get_aux(key)? {
@@ -90,7 +90,7 @@ use sc_network::{ObservedRole, PeerId, ReputationChange};
use parity_scale_codec::{Encode, Decode};
use sp_finality_grandpa::AuthorityId;
use sc_telemetry::{telemetry, CONSENSUS_DEBUG};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG};
use log::{trace, debug};
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
use prometheus_endpoint::{CounterVec, Opts, PrometheusError, register, Registry, U64};
@@ -744,7 +744,7 @@ impl<Block: BlockT> Inner<Block> {
fn note_set(&mut self, set_id: SetId, authorities: Vec<AuthorityId>) -> MaybeMessage<Block> {
{
let local_view = match self.local_view {
ref mut x @ None => x.get_or_insert(LocalView::new(
ref mut x @ None => x.get_or_insert(LocalView::new(
set_id,
Round(1),
)),
@@ -828,7 +828,12 @@ impl<Block: BlockT> Inner<Block> {
// 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.config.telemetry;
CONSENSUS_DEBUG;
"afg.bad_msg_signature";
"signature" => ?full.message.id,
);
return Action::Discard(cost::UNKNOWN_VOTER);
}
@@ -840,7 +845,12 @@ impl<Block: BlockT> Inner<Block> {
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.config.telemetry;
CONSENSUS_DEBUG;
"afg.bad_msg_signature";
"signature" => ?full.message.id,
);
return Action::Discard(cost::BAD_SIGNATURE);
}
@@ -866,7 +876,10 @@ impl<Block: BlockT> Inner<Block> {
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.config.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(),
@@ -1277,6 +1290,7 @@ pub(super) struct GossipValidator<Block: BlockT> {
set_state: environment::SharedVoterSetState<Block>,
report_sender: TracingUnboundedSender<PeerReport>,
metrics: Option<Metrics>,
telemetry: Option<TelemetryHandle>,
}
impl<Block: BlockT> GossipValidator<Block> {
@@ -1287,6 +1301,7 @@ impl<Block: BlockT> GossipValidator<Block> {
config: crate::Config,
set_state: environment::SharedVoterSetState<Block>,
prometheus_registry: Option<&Registry>,
telemetry: Option<TelemetryHandle>,
) -> (GossipValidator<Block>, TracingUnboundedReceiver<PeerReport>) {
let metrics = match prometheus_registry.map(Metrics::register) {
Some(Ok(metrics)) => Some(metrics),
@@ -1303,6 +1318,7 @@ impl<Block: BlockT> GossipValidator<Block> {
set_state,
report_sender: tx,
metrics,
telemetry,
};
(val, rx)
@@ -1411,7 +1427,12 @@ impl<Block: BlockT> GossipValidator<Block> {
Err(e) => {
message_name = None;
debug!(target: "afg", "Error decoding message: {}", e);
telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => "");
telemetry!(
self.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())
@@ -1630,6 +1651,7 @@ mod tests {
name: None,
is_authority: true,
observer_enabled: true,
telemetry: None,
}
}
@@ -1797,6 +1819,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
let set_id = 1;
@@ -1833,6 +1856,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
let set_id = 1;
let auth = AuthorityId::from_slice(&[1u8; 32]);
@@ -1878,6 +1902,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
let set_id = 1;
@@ -1947,6 +1972,7 @@ mod tests {
config(),
set_state.clone(),
None,
None,
);
let set_id = 1;
@@ -2002,6 +2028,7 @@ mod tests {
config(),
set_state.clone(),
None,
None,
);
// the validator starts at set id 2
@@ -2082,6 +2109,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
// the validator starts at set id 1.
@@ -2156,6 +2184,7 @@ mod tests {
config,
voter_set_state(),
None,
None,
);
// the validator starts at set id 1.
@@ -2190,6 +2219,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
// the validator starts at set id 1.
@@ -2250,6 +2280,7 @@ mod tests {
config,
voter_set_state(),
None,
None,
);
// the validator starts at set id 1.
@@ -2289,6 +2320,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
// the validator starts at set id 1.
@@ -2322,6 +2354,7 @@ mod tests {
config,
voter_set_state(),
None,
None,
);
// the validator start at set id 0
@@ -2401,6 +2434,7 @@ mod tests {
config(),
voter_set_state(),
None,
None,
);
// the validator start at set id 0
@@ -2441,6 +2475,7 @@ mod tests {
config,
voter_set_state(),
None,
None,
);
// the validator start at set id 0
@@ -2490,7 +2525,7 @@ mod tests {
#[test]
fn only_gossip_commits_to_peers_on_same_set() {
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None);
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None, None);
// the validator start at set id 1
val.note_set(SetId(1), Vec::new(), |_, _| {});
@@ -2568,7 +2603,7 @@ mod tests {
#[test]
fn expire_commits_from_older_rounds() {
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None);
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None, None);
let commit = |round, set_id, target_number| {
let commit = finality_grandpa::CompactCommit {
@@ -2619,7 +2654,7 @@ mod tests {
#[test]
fn allow_noting_different_authorities_for_same_set() {
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None);
let (val, _) = GossipValidator::<Block>::new(config(), voter_set_state(), None, None);
let a1 = vec![AuthorityId::from_slice(&[0; 32])];
val.note_set(SetId(1), a1.clone(), |_, _| {});
@@ -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::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO};
use crate::{
CatchUp, Commit, CommunicationIn, CommunicationOutH,
@@ -192,6 +192,8 @@ pub(crate) struct NetworkBridge<B: BlockT, N: Network<B>> {
// just an `UnboundedReceiver`, one could also switch to a multi-producer-*multi*-consumer
// channel implementation.
gossip_validator_report_stream: Arc<Mutex<TracingUnboundedReceiver<PeerReport>>>,
telemetry: Option<TelemetryHandle>,
}
impl<B: BlockT, N: Network<B>> Unpin for NetworkBridge<B, N> {}
@@ -206,11 +208,13 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
config: crate::Config,
set_state: crate::environment::SharedVoterSetState<B>,
prometheus_registry: Option<&Registry>,
telemetry: Option<TelemetryHandle>,
) -> Self {
let (validator, report_stream) = GossipValidator::new(
config,
set_state.clone(),
prometheus_registry,
telemetry.clone(),
);
let validator = Arc::new(validator);
@@ -268,6 +272,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
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)),
telemetry,
}
}
@@ -320,6 +325,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
});
let topic = round_topic::<B>(round.0, set_id.0);
let telemetry = self.telemetry.clone();
let incoming = self.gossip_engine.lock().messages_for(topic)
.filter_map(move |notification| {
let decoded = GossipMessage::<B>::decode(&mut &notification.message[..]);
@@ -339,21 +345,30 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
if voters.len().get() <= TELEMETRY_VOTERS_LIMIT {
match &msg.message.message {
PrimaryPropose(propose) => {
telemetry!(CONSENSUS_INFO; "afg.received_propose";
telemetry!(
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";
telemetry!(
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";
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.received_precommit";
"voter" => ?format!("{}", msg.message.id),
"target_number" => ?precommit.target_number,
"target_hash" => ?precommit.target_hash,
@@ -379,6 +394,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
network: self.gossip_engine.clone(),
sender: tx,
has_voted,
telemetry: self.telemetry.clone(),
};
// Combine incoming votes from external GRANDPA nodes with outgoing
@@ -412,6 +428,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
voters,
self.validator.clone(),
self.neighbor_sender.clone(),
self.telemetry.clone(),
);
let outgoing = CommitsOut::<B>::new(
@@ -420,6 +437,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
is_voter,
self.validator.clone(),
self.neighbor_sender.clone(),
self.telemetry.clone(),
);
let outgoing = outgoing.with(|out| {
@@ -491,72 +509,80 @@ fn incoming_global<B: BlockT>(
voters: Arc<VoterSet<AuthorityId>>,
gossip_validator: Arc<GossipValidator<B>>,
neighbor_sender: periodic::NeighborPacketSender<B>,
telemetry: Option<TelemetryHandle>,
) -> impl Stream<Item = CommunicationIn<B>> {
let process_commit = move |
msg: FullCommitMessage<B>,
mut notification: sc_network_gossip::TopicNotification,
gossip_engine: &Arc<Mutex<GossipEngine<B>>>,
gossip_validator: &Arc<GossipValidator<B>>,
voters: &VoterSet<AuthorityId>,
| {
if voters.len().get() <= TELEMETRY_VOTERS_LIMIT {
let precommits_signed_by: Vec<String> =
msg.message.auth_data.iter().map(move |(_, a)| {
format!("{}", a)
}).collect();
let process_commit = {
let telemetry = telemetry.clone();
move |
msg: FullCommitMessage<B>,
mut notification: sc_network_gossip::TopicNotification,
gossip_engine: &Arc<Mutex<GossipEngine<B>>>,
gossip_validator: &Arc<GossipValidator<B>>,
voters: &VoterSet<AuthorityId>,
| {
if voters.len().get() <= TELEMETRY_VOTERS_LIMIT {
let precommits_signed_by: Vec<String> =
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::<B>(
&msg.message,
voters,
msg.round,
msg.set_id,
) {
if let Some(who) = notification.sender {
gossip_engine.lock().report(who, cost);
}
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),
telemetry!(
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(),
);
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);
if let Err(cost) = check_compact_commit::<B>(
&msg.message,
voters,
msg.round,
msg.set_id,
telemetry.as_ref(),
) {
if let Some(who) = notification.sender {
gossip_engine.lock().report(who, cost);
}
return None;
}
};
let cb = voter::Callback::Work(Box::new(cb));
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),
);
Some(voter::CommunicationIn::Commit(round.0, commit, cb))
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));
Some(voter::CommunicationIn::Commit(round.0, commit, cb))
}
};
let process_catch_up = move |
@@ -573,6 +599,7 @@ fn incoming_global<B: BlockT>(
&msg.message,
voters,
msg.set_id,
telemetry.clone(),
) {
if let Some(who) = notification.sender {
gossip_engine.lock().report(who, cost);
@@ -629,6 +656,7 @@ impl<B: BlockT, N: Network<B>> Clone for NetworkBridge<B, N> {
neighbor_sender: self.neighbor_sender.clone(),
neighbor_packet_worker: self.neighbor_packet_worker.clone(),
gossip_validator_report_stream: self.gossip_validator_report_stream.clone(),
telemetry: self.telemetry.clone(),
}
}
}
@@ -655,6 +683,7 @@ pub(crate) struct OutgoingMessages<Block: BlockT> {
sender: mpsc::Sender<SignedMessage<Block>>,
network: Arc<Mutex<GossipEngine<Block>>>,
has_voted: HasVoted<Block>,
telemetry: Option<TelemetryHandle>,
}
impl<B: BlockT> Unpin for OutgoingMessages<B> {}
@@ -717,7 +746,9 @@ impl<Block: BlockT> Sink<Message<Block>> for OutgoingMessages<Block>
);
telemetry!(
CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers";
self.telemetry;
CONSENSUS_DEBUG;
"afg.announcing_blocks_to_voted_peers";
"block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id,
);
@@ -756,6 +787,7 @@ fn check_compact_commit<Block: BlockT>(
voters: &VoterSet<AuthorityId>,
round: Round,
set_id: SetId,
telemetry: Option<&TelemetryHandle>,
) -> Result<(), ReputationChange> {
// 4f + 1 = equivocations from f voters.
let f = voters.total_weight() - voters.threshold();
@@ -797,7 +829,12 @@ fn check_compact_commit<Block: BlockT>(
&mut buf,
) {
debug!(target: "afg", "Bad commit message signature {}", id);
telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id);
telemetry!(
telemetry;
CONSENSUS_DEBUG;
"afg.bad_commit_msg_signature";
"id" => ?id,
);
let cost = Misbehavior::BadCommitMessage {
signatures_checked: i as i32,
blocks_loaded: 0,
@@ -817,6 +854,7 @@ fn check_catch_up<Block: BlockT>(
msg: &CatchUp<Block>,
voters: &VoterSet<AuthorityId>,
set_id: SetId,
telemetry: Option<TelemetryHandle>,
) -> Result<(), ReputationChange> {
// 4f + 1 = equivocations from f voters.
let f = voters.total_weight() - voters.threshold();
@@ -867,6 +905,7 @@ fn check_catch_up<Block: BlockT>(
set_id: SetIdNumber,
mut signatures_checked: usize,
buf: &mut Vec<u8>,
telemetry: Option<TelemetryHandle>,
) -> Result<usize, ReputationChange> where
B: BlockT,
I: Iterator<Item=(Message<B>, &'a AuthorityId, &'a AuthoritySignature)>,
@@ -885,7 +924,12 @@ fn check_catch_up<Block: BlockT>(
buf,
) {
debug!(target: "afg", "Bad catch up message signature {}", id);
telemetry!(CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id);
telemetry!(
telemetry;
CONSENSUS_DEBUG;
"afg.bad_catch_up_msg_signature";
"id" => ?id,
);
let cost = Misbehavior::BadCatchUpMessage {
signatures_checked: signatures_checked as i32,
@@ -909,6 +953,7 @@ fn check_catch_up<Block: BlockT>(
set_id.0,
0,
&mut buf,
telemetry.clone(),
)?;
// check signatures on all contained precommits.
@@ -920,6 +965,7 @@ fn check_catch_up<Block: BlockT>(
set_id.0,
signatures_checked,
&mut buf,
telemetry,
)?;
Ok(())
@@ -932,6 +978,7 @@ struct CommitsOut<Block: BlockT> {
is_voter: bool,
gossip_validator: Arc<GossipValidator<Block>>,
neighbor_sender: periodic::NeighborPacketSender<Block>,
telemetry: Option<TelemetryHandle>,
}
impl<Block: BlockT> CommitsOut<Block> {
@@ -942,6 +989,7 @@ impl<Block: BlockT> CommitsOut<Block> {
is_voter: bool,
gossip_validator: Arc<GossipValidator<Block>>,
neighbor_sender: periodic::NeighborPacketSender<Block>,
telemetry: Option<TelemetryHandle>,
) -> Self {
CommitsOut {
network,
@@ -949,6 +997,7 @@ impl<Block: BlockT> CommitsOut<Block> {
is_voter,
gossip_validator,
neighbor_sender,
telemetry,
}
}
}
@@ -968,8 +1017,12 @@ impl<Block: BlockT> Sink<(RoundNumber, Commit<Block>)> for CommitsOut<Block> {
let (round, commit) = input;
let round = Round(round);
telemetry!(CONSENSUS_DEBUG; "afg.commit_issued";
"target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash,
telemetry!(
self.telemetry;
CONSENSUS_DEBUG;
"afg.commit_issued";
"target_number" => ?commit.target_number,
"target_hash" => ?commit.target_hash,
);
let (precommits, auth_data) = commit.precommits.into_iter()
.map(|signed| (signed.precommit, (signed.signature, signed.id)))
@@ -139,6 +139,7 @@ fn config() -> crate::Config {
name: None,
is_authority: true,
observer_enabled: true,
telemetry: None,
}
}
@@ -189,6 +190,7 @@ pub(crate) fn make_test_network() -> (
config(),
voter_set_state(),
None,
None,
);
(
@@ -39,7 +39,7 @@ use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, Zero,
};
use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO};
use crate::{
local_authority_id, CommandOrError, Commit, Config, Error, NewAuthoritySet, Precommit, Prevote,
@@ -445,6 +445,7 @@ pub(crate) struct Environment<Backend, Block: BlockT, C, N: NetworkT<Block>, SC,
pub(crate) voting_rule: VR,
pub(crate) metrics: Option<Metrics>,
pub(crate) justification_sender: Option<GrandpaJustificationSender<Block>>,
pub(crate) telemetry: Option<TelemetryHandle>,
pub(crate) _phantom: PhantomData<Backend>,
}
@@ -891,7 +892,10 @@ where
};
let report_prevote_metrics = |prevote: &Prevote<Block>| {
telemetry!(CONSENSUS_DEBUG; "afg.prevote_issued";
telemetry!(
self.telemetry;
CONSENSUS_DEBUG;
"afg.prevote_issued";
"round" => round,
"target_number" => ?prevote.target_number,
"target_hash" => ?prevote.target_hash,
@@ -950,7 +954,10 @@ where
};
let report_precommit_metrics = |precommit: &Precommit<Block>| {
telemetry!(CONSENSUS_DEBUG; "afg.precommit_issued";
telemetry!(
self.telemetry;
CONSENSUS_DEBUG;
"afg.precommit_issued";
"round" => round,
"target_number" => ?precommit.target_number,
"target_hash" => ?precommit.target_hash,
@@ -1146,6 +1153,7 @@ where
(round, commit).into(),
false,
self.justification_sender.as_ref(),
self.telemetry.clone(),
)
}
@@ -1210,6 +1218,7 @@ pub(crate) fn finalize_block<BE, Block, Client>(
justification_or_commit: JustificationOrCommit<Block>,
initial_sync: bool,
justification_sender: Option<&GrandpaJustificationSender<Block>>,
telemetry: Option<TelemetryHandle>,
) -> Result<(), CommandOrError<Block::Hash, NumberFor<Block>>>
where
Block: BlockT,
@@ -1245,6 +1254,7 @@ where
number,
&is_descendent_of::<Block, _>(&*client, None),
initial_sync,
None,
).map_err(|e| Error::Safety(e.to_string()))?;
// send a justification notification if a sender exists and in case of error log it.
@@ -1320,7 +1330,10 @@ where
warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e);
e
})?;
telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to";
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.finalized_blocks_up_to";
"number" => ?number, "hash" => ?hash,
);
@@ -1340,7 +1353,10 @@ where
);
}
telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set";
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.generating_new_authority_set";
"number" => ?canon_number, "hash" => ?canon_hash,
"authorities" => ?set_ref.to_vec(),
"set_id" => ?new_id,
@@ -247,9 +247,6 @@ where
.map_err(|_| ClientError::JustificationDecode)?;
justification.verify(current_set_id, &current_authorities)?;
use sc_telemetry::{telemetry, CONSENSUS_INFO};
telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok";
"finalized_header_hash" => ?proof.block);
Ok(proof)
}
@@ -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::TelemetryHandle;
use sp_utils::mpsc::TracingUnboundedSender;
use sp_api::TransactionFor;
@@ -62,6 +63,7 @@ pub struct GrandpaBlockImport<Backend, Block: BlockT, Client, SC> {
send_voter_commands: TracingUnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
authority_set_hard_forks: HashMap<Block::Hash, PendingChange<Block::Hash, NumberFor<Block>>>,
justification_sender: GrandpaJustificationSender<Block>,
telemetry: Option<TelemetryHandle>,
_phantom: PhantomData<Backend>,
}
@@ -76,6 +78,7 @@ impl<Backend, Block: BlockT, Client, SC: Clone> Clone for
send_voter_commands: self.send_voter_commands.clone(),
authority_set_hard_forks: self.authority_set_hard_forks.clone(),
justification_sender: self.justification_sender.clone(),
telemetry: self.telemetry.clone(),
_phantom: PhantomData,
}
}
@@ -338,7 +341,13 @@ 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.telemetry.clone(),
)
.map_err(|e| ConsensusError::ClientImport(e.to_string()))
.map_err(ConsensusError::from)?;
@@ -355,8 +364,11 @@ where
let canon_hash =
self.inner.header(BlockId::Number(canon_number))
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?
.expect("the given block number is less or equal than the current best finalized number; \
current best finalized number must exist in chain; qed.")
.expect(
"the given block number is less or equal than the current best
finalized number; current best finalized number must exist in
chain; qed."
)
.hash();
NewAuthoritySet {
@@ -557,6 +569,7 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
send_voter_commands: TracingUnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
authority_set_hard_forks: Vec<(SetId, PendingChange<Block::Hash, NumberFor<Block>>)>,
justification_sender: GrandpaJustificationSender<Block>,
telemetry: Option<TelemetryHandle>,
) -> GrandpaBlockImport<Backend, Block, Client, SC> {
// check for and apply any forced authority set hard fork that applies
// to the *current* authority set.
@@ -600,6 +613,7 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
send_voter_commands,
authority_set_hard_forks,
justification_sender,
telemetry,
_phantom: PhantomData,
}
}
@@ -644,6 +658,7 @@ where
justification.into(),
initial_sync,
Some(&self.justification_sender),
self.telemetry.clone(),
);
match result {
+60 -22
View File
@@ -79,7 +79,7 @@ use sp_core::{
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use sp_application_crypto::AppKey;
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_INFO, CONSENSUS_DEBUG};
use parking_lot::RwLock;
use finality_grandpa::Error as GrandpaError;
@@ -270,6 +270,8 @@ pub struct Config {
pub name: Option<String>,
/// The keystore that manages the keys of this node.
pub keystore: Option<SyncCryptoStorePtr>,
/// TelemetryHandle instance.
pub telemetry: Option<TelemetryHandle>,
}
impl Config {
@@ -451,6 +453,7 @@ pub struct LinkHalf<Block: BlockT, C, SC> {
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
justification_sender: GrandpaJustificationSender<Block>,
justification_stream: GrandpaJustificationStream<Block>,
telemetry: Option<TelemetryHandle>,
}
impl<Block: BlockT, C, SC> LinkHalf<Block, C, SC> {
@@ -501,6 +504,7 @@ pub fn block_import<BE, Block: BlockT, Client, SC>(
client: Arc<Client>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
telemetry: Option<TelemetryHandle>,
) -> Result<
(
GrandpaBlockImport<BE, Block, Client, SC>,
@@ -518,6 +522,7 @@ where
genesis_authorities_provider,
select_chain,
Default::default(),
telemetry,
)
}
@@ -531,6 +536,7 @@ pub fn block_import_with_authority_set_hard_forks<BE, Block: BlockT, Client, SC>
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor<Block>), AuthorityList)>,
telemetry: Option<TelemetryHandle>,
) -> Result<
(
GrandpaBlockImport<BE, Block, Client, SC>,
@@ -550,13 +556,19 @@ where
&*client,
genesis_hash,
<NumberFor<Block>>::zero(),
|| {
let authorities = genesis_authorities_provider.get()?;
telemetry!(CONSENSUS_DEBUG; "afg.loading_authorities";
"authorities_len" => ?authorities.len()
);
Ok(authorities)
}
{
let telemetry = telemetry.clone();
move || {
let authorities = genesis_authorities_provider.get()?;
telemetry!(
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");
@@ -590,6 +602,7 @@ where
voter_commands_tx,
authority_set_hard_forks,
justification_sender.clone(),
telemetry.clone(),
),
LinkHalf {
client,
@@ -598,6 +611,7 @@ where
voter_commands_rx,
justification_sender,
justification_stream,
telemetry,
},
))
}
@@ -660,14 +674,14 @@ pub struct GrandpaParams<Block: BlockT, C, N, SC, VR> {
/// `sc_network` crate, it is assumed that the Grandpa notifications protocol has been passed
/// to the configuration of the networking. See [`grandpa_peers_set_config`].
pub network: N,
/// If supplied, can be used to hook on telemetry connection established events.
pub telemetry_on_connect: Option<TracingUnboundedReceiver<()>>,
/// A voting rule used to potentially restrict target votes.
pub voting_rule: VR,
/// The prometheus metrics registry.
pub prometheus_registry: Option<prometheus_endpoint::Registry>,
/// The voter state is exposed at an RPC endpoint.
pub shared_voter_state: SharedVoterState,
/// TelemetryHandle instance.
pub telemetry: Option<TelemetryHandle>,
}
/// Returns the configuration value to put in
@@ -706,10 +720,10 @@ where
mut config,
link,
network,
telemetry_on_connect,
voting_rule,
prometheus_registry,
shared_voter_state,
telemetry,
} = grandpa_params;
// NOTE: we have recently removed `run_grandpa_observer` from the public
@@ -725,6 +739,7 @@ where
voter_commands_rx,
justification_sender,
justification_stream: _,
telemetry: _,
} = link;
let network = NetworkBridge::new(
@@ -732,11 +747,16 @@ where
config.clone(),
persistent_data.set_state.clone(),
prometheus_registry.as_ref(),
telemetry.clone(),
);
let conf = config.clone();
let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect {
let telemetry_task = if let Some(telemetry_on_connect) = telemetry
.as_ref()
.map(|x| x.on_connect_stream())
{
let authorities = persistent_data.authority_set.clone();
let telemetry = telemetry.clone();
let events = telemetry_on_connect
.for_each(move |_| {
let current_authorities = authorities.current_authorities();
@@ -751,10 +771,13 @@ where
let authorities = serde_json::to_string(&authorities).expect(
"authorities is always at least an empty vector; \
elements are always of type string",
elements are always of type string",
);
telemetry!(CONSENSUS_INFO; "afg.authority_set";
telemetry!(
telemetry;
CONSENSUS_INFO;
"afg.authority_set";
"authority_id" => authority_id.to_string(),
"authority_set_id" => ?set_id,
"authorities" => authorities,
@@ -778,6 +801,7 @@ where
prometheus_registry,
shared_voter_state,
justification_sender,
telemetry,
);
let voter_work = voter_work.map(|res| match res {
@@ -816,7 +840,7 @@ struct VoterWork<B, Block: BlockT, C, N: NetworkT<Block>, SC, VR> {
env: Arc<Environment<B, Block, C, N, SC, VR>>,
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
network: NetworkBridge<Block, N>,
telemetry: Option<TelemetryHandle>,
/// Prometheus metrics.
metrics: Option<Metrics>,
}
@@ -843,6 +867,7 @@ where
prometheus_registry: Option<prometheus_endpoint::Registry>,
shared_voter_state: SharedVoterState,
justification_sender: GrandpaJustificationSender<Block>,
telemetry: Option<TelemetryHandle>,
) -> Self {
let metrics = match prometheus_registry.as_ref().map(Metrics::register) {
Some(Ok(metrics)) => Some(metrics),
@@ -866,6 +891,7 @@ where
voter_set_state: persistent_data.set_state,
metrics: metrics.as_ref().map(|m| m.environment.clone()),
justification_sender: Some(justification_sender),
telemetry: telemetry.clone(),
_phantom: PhantomData,
});
@@ -877,6 +903,7 @@ where
env,
voter_commands_rx,
network,
telemetry,
metrics,
};
work.rebuild_voter();
@@ -892,7 +919,10 @@ 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.telemetry;
CONSENSUS_DEBUG;
"afg.starting_new_voter";
"name" => ?self.env.config.name(),
"set_id" => ?self.env.set_id,
"authority_id" => authority_id.to_string(),
@@ -911,7 +941,10 @@ where
"authorities is always at least an empty vector; elements are always of type string",
);
telemetry!(CONSENSUS_INFO; "afg.authority_set";
telemetry!(
self.telemetry;
CONSENSUS_INFO;
"afg.authority_set";
"number" => ?chain_info.finalized_number,
"hash" => ?chain_info.finalized_hash,
"authority_id" => authority_id.to_string(),
@@ -971,7 +1004,10 @@ where
let voters: Vec<String> = new.authorities.iter().map(move |(a, _)| {
format!("{}", a)
}).collect();
telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities";
telemetry!(
self.telemetry;
CONSENSUS_INFO;
"afg.voter_command_change_authorities";
"number" => ?new.canon_number,
"hash" => ?new.canon_hash,
"voters" => ?voters,
@@ -992,10 +1028,11 @@ where
})?;
let voters = Arc::new(VoterSet::new(new.authorities.into_iter())
.expect("new authorities come from pending change; \
pending change comes from `AuthoritySet`; \
`AuthoritySet` validates authorities is non-empty and weights are non-zero; \
qed."
.expect(
"new authorities come from pending change; \
pending change comes from `AuthoritySet`; \
`AuthoritySet` validates authorities is non-empty and weights are non-zero; \
qed."
)
);
@@ -1011,6 +1048,7 @@ where
voting_rule: self.env.voting_rule.clone(),
metrics: self.env.metrics.clone(),
justification_sender: self.env.justification_sender.clone(),
telemetry: self.telemetry.clone(),
_phantom: PhantomData,
});
@@ -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::TelemetryHandle;
use sp_utils::mpsc::TracingUnboundedReceiver;
use sp_runtime::traits::{NumberFor, Block as BlockT};
use sp_blockchain::HeaderMetadata;
@@ -67,6 +68,7 @@ fn grandpa_observer<BE, Block: BlockT, Client, S, F>(
last_finalized_number: NumberFor<Block>,
commits: S,
note_round: F,
telemetry: Option<TelemetryHandle>,
) -> impl Future<Output = Result<(), CommandOrError<Block::Hash, NumberFor<Block>>>>
where
NumberFor<Block>: BlockNumberOps,
@@ -121,6 +123,7 @@ where
(round, commit).into(),
false,
justification_sender.as_ref(),
telemetry.clone(),
) {
Ok(_) => {},
Err(e) => return future::err(e),
@@ -172,7 +175,8 @@ where
persistent_data,
voter_commands_rx,
justification_sender,
..
justification_stream: _,
telemetry,
} = link;
let network = NetworkBridge::new(
@@ -180,15 +184,17 @@ where
config.clone(),
persistent_data.set_state.clone(),
None,
telemetry.clone(),
);
let observer_work = ObserverWork::new(
client,
client.clone(),
network,
persistent_data,
config.keystore,
voter_commands_rx,
Some(justification_sender),
telemetry.clone(),
);
let observer_work = observer_work
@@ -210,6 +216,7 @@ struct ObserverWork<B: BlockT, BE, Client, N: NetworkT<B>> {
keystore: Option<SyncCryptoStorePtr>,
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<B::Hash, NumberFor<B>>>,
justification_sender: Option<GrandpaJustificationSender<B>>,
telemetry: Option<TelemetryHandle>,
_phantom: PhantomData<BE>,
}
@@ -228,6 +235,7 @@ where
keystore: Option<SyncCryptoStorePtr>,
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<B::Hash, NumberFor<B>>>,
justification_sender: Option<GrandpaJustificationSender<B>>,
telemetry: Option<TelemetryHandle>,
) -> Self {
let mut work = ObserverWork {
@@ -240,6 +248,7 @@ where
keystore: keystore.clone(),
voter_commands_rx,
justification_sender,
telemetry,
_phantom: PhantomData,
};
work.rebuild_observer();
@@ -289,6 +298,7 @@ where
last_finalized_number,
global_in,
note_round,
self.telemetry.clone(),
);
self.observer = Box::pin(observer);
@@ -429,6 +439,7 @@ mod tests {
None,
voter_command_rx,
None,
None,
);
// Trigger a reputation change through the gossip validator.
+19 -6
View File
@@ -120,6 +120,7 @@ impl TestNetFactory for GrandpaTestNet {
client.clone(),
&self.test_config,
LongestChain::new(backend.clone()),
None,
).expect("Could not create block import for fresh peer.");
let justification_import = Box::new(import.clone());
(
@@ -252,13 +253,14 @@ fn initialize_grandpa(
name: Some(format!("peer#{}", peer_id)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link,
network: net_service,
telemetry_on_connect: None,
voting_rule: (),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network");
@@ -395,13 +397,14 @@ fn finalize_3_voters_1_full_observer() {
name: Some(format!("peer#{}", peer_id)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link: link,
network: net_service,
telemetry_on_connect: None,
voting_rule: (),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
run_grandpa_voter(grandpa_params).expect("all in order with client and network")
@@ -488,13 +491,14 @@ fn transition_3_voters_twice_1_full_observer() {
name: Some(format!("peer#{}", peer_id)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link,
network: net_service,
telemetry_on_connect: None,
voting_rule: (),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
voters.push(run_grandpa_voter(grandpa_params).expect("all in order with client and network"));
@@ -921,6 +925,7 @@ fn voter_persists_its_votes() {
name: Some(format!("peer#{}", 1)),
is_authority: true,
observer_enabled: true,
telemetry: None,
};
let set_state = {
@@ -939,6 +944,7 @@ fn voter_persists_its_votes() {
config.clone(),
set_state,
None,
None,
)
};
@@ -964,13 +970,14 @@ fn voter_persists_its_votes() {
name: Some(format!("peer#{}", 0)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link,
network: net_service,
telemetry_on_connect: None,
voting_rule: VotingRulesBuilder::default().build(),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
run_grandpa_voter(grandpa_params).expect("all in order with client and network")
@@ -1006,13 +1013,14 @@ fn voter_persists_its_votes() {
name: Some(format!("peer#{}", 0)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link,
network: net_service,
telemetry_on_connect: None,
voting_rule: VotingRulesBuilder::default().build(),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
run_grandpa_voter(grandpa_params)
@@ -1165,6 +1173,7 @@ fn finalize_3_voters_1_light_observer() {
name: Some("observer".to_string()),
is_authority: false,
observer_enabled: true,
telemetry: None,
},
net.peers[3].data.lock().take().expect("link initialized at startup; qed"),
net.peers[3].network_service().clone(),
@@ -1206,13 +1215,14 @@ fn voter_catches_up_to_latest_round_when_behind() {
name: Some(format!("peer#{}", peer_id)),
is_authority: true,
observer_enabled: true,
telemetry: None,
},
link,
network: net.lock().peer(peer_id).network_service().clone(),
telemetry_on_connect: None,
voting_rule: (),
prometheus_registry: None,
shared_voter_state: SharedVoterState::empty(),
telemetry: None,
};
Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network"))
@@ -1328,6 +1338,7 @@ where
name: None,
is_authority: true,
observer_enabled: true,
telemetry: None,
};
let network = NetworkBridge::new(
@@ -1335,6 +1346,7 @@ where
config.clone(),
set_state.clone(),
None,
None,
);
Environment {
@@ -1349,6 +1361,7 @@ where
voting_rule,
metrics: None,
justification_sender: None,
telemetry: None,
_phantom: PhantomData,
}
}
-2
View File
@@ -91,5 +91,3 @@ grandpa = { version = "0.9.0", package = "sc-finality-grandpa", path = "../final
grandpa-primitives = { version = "3.0.0", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" }
tokio = { version = "0.2.25", default-features = false }
async-std = { version = "1.6.5", default-features = false }
tracing-subscriber = "0.2.15"
tracing-log = "0.1.1"
+52 -42
View File
@@ -55,8 +55,8 @@ use wasm_timer::SystemTime;
use sc_telemetry::{
telemetry,
ConnectionMessage,
TelemetryConnectionNotifier,
TelemetrySpan,
Telemetry,
TelemetryHandle,
SUBSTRATE_INFO,
};
use sp_transaction_pool::MaintainedTransactionPool;
@@ -213,17 +213,17 @@ pub type TLightClientWithBackend<TBl, TRtApi, TExecDisp, TBackend> = Client<
>;
trait AsCryptoStoreRef {
fn keystore_ref(&self) -> Arc<dyn CryptoStore>;
fn sync_keystore_ref(&self) -> Arc<dyn SyncCryptoStore>;
fn keystore_ref(&self) -> Arc<dyn CryptoStore>;
fn sync_keystore_ref(&self) -> Arc<dyn SyncCryptoStore>;
}
impl<T> AsCryptoStoreRef for Arc<T> where T: CryptoStore + SyncCryptoStore + 'static {
fn keystore_ref(&self) -> Arc<dyn CryptoStore> {
self.clone()
}
fn sync_keystore_ref(&self) -> Arc<dyn SyncCryptoStore> {
self.clone()
}
fn keystore_ref(&self) -> Arc<dyn CryptoStore> {
self.clone()
}
fn sync_keystore_ref(&self) -> Arc<dyn SyncCryptoStore> {
self.clone()
}
}
/// Construct and hold different layers of Keystore wrappers
@@ -291,16 +291,18 @@ impl KeystoreContainer {
/// Creates a new full client for the given config.
pub fn new_full_client<TBl, TRtApi, TExecDisp>(
config: &Configuration,
telemetry: Option<TelemetryHandle>,
) -> Result<TFullClient<TBl, TRtApi, TExecDisp>, Error> where
TBl: BlockT,
TExecDisp: NativeExecutionDispatch + 'static,
{
new_full_parts(config).map(|parts| parts.0)
new_full_parts(config, telemetry).map(|parts| parts.0)
}
/// Create the initial parts of a full node.
pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
config: &Configuration,
telemetry: Option<TelemetryHandle>,
) -> Result<TFullParts<TBl, TRtApi, TExecDisp>, Error> where
TBl: BlockT,
TExecDisp: NativeExecutionDispatch + 'static,
@@ -356,6 +358,7 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
extensions,
Box::new(task_manager.spawn_handle()),
config.prometheus_config.as_ref().map(|config| config.registry.clone()),
telemetry,
ClientConfig {
offchain_worker_enabled : config.offchain_worker.enabled,
offchain_indexing_api: config.offchain_worker.indexing_enabled,
@@ -377,6 +380,7 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
/// Create the initial parts of a light node.
pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
config: &Configuration,
telemetry: Option<TelemetryHandle>,
) -> Result<TLightParts<TBl, TRtApi, TExecDisp>, Error> where
TBl: BlockT,
TExecDisp: NativeExecutionDispatch + 'static,
@@ -421,6 +425,7 @@ pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
executor,
Box::new(task_manager.spawn_handle()),
config.prometheus_config.as_ref().map(|config| config.registry.clone()),
telemetry,
)?);
Ok((client, backend, keystore_container, task_manager, on_demand))
@@ -447,6 +452,7 @@ pub fn new_client<E, Block, RA>(
execution_extensions: ExecutionExtensions<Block>,
spawn_handle: Box<dyn SpawnNamed>,
prometheus_registry: Option<Registry>,
telemetry: Option<TelemetryHandle>,
config: ClientConfig,
) -> Result<
crate::client::Client<
@@ -470,6 +476,7 @@ pub fn new_client<E, Block, RA>(
bad_blocks,
execution_extensions,
prometheus_registry,
telemetry,
config,
)?)
}
@@ -501,10 +508,8 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> {
pub network_status_sinks: NetworkStatusSinks<TBl>,
/// A Sender for RPC requests.
pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
/// Telemetry span.
///
/// This span needs to be entered **before** calling [`spawn_tasks()`].
pub telemetry_span: Option<TelemetrySpan>,
/// Telemetry instance for this node.
pub telemetry: Option<&'a mut Telemetry>,
}
/// Build a shared offchain workers instance.
@@ -541,13 +546,12 @@ pub fn build_offchain_workers<TBl, TCl>(
/// Spawn the tasks that are required to run a node.
pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
params: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
) -> Result<(RpcHandlers, Option<TelemetryConnectionNotifier>), Error>
) -> Result<RpcHandlers, Error>
where
TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> +
StorageProvider<TBl, TBackend> + CallApiAt<TBl> +
Send + 'static,
StorageProvider<TBl, TBackend> + CallApiAt<TBl> + Send + 'static,
<TCl as ProvideRuntimeApi<TBl>>::Api:
sp_api::Metadata<TBl> +
sc_offchain::OffchainWorkerApi<TBl> +
@@ -573,7 +577,7 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
network,
network_status_sinks,
system_rpc_tx,
telemetry_span,
telemetry,
} = params;
let chain_info = client.usage_info().chain;
@@ -584,12 +588,16 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
).map_err(|e| Error::Application(Box::new(e)))?;
let telemetry_connection_notifier = init_telemetry(
&mut config,
telemetry_span,
network.clone(),
client.clone(),
);
let telemetry = telemetry
.map(|telemetry| {
init_telemetry(
&mut config,
network.clone(),
client.clone(),
telemetry,
)
})
.transpose()?;
info!("📦 Highest known block at #{}", chain_info.best_number);
@@ -603,7 +611,11 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
spawn_handle.spawn(
"on-transaction-imported",
transaction_notifications(transaction_pool.clone(), network.clone()),
transaction_notifications(
transaction_pool.clone(),
network.clone(),
telemetry.clone(),
),
);
// Prometheus metrics.
@@ -611,7 +623,7 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
config.prometheus_config.clone()
{
// Set static metrics.
let metrics = MetricsService::with_prometheus(&registry, &config)?;
let metrics = MetricsService::with_prometheus(telemetry.clone(), &registry, &config)?;
spawn_handle.spawn(
"prometheus-endpoint",
prometheus_endpoint::init_prometheus(port, registry).map(drop)
@@ -619,7 +631,7 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
metrics
} else {
MetricsService::new()
MetricsService::new(telemetry.clone())
};
// Periodically updated metrics and telemetry updates.
@@ -659,12 +671,13 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone()));
Ok((rpc_handlers, telemetry_connection_notifier))
Ok(rpc_handlers)
}
async fn transaction_notifications<TBl, TExPool>(
transaction_pool: Arc<TExPool>,
network: Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
telemetry: Option<TelemetryHandle>,
)
where
TBl: BlockT,
@@ -676,9 +689,12 @@ async fn transaction_notifications<TBl, TExPool>(
.for_each(move |hash| {
network.propagate_transaction(hash);
let status = transaction_pool.status();
telemetry!(SUBSTRATE_INFO; "txpool.import";
telemetry!(
telemetry;
SUBSTRATE_INFO;
"txpool.import";
"ready" => status.ready,
"future" => status.future
"future" => status.future,
);
ready(())
})
@@ -687,12 +703,10 @@ async fn transaction_notifications<TBl, TExPool>(
fn init_telemetry<TBl: BlockT, TCl: BlockBackend<TBl>>(
config: &mut Configuration,
telemetry_span: Option<TelemetrySpan>,
network: Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
client: Arc<TCl>,
) -> Option<TelemetryConnectionNotifier> {
let telemetry_span = telemetry_span?;
let endpoints = config.telemetry_endpoints.clone()?;
telemetry: &mut Telemetry,
) -> sc_telemetry::Result<TelemetryHandle> {
let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default();
let connection_message = ConnectionMessage {
name: config.network.node_name.to_owned(),
@@ -708,13 +722,9 @@ fn init_telemetry<TBl: BlockT, TCl: BlockBackend<TBl>>(
network_id: network.local_peer_id().to_base58(),
};
config.telemetry_handle
.as_mut()
.map(|handle| handle.start_telemetry(
telemetry_span,
endpoints,
connection_message,
))
telemetry.start_telemetry(connection_message)?;
Ok(telemetry.handle())
}
fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
@@ -368,6 +368,7 @@ mod tests {
None,
Box::new(TaskExecutor::new()),
None,
None,
Default::default(),
).expect("Creates a client");
+26 -8
View File
@@ -35,7 +35,11 @@ use sp_core::{
};
#[cfg(feature="test-helpers")]
use sp_keystore::SyncCryptoStorePtr;
use sc_telemetry::{telemetry, SUBSTRATE_INFO};
use sc_telemetry::{
telemetry,
TelemetryHandle,
SUBSTRATE_INFO,
};
use sp_runtime::{
Justification, BuildStorage,
generic::{BlockId, SignedBlock, DigestItem},
@@ -115,6 +119,7 @@ pub struct Client<B, E, Block, RA> where Block: BlockT {
block_rules: BlockRules<Block>,
execution_extensions: ExecutionExtensions<Block>,
config: ClientConfig,
telemetry: Option<TelemetryHandle>,
_phantom: PhantomData<RA>,
}
@@ -152,6 +157,7 @@ pub fn new_in_mem<E, Block, S, RA>(
genesis_storage: &S,
keystore: Option<SyncCryptoStorePtr>,
prometheus_registry: Option<Registry>,
telemetry: Option<TelemetryHandle>,
spawn_handle: Box<dyn SpawnNamed>,
config: ClientConfig,
) -> sp_blockchain::Result<Client<
@@ -171,6 +177,7 @@ pub fn new_in_mem<E, Block, S, RA>(
keystore,
spawn_handle,
prometheus_registry,
telemetry,
config,
)
}
@@ -196,6 +203,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
keystore: Option<SyncCryptoStorePtr>,
spawn_handle: Box<dyn SpawnNamed>,
prometheus_registry: Option<Registry>,
telemetry: Option<TelemetryHandle>,
config: ClientConfig,
) -> sp_blockchain::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
where
@@ -218,6 +226,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
Default::default(),
extensions,
prometheus_registry,
telemetry,
config,
)
}
@@ -298,6 +307,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
bad_blocks: BadBlocks<Block>,
execution_extensions: ExecutionExtensions<Block>,
prometheus_registry: Option<Registry>,
telemetry: Option<TelemetryHandle>,
config: ClientConfig,
) -> sp_blockchain::Result<Self> {
if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() {
@@ -330,6 +340,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
block_rules: BlockRules::new(fork_blocks, bad_blocks),
execution_extensions,
config,
telemetry,
_phantom: Default::default(),
})
}
@@ -672,7 +683,10 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
if origin != BlockOrigin::NetworkInitialSync ||
rand::thread_rng().gen_bool(0.1)
{
telemetry!(SUBSTRATE_INFO; "block.import";
telemetry!(
self.telemetry;
SUBSTRATE_INFO;
"block.import";
"height" => height,
"best" => ?hash,
"origin" => ?origin
@@ -989,10 +1003,13 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
let header = self.header(&BlockId::Hash(*last))?
.expect(
"Header already known to exist in DB because it is \
indicated in the tree route; qed"
indicated in the tree route; qed"
);
telemetry!(SUBSTRATE_INFO; "notify.finalized";
telemetry!(
self.telemetry;
SUBSTRATE_INFO;
"notify.finalized";
"height" => format!("{}", header.number()),
"best" => ?last,
);
@@ -1002,7 +1019,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
let header = self.header(&BlockId::Hash(finalized_hash))?
.expect(
"Header already known to exist in DB because it is \
indicated in the tree route; qed"
indicated in the tree route; qed"
);
let notification = FinalityNotification {
@@ -1991,9 +2008,10 @@ impl<B, E, Block, RA> backend::AuxStore for &Client<B, E, Block, RA>
}
impl<BE, E, B, RA> sp_consensus::block_validation::Chain<B> for Client<BE, E, B, RA>
where BE: backend::Backend<B>,
E: CallExecutor<B>,
B: BlockT
where
BE: backend::Backend<B>,
E: CallExecutor<B>,
B: BlockT,
{
fn block_status(
&self,
+3 -1
View File
@@ -22,6 +22,7 @@ use std::sync::Arc;
use sc_executor::RuntimeInfo;
use sp_core::traits::{CodeExecutor, SpawnNamed};
use sc_telemetry::TelemetryHandle;
use sp_runtime::BuildStorage;
use sp_runtime::traits::{Block as BlockT, HashFor};
use sp_blockchain::Result as ClientResult;
@@ -31,7 +32,6 @@ use super::{call_executor::LocalCallExecutor, client::{Client, ClientConfig}};
use sc_client_api::light::Storage as BlockchainStorage;
use sc_light::{Backend, GenesisCallExecutor};
/// Create an instance of light client.
pub fn new_light<B, S, RA, E>(
backend: Arc<Backend<S, HashFor<B>>>,
@@ -39,6 +39,7 @@ pub fn new_light<B, S, RA, E>(
code_executor: E,
spawn_handle: Box<dyn SpawnNamed>,
prometheus_registry: Option<Registry>,
telemetry: Option<TelemetryHandle>,
) -> ClientResult<
Client<
Backend<S, HashFor<B>>,
@@ -70,6 +71,7 @@ pub fn new_light<B, S, RA, E>(
Default::default(),
Default::default(),
prometheus_registry,
telemetry,
ClientConfig::default(),
)
}
-5
View File
@@ -96,11 +96,6 @@ 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<ExtTransport>,
/// 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<sc_telemetry::TelemetryHandle>,
/// The default number of 64KB pages to allocate for Wasm execution
pub default_heap_pages: Option<u64>,
/// Should offchain workers be executed.
+3
View File
@@ -46,6 +46,9 @@ pub enum Error {
#[error(transparent)]
Keystore(#[from] sc_keystore::Error),
#[error(transparent)]
Telemetry(#[from] sc_telemetry::Error),
#[error("Best chain selection strategy (SelectChain) is not provided.")]
SelectChainRequired,
+9 -2
View File
@@ -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::{telemetry, TelemetryHandle, SUBSTRATE_INFO};
use sp_api::ProvideRuntimeApi;
use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto};
use sp_transaction_pool::{PoolStatus, MaintainedTransactionPool};
@@ -112,23 +112,26 @@ pub struct MetricsService {
last_update: Instant,
last_total_bytes_inbound: u64,
last_total_bytes_outbound: u64,
telemetry: Option<TelemetryHandle>,
}
impl MetricsService {
/// Creates a `MetricsService` that only sends information
/// to the telemetry.
pub fn new() -> Self {
pub fn new(telemetry: Option<TelemetryHandle>) -> Self {
MetricsService {
metrics: None,
last_total_bytes_inbound: 0,
last_total_bytes_outbound: 0,
last_update: Instant::now(),
telemetry,
}
}
/// Creates a `MetricsService` that sends metrics
/// to prometheus alongside the telemetry.
pub fn with_prometheus(
telemetry: Option<TelemetryHandle>,
registry: &Registry,
config: &Configuration,
) -> Result<Self, PrometheusError> {
@@ -149,6 +152,7 @@ impl MetricsService {
last_total_bytes_inbound: 0,
last_total_bytes_outbound: 0,
last_update: Instant::now(),
telemetry,
})
}
@@ -245,6 +249,7 @@ impl MetricsService {
// Update/send metrics that are always available.
telemetry!(
self.telemetry;
SUBSTRATE_INFO;
"system.interval";
"height" => best_number,
@@ -307,6 +312,7 @@ impl MetricsService {
};
telemetry!(
self.telemetry;
SUBSTRATE_INFO;
"system.interval";
"peers" => num_peers,
@@ -328,6 +334,7 @@ impl MetricsService {
// Send network state information, if any.
if let Some(net_state) = net_state {
telemetry!(
self.telemetry;
SUBSTRATE_INFO;
"system.network_state";
"state" => net_state,
@@ -20,14 +20,7 @@ use crate::config::TaskExecutor;
use crate::task_manager::TaskManager;
use futures::{future::FutureExt, pin_mut, select};
use parking_lot::Mutex;
use sc_telemetry::TelemetrySpan;
use std::{any::Any, env, sync::Arc, time::Duration};
use tracing::{event::Event, span::Id, subscriber::Subscriber};
use tracing_subscriber::{
layer::{Context, SubscriberExt},
registry::LookupSpan,
Layer,
};
use std::{any::Any, sync::Arc, time::Duration};
#[derive(Clone, Debug)]
struct DropTester(Arc<Mutex<usize>>);
@@ -317,94 +310,3 @@ fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() {
runtime.block_on(task_manager.clean_shutdown());
assert_eq!(drop_tester, 0);
}
struct TestLayer {
spans_found: Arc<Mutex<Option<Vec<Id>>>>,
}
impl<S> Layer<S> for TestLayer
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
fn on_event(&self, _: &Event<'_>, ctx: Context<S>) {
let mut spans_found = self.spans_found.lock();
if spans_found.is_some() {
panic!("on_event called multiple times");
}
*spans_found = Some(ctx.scope().map(|x| x.id()).collect());
}
}
fn setup_subscriber() -> (
impl Subscriber + for<'a> LookupSpan<'a>,
Arc<Mutex<Option<Vec<Id>>>>,
) {
let spans_found = Arc::new(Mutex::new(Default::default()));
let layer = TestLayer {
spans_found: spans_found.clone(),
};
let subscriber = tracing_subscriber::fmt().finish().with(layer);
(subscriber, spans_found)
}
/// This is not an actual test, it is used by the `telemetry_span_is_forwarded_to_task` test.
/// The given test will call the test executable and only execute this one test that
/// test that the telemetry span and the prefix span are forwarded correctly. This needs to be done
/// in a separate process to avoid interfering with the other tests.
#[test]
fn subprocess_telemetry_span_is_forwarded_to_task() {
if env::var("SUBPROCESS_TEST").is_err() {
return;
}
let (subscriber, spans_found) = setup_subscriber();
tracing_log::LogTracer::init().unwrap();
let _sub_guard = tracing::subscriber::set_global_default(subscriber);
let mut runtime = tokio::runtime::Runtime::new().unwrap();
let prefix_span = tracing::info_span!("prefix");
let _enter_prefix_span = prefix_span.enter();
let telemetry_span = TelemetrySpan::new();
let _enter_telemetry_span = telemetry_span.enter();
let handle = runtime.handle().clone();
let task_executor = TaskExecutor::from(move |fut, _| handle.spawn(fut).map(|_| ()));
let task_manager = new_task_manager(task_executor);
let (sender, receiver) = futures::channel::oneshot::channel();
task_manager.spawn_handle().spawn(
"log-something",
async move {
log::info!("boo!");
sender.send(()).unwrap();
}
.boxed(),
);
runtime.block_on(receiver).unwrap();
runtime.block_on(task_manager.clean_shutdown());
let spans = spans_found.lock().take().unwrap();
assert_eq!(2, spans.len());
assert_eq!(spans[0], prefix_span.id().unwrap());
assert_eq!(spans[1], telemetry_span.span().id().unwrap());
}
#[test]
fn telemetry_span_is_forwarded_to_task() {
let executable = env::current_exe().unwrap();
let output = std::process::Command::new(executable)
.env("SUBPROCESS_TEST", "1")
.args(&["--nocapture", "subprocess_telemetry_span_is_forwarded_to_task"])
.output()
.unwrap();
println!("{}", String::from_utf8(output.stdout).unwrap());
eprintln!("{}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
@@ -1744,6 +1744,7 @@ fn cleans_up_closed_notification_sinks_on_block_import() {
&substrate_test_runtime_client::GenesisParameters::default().genesis_storage(),
None,
None,
None,
Box::new(TaskExecutor::new()),
Default::default(),
)
-1
View File
@@ -267,7 +267,6 @@ fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'sta
prometheus_config: None,
telemetry_endpoints: None,
telemetry_external_transport: None,
telemetry_handle: None,
default_heap_pages: None,
offchain_worker: Default::default(),
force_authoring: false,
+1 -3
View File
@@ -25,8 +25,6 @@ rand = "0.7.2"
serde = { version = "1.0.101", features = ["derive"] }
take_mut = "0.2.2"
void = "1.0.2"
tracing = "0.1.10"
tracing-subscriber = "0.2.13"
serde_json = "1.0.41"
sp-utils = { version = "3.0.0", path = "../../primitives/utils" }
chrono = "0.4.19"
thiserror = "1.0.21"
+31
View File
@@ -0,0 +1,31 @@
// 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 <https://www.gnu.org/licenses/>.
#[allow(missing_docs)]
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("IO Error")]
IoError(#[from] std::io::Error),
#[error("This telemetry instance has already been initialized!")]
TelemetryAlreadyInitialized,
#[error("The telemetry worker has been dropped already.")]
TelemetryWorkerDropped,
}
#[allow(missing_docs)]
pub type Result<T> = std::result::Result<T, Error>;
-149
View File
@@ -1,149 +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 <https://www.gnu.org/licenses/>.
use crate::{initialize_transport, TelemetryWorker};
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};
/// 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(Mutex<mpsc::Sender<(Id, u8, String)>>);
impl TelemetryLayer {
/// Create a new [`TelemetryLayer`] and [`TelemetryWorker`].
///
/// The `buffer_size` defaults to 16.
///
/// 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<usize>,
telemetry_external_transport: Option<ExtTransport>,
) -> io::Result<(Self, TelemetryWorker)> {
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))
}
}
impl<S> Layer<S> for TelemetryLayer
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
fn on_event(&self, event: &Event<'_>, ctx: Context<S>) {
if event.metadata().target() != TELEMETRY_LOG_SPAN {
return;
}
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();
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
{
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
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,
);
}
}
}
}
}
#[derive(Debug)]
struct TelemetryAttrs {
verbosity: Option<u64>,
json: Option<String>,
id: Id,
}
impl TelemetryAttrs {
fn new(id: Id) -> Self {
Self {
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) {
// noop
}
fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
if field.name() == "verbosity" {
(*self.0).verbosity = Some(value);
}
}
fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
if field.name() == "json" {
(*self.0).json = Some(format!(
r#"{{"id":{},"ts":{:?},"payload":{}}}"#,
self.0.id.into_u64(),
chrono::Local::now().to_rfc3339().to_string(),
value,
));
}
}
}
+214 -138
View File
@@ -29,7 +29,7 @@
//! 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 with the [`TelemetryWorker`] using a [`TelemetryHandle`].
//! Substrate's nodes initialize/register with the [`TelemetryWorker`] using a [`TelemetryWorkerHandle`].
//! This handle can be cloned and passed around. It uses an asynchronous channel to communicate with
//! the running [`TelemetryWorker`] dedicated to registration. Registering can happen at any point
//! in time during the process execution.
@@ -39,61 +39,45 @@
use futures::{channel::mpsc, prelude::*};
use libp2p::Multiaddr;
use log::{error, warn};
use parking_lot::Mutex;
use serde::Serialize;
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
use std::collections::HashMap;
use tracing::Id;
use std::sync::{atomic, Arc};
pub use libp2p::wasm_ext::ExtTransport;
pub use log;
pub use serde_json;
pub use tracing;
mod endpoints;
mod layer;
mod error;
mod node;
mod transport;
pub use endpoints::*;
pub use layer::*;
pub use error::*;
use node::*;
use transport::*;
/// Substrate DEBUG log level.
pub const SUBSTRATE_DEBUG: u8 = 9;
pub const SUBSTRATE_DEBUG: VerbosityLevel = 9;
/// Substrate INFO log level.
pub const SUBSTRATE_INFO: u8 = 0;
pub const SUBSTRATE_INFO: VerbosityLevel = 0;
/// Consensus TRACE log level.
pub const CONSENSUS_TRACE: u8 = 9;
pub const CONSENSUS_TRACE: VerbosityLevel = 9;
/// Consensus DEBUG log level.
pub const CONSENSUS_DEBUG: u8 = 5;
pub const CONSENSUS_DEBUG: VerbosityLevel = 5;
/// Consensus WARN log level.
pub const CONSENSUS_WARN: u8 = 4;
pub const CONSENSUS_WARN: VerbosityLevel = 4;
/// Consensus INFO log level.
pub const CONSENSUS_INFO: u8 = 1;
pub const CONSENSUS_INFO: VerbosityLevel = 1;
pub(crate) type TelemetryMessage = (Id, u8, String);
/// Telemetry message verbosity.
pub type VerbosityLevel = u8;
/// A handle representing a telemetry span, with the capability to enter the span if it exists.
#[derive(Debug, Clone)]
pub struct TelemetrySpan(tracing::Span);
impl TelemetrySpan {
/// Enters this span, returning a guard that will exit the span when dropped.
pub fn enter(&self) -> tracing::span::Entered {
self.0.enter()
}
/// Constructs a new [`TelemetrySpan`].
pub fn new() -> Self {
Self(tracing::error_span!(TELEMETRY_LOG_SPAN))
}
/// Return a clone of the underlying `tracing::Span` instance.
pub fn span(&self) -> tracing::Span {
self.0.clone()
}
}
pub(crate) type Id = u64;
pub(crate) type TelemetryPayload = serde_json::Map<String, serde_json::Value>;
pub(crate) type TelemetryMessage = (Id, VerbosityLevel, TelemetryPayload);
/// Message sent when the connection (re-)establishes.
#[derive(Debug, Serialize)]
@@ -129,64 +113,79 @@ pub struct TelemetryWorker {
message_sender: mpsc::Sender<TelemetryMessage>,
register_receiver: mpsc::UnboundedReceiver<Register>,
register_sender: mpsc::UnboundedSender<Register>,
id_counter: Arc<atomic::AtomicU64>,
transport: WsTrans,
}
impl TelemetryWorker {
pub(crate) fn new(buffer_size: usize, transport: WsTrans) -> Self {
/// Instantiate a new [`TelemetryWorker`] which can run in background.
///
/// Only one is needed per process.
pub fn new(buffer_size: usize) -> Result<Self> {
let transport = initialize_transport(None)?;
let (message_sender, message_receiver) = mpsc::channel(buffer_size);
let (register_sender, register_receiver) = mpsc::unbounded();
Self {
Ok(Self {
message_receiver,
message_sender,
register_receiver,
register_sender,
id_counter: Arc::new(atomic::AtomicU64::new(1)),
transport,
}
})
}
/// Get a new [`TelemetryHandle`].
/// Instantiate a new [`TelemetryWorker`] which can run in background.
///
/// Only one is needed per process.
pub fn with_transport(buffer_size: usize, transport: Option<ExtTransport>) -> Result<Self> {
let transport = initialize_transport(transport)?;
let (message_sender, message_receiver) = mpsc::channel(buffer_size);
let (register_sender, register_receiver) = mpsc::unbounded();
Ok(Self {
message_receiver,
message_sender,
register_receiver,
register_sender,
id_counter: Arc::new(atomic::AtomicU64::new(1)),
transport,
})
}
/// Get a new [`TelemetryWorkerHandle`].
///
/// This is used when you want to register with the [`TelemetryWorker`].
pub fn handle(&self) -> TelemetryHandle {
TelemetryHandle {
message_sender: self.register_sender.clone(),
pub fn handle(&self) -> TelemetryWorkerHandle {
TelemetryWorkerHandle {
message_sender: self.message_sender.clone(),
register_sender: self.register_sender.clone(),
id_counter: self.id_counter.clone(),
}
}
/// Get a clone of the channel's `Sender` used to send telemetry events.
pub(crate) fn message_sender(&self) -> mpsc::Sender<TelemetryMessage> {
self.message_sender.clone()
}
/// Run the telemetry worker.
///
/// This should be run in a background task.
pub async fn run(self) {
let Self {
mut message_receiver,
message_sender: _,
mut register_receiver,
register_sender: _,
transport,
} = self;
let mut node_map: HashMap<Id, Vec<(u8, Multiaddr)>> = HashMap::new();
pub async fn run(mut self) {
let mut node_map: HashMap<Id, Vec<(VerbosityLevel, Multiaddr)>> = HashMap::new();
let mut node_pool: HashMap<Multiaddr, _> = HashMap::new();
let mut pending_connection_notifications: Vec<_> = Vec::new();
loop {
futures::select! {
message = message_receiver.next() => Self::process_message(
message = self.message_receiver.next() => Self::process_message(
message,
&mut node_pool,
&node_map,
).await,
init_payload = register_receiver.next() => Self::process_register(
init_payload = self.register_receiver.next() => Self::process_register(
init_payload,
&mut node_pool,
&mut node_map,
transport.clone(),
&mut pending_connection_notifications,
self.transport.clone(),
).await,
}
}
@@ -195,7 +194,8 @@ impl TelemetryWorker {
async fn process_register(
input: Option<Register>,
node_pool: &mut HashMap<Multiaddr, Node<WsTrans>>,
node_map: &mut HashMap<Id, Vec<(u8, Multiaddr)>>,
node_map: &mut HashMap<Id, Vec<(VerbosityLevel, Multiaddr)>>,
pending_connection_notifications: &mut Vec<(Multiaddr, ConnectionNotifierSender)>,
transport: WsTrans,
) {
let input = input.expect("the stream is never closed; qed");
@@ -212,7 +212,7 @@ impl TelemetryWorker {
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("id".to_string(), id.into());
obj.insert("payload".to_string(), value.into());
Some(obj)
}
@@ -245,6 +245,16 @@ impl TelemetryWorker {
});
node.connection_messages.extend(connection_message.clone());
pending_connection_notifications.retain(|(addr_b, connection_message)| {
if *addr_b == addr {
node.telemetry_connection_notifier
.push(connection_message.clone());
false
} else {
true
}
});
}
}
Register::Notifier {
@@ -252,15 +262,15 @@ impl TelemetryWorker {
connection_notifier,
} => {
for addr in addresses {
// If the Node has been initialized, we directly push the connection_notifier.
// Otherwise we push it to a queue that will be consumed when the connection
// initializes, thus ensuring that the connection notifier will be sent to the
// Node when it becomes available.
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,
);
pending_connection_notifications.push((addr, connection_notifier.clone()));
}
}
}
@@ -271,21 +281,31 @@ impl TelemetryWorker {
async fn process_message(
input: Option<TelemetryMessage>,
node_pool: &mut HashMap<Multiaddr, Node<WsTrans>>,
node_map: &HashMap<Id, Vec<(u8, Multiaddr)>>,
node_map: &HashMap<Id, Vec<(VerbosityLevel, Multiaddr)>>,
) {
let (id, verbosity, message) = input.expect("the stream is never closed; qed");
let (id, verbosity, payload) = input.expect("the stream is never closed; qed");
let ts = chrono::Local::now().to_rfc3339().to_string();
let mut message = serde_json::Map::new();
message.insert("id".into(), id.into());
message.insert("ts".into(), ts.into());
message.insert("payload".into(), payload.into());
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.
// This is a normal error because the telemetry ID exists before the telemetry is
// initialized.
log::trace!(
target: "telemetry",
"Received telemetry log for unknown id ({:?}): {}",
id,
message,
serde_json::to_string(&message)
.unwrap_or_else(|err| format!(
"could not be serialized ({}): {:?}",
err,
message,
)),
);
return;
};
@@ -304,12 +324,17 @@ impl TelemetryWorker {
if let Some(node) = node_pool.get_mut(&addr) {
let _ = node.send(message.clone()).await;
} else {
log::error!(
log::debug!(
target: "telemetry",
"Received message for unknown node ({}). This is a bug. \
Message sent: {}",
addr,
message,
serde_json::to_string(&message)
.unwrap_or_else(|err| format!(
"could not be serialized ({}): {:?}",
err,
message,
)),
);
}
}
@@ -318,11 +343,41 @@ impl TelemetryWorker {
/// Handle to the [`TelemetryWorker`] thats allows initializing the telemetry for a Substrate node.
#[derive(Debug, Clone)]
pub struct TelemetryHandle {
message_sender: mpsc::UnboundedSender<Register>,
pub struct TelemetryWorkerHandle {
message_sender: mpsc::Sender<TelemetryMessage>,
register_sender: mpsc::UnboundedSender<Register>,
id_counter: Arc<atomic::AtomicU64>,
}
impl TelemetryHandle {
impl TelemetryWorkerHandle {
/// Instantiate a new [`Telemetry`] object.
pub fn new_telemetry(&mut self, endpoints: TelemetryEndpoints) -> Telemetry {
let addresses = endpoints.0.iter().map(|(addr, _)| addr.clone()).collect();
Telemetry {
message_sender: self.message_sender.clone(),
register_sender: self.register_sender.clone(),
id: self.id_counter.fetch_add(1, atomic::Ordering::Relaxed),
connection_notifier: TelemetryConnectionNotifier {
register_sender: self.register_sender.clone(),
addresses,
},
endpoints: Some(endpoints),
}
}
}
/// A telemetry instance that can be used to send telemetry messages.
#[derive(Debug)]
pub struct Telemetry {
message_sender: mpsc::Sender<TelemetryMessage>,
register_sender: mpsc::UnboundedSender<Register>,
id: Id,
connection_notifier: TelemetryConnectionNotifier,
endpoints: Option<TelemetryEndpoints>,
}
impl Telemetry {
/// Initialize the telemetry with the endpoints provided in argument for the current substrate
/// node.
///
@@ -333,42 +388,67 @@ 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,
span: TelemetrySpan,
endpoints: TelemetryEndpoints,
connection_message: ConnectionMessage,
) -> TelemetryConnectionNotifier {
let Self { message_sender } = self;
let connection_notifier = TelemetryConnectionNotifier {
message_sender: message_sender.clone(),
addresses: endpoints.0.iter().map(|(addr, _)| addr.clone()).collect(),
pub fn start_telemetry(&mut self, connection_message: ConnectionMessage) -> Result<()> {
let endpoints = match self.endpoints.take() {
Some(x) => x,
None => return Err(Error::TelemetryAlreadyInitialized),
};
match span.0.id() {
Some(id) => {
match message_sender.unbounded_send(Register::Telemetry {
id,
endpoints,
connection_message,
}) {
Ok(()) => {}
Err(err) => error!(
target: "telemetry",
"Could not initialize telemetry: \
the telemetry is probably already running: {}",
err,
),
}
}
None => error!(
self.register_sender
.unbounded_send(Register::Telemetry {
id: self.id,
endpoints,
connection_message,
})
.map_err(|_| Error::TelemetryWorkerDropped)
}
/// Make a new clonable handle to this [`Telemetry`]. This is used for reporting telemetries.
pub fn handle(&self) -> TelemetryHandle {
TelemetryHandle {
message_sender: Arc::new(Mutex::new(self.message_sender.clone())),
id: self.id,
connection_notifier: self.connection_notifier.clone(),
}
}
}
/// Handle to a [`Telemetry`].
///
/// Used to report telemetry messages.
#[derive(Debug, Clone)]
pub struct TelemetryHandle {
message_sender: Arc<Mutex<mpsc::Sender<TelemetryMessage>>>,
id: Id,
connection_notifier: TelemetryConnectionNotifier,
}
impl TelemetryHandle {
/// Send telemetry messages.
pub fn send_telemetry(&self, verbosity: VerbosityLevel, payload: TelemetryPayload) {
match self
.message_sender
.lock()
.try_send((self.id, verbosity, payload))
{
Ok(()) => {}
Err(err) if err.is_full() => log::trace!(
target: "telemetry",
"Could not initialize telemetry: the span could not be entered",
"Telemetry channel full.",
),
Err(_) => log::trace!(
target: "telemetry",
"Telemetry channel closed.",
),
}
}
connection_notifier
/// Get event stream for telemetry connection established events.
///
/// This function will return an error if the telemetry has already been started by
/// [`Telemetry::start_telemetry`].
pub fn on_connect_stream(&self) -> ConnectionNotifierReceiver {
self.connection_notifier.on_connect_stream()
}
}
@@ -376,18 +456,14 @@ impl TelemetryHandle {
/// (re-)establishes.
#[derive(Clone, Debug)]
pub struct TelemetryConnectionNotifier {
message_sender: mpsc::UnboundedSender<Register>,
register_sender: mpsc::UnboundedSender<Register>,
addresses: Vec<Multiaddr>,
}
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 (message_sender, message_receiver) = tracing_unbounded("mpsc_telemetry_on_connect");
if let Err(err) = self.message_sender.unbounded_send(Register::Notifier {
fn on_connect_stream(&self) -> ConnectionNotifierReceiver {
let (message_sender, message_receiver) = connection_notifier_channel();
if let Err(err) = self.register_sender.unbounded_send(Register::Notifier {
addresses: self.addresses.clone(),
connection_notifier: message_sender,
}) {
@@ -428,34 +504,34 @@ enum Register {
/// # 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,
/// # let telemetry: Option<TelemetryHandle> = None;
/// telemetry!(
/// telemetry; // an `Option<TelemetryHandle>`
/// 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 {
( $verbosity:expr; $msg:expr; $( $t:tt )* ) => {{
let verbosity: u8 = $verbosity;
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("msg".into(), $msg.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(),
);
},
( $telemetry:expr; $verbosity:expr; $msg:expr; $( $t:tt )* ) => {{
if let Some(telemetry) = $telemetry.as_ref() {
let verbosity: $crate::VerbosityLevel = $verbosity;
match format_fields_to_json!($($t)*) {
Err(err) => {
$crate::log::debug!(
target: "telemetry",
"Could not serialize value for telemetry: {}",
err,
);
},
Ok(mut json) => {
json.insert("msg".into(), $msg.into());
telemetry.send_telemetry(verbosity, json);
},
}
}
}};
}
+28 -8
View File
@@ -16,6 +16,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::TelemetryPayload;
use futures::channel::mpsc;
use futures::prelude::*;
use libp2p::core::transport::Transport;
use libp2p::Multiaddr;
@@ -23,7 +25,13 @@ 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<()>;
pub(crate) type ConnectionNotifierSender = mpsc::Sender<()>;
pub(crate) type ConnectionNotifierReceiver = mpsc::Receiver<()>;
pub(crate) fn connection_notifier_channel() -> (ConnectionNotifierSender, ConnectionNotifierReceiver)
{
mpsc::channel(0)
}
/// Handler for a single telemetry node.
///
@@ -45,7 +53,7 @@ pub(crate) struct Node<TTrans: Transport> {
/// Transport used to establish new connections.
transport: TTrans,
/// Messages that are sent when the connection (re-)establishes.
pub(crate) connection_messages: Vec<serde_json::Map<String, serde_json::Value>>,
pub(crate) connection_messages: Vec<TelemetryPayload>,
/// Notifier for when the connection (re-)establishes.
pub(crate) telemetry_connection_notifier: Vec<ConnectionNotifierSender>,
}
@@ -123,7 +131,7 @@ where
pub(crate) enum Infallible {}
impl<TTrans: Transport, TSinkErr> Sink<String> for Node<TTrans>
impl<TTrans: Transport, TSinkErr> Sink<TelemetryPayload> for Node<TTrans>
where
TTrans: Clone + Unpin,
TTrans::Dial: Unpin,
@@ -234,16 +242,28 @@ where
Poll::Ready(Ok(()))
}
fn start_send(mut self: Pin<&mut Self>, item: String) -> Result<(), Self::Error> {
fn start_send(mut self: Pin<&mut Self>, item: TelemetryPayload) -> Result<(), Self::Error> {
match &mut self.socket {
NodeSocket::Connected(conn) => {
let _ = conn.sink.start_send_unpin(item.into()).expect("boo");
}
NodeSocket::Connected(conn) => match serde_json::to_vec(&item) {
Ok(data) => {
let _ = conn.sink.start_send_unpin(data);
}
Err(err) => log::debug!(
target: "telemetry",
"Could not serialize payload: {}",
err,
),
},
_socket => {
log::trace!(
target: "telemetry",
"Message has been discarded: {}",
item,
serde_json::to_string(&item)
.unwrap_or_else(|err| format!(
"could not be serialized ({}): {:?}",
err,
item,
)),
);
}
}
-1
View File
@@ -30,7 +30,6 @@ tracing-core = "0.1.17"
tracing-log = "0.1.1"
tracing-subscriber = "0.2.15"
sp-tracing = { version = "3.0.0", path = "../../primitives/tracing" }
sc-telemetry = { version = "3.0.0", path = "../telemetry" }
sc-tracing-proc-macro = { version = "3.0.0", path = "./proc-macro" }
[target.'cfg(target_os = "unknown")'.dependencies]
+1 -35
View File
@@ -24,7 +24,7 @@
//!
//! See `sp-tracing` for examples on how to use tracing.
//!
//! Currently we provide `Log` (default), `Telemetry` variants for `Receiver`
//! Currently we only provide `Log` (default).
#![warn(missing_docs)]
@@ -46,7 +46,6 @@ use tracing_subscriber::{
CurrentSpan,
layer::{Layer, Context},
};
use sc_telemetry::{telemetry, SUBSTRATE_INFO};
use sp_tracing::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER};
#[doc(hidden)]
@@ -67,8 +66,6 @@ pub struct ProfilingLayer {
pub enum TracingReceiver {
/// Output to logger
Log,
/// Output to telemetry
Telemetry,
}
impl Default for TracingReceiver {
@@ -214,10 +211,6 @@ impl ProfilingLayer {
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),
targets,
),
}
}
@@ -392,33 +385,6 @@ 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;
impl TraceHandler for TelemetryTraceHandler {
fn handle_span(&self, span_datum: SpanDatum) {
telemetry!(SUBSTRATE_INFO; "tracing.profiling";
"name" => span_datum.name,
"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()),
"values" => span_datum.values
);
}
fn handle_event(&self, event: TraceEvent) {
telemetry!(SUBSTRATE_INFO; "tracing.event";
"name" => event.name,
"target" => event.target,
"parent_id" => event.parent_id.as_ref().map(|i| i.into_u64()),
"values" => event.values
);
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -62,10 +62,6 @@ 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 writer = &mut MaybeColorWriter::new(self.enable_color, writer);
let normalized_meta = event.normalized_metadata();
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
+19 -47
View File
@@ -29,16 +29,16 @@ mod layers;
pub use directives::*;
pub use sc_tracing_proc_macro::*;
use sc_telemetry::{ExtTransport, TelemetryWorker};
use std::io;
use tracing::Subscriber;
use tracing_subscriber::{
filter::LevelFilter,
fmt::time::ChronoLocal,
fmt::{
format, FormatEvent, FormatFields, Formatter, Layer as FmtLayer, MakeWriter,
SubscriberBuilder,
},
layer::{self, SubscriberExt}, filter::LevelFilter,
layer::{self, SubscriberExt},
registry::LookupSpan,
EnvFilter, FmtSubscriber, Layer, Registry,
};
@@ -75,8 +75,6 @@ fn prepare_subscriber<N, E, F, W>(
directives: &str,
profiling_targets: Option<&str>,
force_colors: Option<bool>,
telemetry_buffer_size: Option<usize>,
telemetry_external_transport: Option<ExtTransport>,
builder_hook: impl Fn(
SubscriberBuilder<
format::DefaultFields,
@@ -85,7 +83,7 @@ fn prepare_subscriber<N, E, F, W>(
fn() -> std::io::Stderr,
>,
) -> SubscriberBuilder<N, E, F, W>,
) -> Result<(impl Subscriber + for<'a> LookupSpan<'a>, TelemetryWorker)>
) -> Result<impl Subscriber + for<'a> LookupSpan<'a>>
where
N: for<'writer> FormatFields<'writer> + 'static,
E: FormatEvent<Registry, N> + 'static,
@@ -130,10 +128,9 @@ where
if let Some(profiling_targets) = profiling_targets {
env_filter = parse_user_directives(env_filter, profiling_targets)?;
env_filter = env_filter
.add_directive(
parse_default_directive("sc_tracing=trace").expect("provided directive is valid")
);
env_filter = env_filter.add_directive(
parse_default_directive("sc_tracing=trace").expect("provided directive is valid"),
);
}
let max_level_hint = Layer::<FmtSubscriber>::max_level_hint(&env_filter);
@@ -164,8 +161,6 @@ where
"%Y-%m-%d %H:%M:%S%.3f".to_string()
});
let (telemetry_layer, telemetry_worker) =
sc_telemetry::TelemetryLayer::new(telemetry_buffer_size, telemetry_external_transport)?;
let event_format = EventFormat {
timer,
display_target: !simple,
@@ -187,20 +182,18 @@ where
#[cfg(not(target_os = "unknown"))]
let builder = builder_hook(builder);
let subscriber = builder.finish().with(PrefixLayer).with(telemetry_layer);
let subscriber = builder.finish().with(PrefixLayer);
#[cfg(target_os = "unknown")]
let subscriber = subscriber.with(ConsoleLogLayer::new(event_format));
Ok((subscriber, telemetry_worker))
Ok(subscriber)
}
/// A builder that is used to initialize the global logger.
pub struct LoggerBuilder {
directives: String,
profiling: Option<(crate::TracingReceiver, String)>,
telemetry_buffer_size: Option<usize>,
telemetry_external_transport: Option<ExtTransport>,
log_reloading: bool,
force_colors: Option<bool>,
}
@@ -211,8 +204,6 @@ impl LoggerBuilder {
Self {
directives: directives.into(),
profiling: None,
telemetry_buffer_size: None,
telemetry_external_transport: None,
log_reloading: true,
force_colors: None,
}
@@ -234,18 +225,6 @@ impl LoggerBuilder {
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);
self
}
/// Force enable/disable colors.
pub fn with_colors(&mut self, enable: bool) -> &mut Self {
self.force_colors = Some(enable);
@@ -255,64 +234,56 @@ impl LoggerBuilder {
/// Initialize the global logger
///
/// This sets various global logging and tracing instances and thus may only be called once.
pub fn init(self) -> Result<TelemetryWorker> {
pub fn init(self) -> Result<()> {
if let Some((tracing_receiver, profiling_targets)) = self.profiling {
if self.log_reloading {
let (subscriber, telemetry_worker) = prepare_subscriber(
let subscriber = prepare_subscriber(
&self.directives,
Some(&profiling_targets),
self.force_colors,
self.telemetry_buffer_size,
self.telemetry_external_transport,
|builder| enable_log_reloading!(builder),
)?;
let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets);
tracing::subscriber::set_global_default(subscriber.with(profiling))?;
Ok(telemetry_worker)
Ok(())
} else {
let (subscriber, telemetry_worker) = prepare_subscriber(
let subscriber = prepare_subscriber(
&self.directives,
Some(&profiling_targets),
self.force_colors,
self.telemetry_buffer_size,
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)
Ok(())
}
} else {
if self.log_reloading {
let (subscriber, telemetry_worker) = prepare_subscriber(
let subscriber = prepare_subscriber(
&self.directives,
None,
self.force_colors,
self.telemetry_buffer_size,
self.telemetry_external_transport,
|builder| enable_log_reloading!(builder),
)?;
tracing::subscriber::set_global_default(subscriber)?;
Ok(telemetry_worker)
Ok(())
} else {
let (subscriber, telemetry_worker) = prepare_subscriber(
let subscriber = prepare_subscriber(
&self.directives,
None,
self.force_colors,
self.telemetry_buffer_size,
self.telemetry_external_transport,
|builder| builder,
)?;
tracing::subscriber::set_global_default(subscriber)?;
Ok(telemetry_worker)
Ok(())
}
}
}
@@ -335,7 +306,8 @@ mod tests {
#[test]
fn test_logger_filters() {
if env::var("RUN_TEST_LOGGER_FILTERS").is_ok() {
let test_directives = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error";
let test_directives =
"afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error";
init_logger(&test_directives);
tracing::dispatcher::get_default(|dispatcher| {
+1
View File
@@ -229,6 +229,7 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
sc_offchain::OffchainDb::factory_from_backend(&*self.backend),
),
None,
None,
ClientConfig {
offchain_indexing_api: self.enable_offchain_indexing_api,
..Default::default()
-1
View File
@@ -27,7 +27,6 @@ sc-informant = { version = "0.9.0", path = "../../client/informant" }
sc-service = { version = "0.9.0", path = "../../client/service", default-features = false }
sc-network = { path = "../../client/network", version = "0.9.0"}
sc-chain-spec = { path = "../../client/chain-spec", version = "3.0.0"}
sc-telemetry = { path = "../../client/telemetry", version = "3.0.0"}
sc-tracing = { path = "../../client/tracing", version = "3.0.0"}
# Imported just for the `wasm-bindgen` feature
+2 -10
View File
@@ -24,7 +24,6 @@ use sc_service::{
GenericChainSpec, RuntimeGenesis,
KeepBlocks, TransactionStorageMode,
};
use sc_telemetry::TelemetryHandle;
use sc_tracing::logging::LoggerBuilder;
use wasm_bindgen::prelude::*;
use futures::{
@@ -37,13 +36,8 @@ 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`.
pub fn init_logging_and_telemetry(
pattern: &str,
) -> Result<sc_telemetry::TelemetryWorker, sc_tracing::logging::Error> {
let transport = ExtTransport::new(ffi::websocket_transport());
let mut logger = LoggerBuilder::new(pattern);
logger.with_transport(transport);
logger.init()
pub fn init_logging(pattern: &str) -> Result<(), sc_tracing::logging::Error> {
LoggerBuilder::new(pattern).init()
}
/// Create a service configuration from a chain spec.
@@ -51,7 +45,6 @@ pub fn init_logging_and_telemetry(
/// This configuration contains good defaults for a browser light client.
pub async fn browser_configuration<G, E>(
chain_spec: GenericChainSpec<G, E>,
telemetry_handle: Option<TelemetryHandle>,
) -> Result<Configuration, Box<dyn std::error::Error>>
where
G: RuntimeGenesis + 'static,
@@ -82,7 +75,6 @@ where
async {}
}).into(),
telemetry_external_transport: Some(transport),
telemetry_handle,
role: Role::Light,
database: {
info!("Opening Indexed DB database '{}'...", name);