// This file is part of Substrate.
// Copyright (C) 2017-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 .
//! Console informant. Prints sync progress and block events. Runs on the calling thread.
use ansi_term::Colour;
use futures::prelude::*;
use futures_timer::Delay;
use log::{debug, info, trace};
use parity_util_mem::MallocSizeOf;
use sc_client_api::{BlockchainEvents, UsageProvider};
use sc_network::NetworkService;
use sc_transaction_pool_api::TransactionPool;
use sp_blockchain::HeaderMetadata;
use sp_runtime::traits::{Block as BlockT, Header};
use std::{collections::VecDeque, fmt::Display, sync::Arc, time::Duration};
mod display;
/// Creates a stream that returns a new value every `duration`.
fn interval(duration: Duration) -> impl Stream- + Unpin {
futures::stream::unfold((), move |_| Delay::new(duration).map(|_| Some(((), ())))).map(drop)
}
/// The format to print telemetry output in.
#[derive(Clone, Debug)]
pub struct OutputFormat {
/// Enable color output in logs.
///
/// Is enabled by default.
pub enable_color: bool,
}
impl Default for OutputFormat {
fn default() -> Self {
Self { enable_color: true }
}
}
/// Marker trait for a type that implements `TransactionPool` and `MallocSizeOf` on `not(target_os =
/// "unknown")`.
#[cfg(target_os = "unknown")]
pub trait TransactionPoolAndMaybeMallogSizeOf: TransactionPool {}
/// Marker trait for a type that implements `TransactionPool` and `MallocSizeOf` on `not(target_os =
/// "unknown")`.
#[cfg(not(target_os = "unknown"))]
pub trait TransactionPoolAndMaybeMallogSizeOf: TransactionPool + MallocSizeOf {}
#[cfg(target_os = "unknown")]
impl TransactionPoolAndMaybeMallogSizeOf for T {}
#[cfg(not(target_os = "unknown"))]
impl TransactionPoolAndMaybeMallogSizeOf for T {}
/// Builds the informant and returns a `Future` that drives the informant.
pub async fn build(
client: Arc,
network: Arc::Hash>>,
pool: Arc,
format: OutputFormat,
) where
C: UsageProvider + HeaderMetadata + BlockchainEvents,
>::Error: Display,
{
let mut display = display::InformantDisplay::new(format.clone());
let client_1 = client.clone();
let display_notifications = interval(Duration::from_millis(5000))
.filter_map(|_| async {
let status = network.status().await;
status.ok()
})
.for_each(move |net_status| {
let info = client_1.usage_info();
if let Some(ref usage) = info.usage {
trace!(target: "usage", "Usage statistics: {}", usage);
} else {
trace!(
target: "usage",
"Usage statistics not displayed as backend does not provide it",
)
}
#[cfg(not(target_os = "unknown"))]
trace!(
target: "usage",
"Subsystems memory [txpool: {} kB]",
parity_util_mem::malloc_size(&*pool) / 1024,
);
display.display(&info, net_status);
future::ready(())
});
futures::select! {
() = display_notifications.fuse() => (),
() = display_block_import(client).fuse() => (),
};
}
fn display_block_import(client: Arc) -> impl Future