diff --git a/Cargo.lock b/Cargo.lock index 7a6098668..6bd3ff0a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -885,6 +885,7 @@ dependencies = [ "serde_derive 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -925,7 +926,7 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2538,7 +2539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.8" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2950,7 +2951,7 @@ dependencies = [ "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" "checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 18de04994..3bcaee114 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -1204,7 +1204,7 @@ impl Chain { .map_err(|e| ErrorKind::StoreErr(e, "chain head header".to_owned()).into()) } - /// Gets a block header by hash + /// Gets a block by hash pub fn get_block(&self, h: &Hash) -> Result { self.store .get_block(h) diff --git a/servers/Cargo.toml b/servers/Cargo.toml index 02b6fb6f8..7269e000a 100644 --- a/servers/Cargo.toml +++ b/servers/Cargo.toml @@ -24,6 +24,7 @@ serde_derive = "1" serde_json = "1" chrono = "0.4.4" tokio = "0.1.11" +walkdir = "2.2.9" grin_api = { path = "../api", version = "2.1.0-dev.1" } grin_chain = { path = "../chain", version = "2.1.0-dev.1" } diff --git a/servers/src/common/stats.rs b/servers/src/common/stats.rs index 047a8483e..946d03165 100644 --- a/servers/src/common/stats.rs +++ b/servers/src/common/stats.rs @@ -25,9 +25,9 @@ use crate::core::ser::ProtocolVersion; use chrono::prelude::*; -use crate::chain; use crate::chain::SyncStatus; use crate::p2p; +use grin_core::pow::Difficulty; /// Server state info collection struct, to be passed around into internals /// and populated when required @@ -51,9 +51,9 @@ pub struct ServerStats { /// Number of peers pub peer_count: u32, /// Chain head - pub head: chain::Tip, + pub chain_stats: ChainStats, /// sync header head - pub header_head: chain::Tip, + pub header_stats: ChainStats, /// Whether we're currently syncing pub sync_status: SyncStatus, /// Handle to current stratum server stats @@ -62,8 +62,32 @@ pub struct ServerStats { pub peer_stats: Vec, /// Difficulty calculation statistics pub diff_stats: DiffStats, + /// Transaction pool statistics + pub tx_stats: TxStats, + /// Disk usage in GB + pub disk_usage_gb: String, } +/// Chain Statistics +#[derive(Clone, Serialize, Debug)] +pub struct ChainStats { + /// Height of the tip (max height of the fork) + pub height: u64, + /// Last block pushed to the fork + pub last_block_h: Hash, + /// Total difficulty accumulated on that fork + pub total_difficulty: Difficulty, + /// Timestamp of highest block or header + pub latest_timestamp: DateTime, +} +/// Transaction Statistics +#[derive(Clone, Serialize, Debug)] +pub struct TxStats { + /// Number of transactions in the transaction pool + pub tx_pool_size: usize, + /// Number of transactions in the stem pool + pub stem_pool_size: usize, +} /// Struct to return relevant information about stratum workers #[derive(Clone, Serialize, Debug)] pub struct WorkerStats { diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index 1b1c5a927..83315baa5 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -27,6 +27,7 @@ use std::{ }; use fs2::FileExt; +use walkdir::WalkDir; use crate::api; use crate::api::TLSConfig; @@ -35,7 +36,9 @@ use crate::common::adapters::{ ChainToPoolAndNetAdapter, NetToChainAdapter, PoolToChainAdapter, PoolToNetAdapter, }; use crate::common::hooks::{init_chain_hooks, init_net_hooks}; -use crate::common::stats::{DiffBlock, DiffStats, PeerStats, ServerStateInfo, ServerStats}; +use crate::common::stats::{ + ChainStats, DiffBlock, DiffStats, PeerStats, ServerStateInfo, ServerStats, TxStats, +}; use crate::common::types::{Error, ServerConfig, StratumServerConfig}; use crate::core::core::hash::{Hashed, ZERO_HASH}; use crate::core::core::verifier_cache::{LruVerifierCache, VerifierCache}; @@ -489,14 +492,50 @@ impl Server { .into_iter() .map(|p| PeerStats::from_peer(&p)) .collect(); + + let tx_stats = TxStats { + tx_pool_size: self.tx_pool.read().txpool.entries.len(), + stem_pool_size: self.tx_pool.read().stempool.entries.len(), + }; + + let head = self.chain.head_header().unwrap(); + let head_stats = ChainStats { + latest_timestamp: head.timestamp, + height: head.height, + last_block_h: head.prev_hash, + total_difficulty: head.total_difficulty(), + }; + + let header_tip = self.chain.header_head().unwrap(); + let header = self.chain.get_block_header(&header_tip.hash()).unwrap(); + let header_stats = ChainStats { + latest_timestamp: header.timestamp, + height: header.height, + last_block_h: header.prev_hash, + total_difficulty: header.total_difficulty(), + }; + + let disk_usage_bytes = WalkDir::new(&self.config.db_root) + .min_depth(1) + .max_depth(3) + .into_iter() + .filter_map(|entry| entry.ok()) + .filter_map(|entry| entry.metadata().ok()) + .filter(|metadata| metadata.is_file()) + .fold(0, |acc, m| acc + m.len()); + + let disk_usage_gb = format!("{:.*}", 3, (disk_usage_bytes as f64 / 1_000_000_000 as f64)); + Ok(ServerStats { peer_count: self.peer_count(), - head: self.head()?, - header_head: self.header_head()?, + chain_stats: head_stats, + header_stats: header_stats, sync_status: self.sync_state.status(), + disk_usage_gb: disk_usage_gb, stratum_stats: stratum_stats, peer_stats: peer_stats, diff_stats: diff_stats, + tx_stats: tx_stats, }) } diff --git a/src/bin/tui/peers.rs b/src/bin/tui/peers.rs index e707b47dc..209f329fb 100644 --- a/src/bin/tui/peers.rs +++ b/src/bin/tui/peers.rs @@ -166,7 +166,10 @@ impl TUIStatusListener for TUIPeerView { let lp_str = match lp { Some(l) => format!( "{} D @ {} H vs Us: {} D @ {} H", - l.total_difficulty, l.height, stats.head.total_difficulty, stats.head.height + l.total_difficulty, + l.height, + stats.chain_stats.total_difficulty, + stats.chain_stats.height ) .to_string(), None => "".to_string(), diff --git a/src/bin/tui/status.rs b/src/bin/tui/status.rs index 7069ab8b9..d26aac75f 100644 --- a/src/bin/tui/status.rs +++ b/src/bin/tui/status.rs @@ -46,9 +46,14 @@ impl TUIStatusListener for TUIStatusView { .child(TextView::new("Connected Peers: ")) .child(TextView::new("0").with_id("connected_peers")), ) + .child( + LinearLayout::new(Orientation::Horizontal) + .child(TextView::new("Disk Usage (GB): ")) + .child(TextView::new("0").with_id("disk_usage")), + ) .child( LinearLayout::new(Orientation::Horizontal).child(TextView::new( - "------------------------------------------------", + "--------------------------------------------------------", )), ) .child( @@ -66,9 +71,14 @@ impl TUIStatusListener for TUIStatusView { .child(TextView::new("Header Cumulative Difficulty: ")) .child(TextView::new(" ").with_id("basic_header_total_difficulty")), ) + .child( + LinearLayout::new(Orientation::Horizontal) + .child(TextView::new("Header Tip Timestamp: ")) + .child(TextView::new(" ").with_id("basic_header_timestamp")), + ) .child( LinearLayout::new(Orientation::Horizontal).child(TextView::new( - "------------------------------------------------", + "--------------------------------------------------------", )), ) .child( @@ -86,9 +96,29 @@ impl TUIStatusListener for TUIStatusView { .child(TextView::new("Chain Cumulative Difficulty: ")) .child(TextView::new(" ").with_id("basic_total_difficulty")), ) + .child( + LinearLayout::new(Orientation::Horizontal) + .child(TextView::new("Chain Tip Timestamp: ")) + .child(TextView::new(" ").with_id("chain_timestamp")), + ) .child( LinearLayout::new(Orientation::Horizontal).child(TextView::new( - "------------------------------------------------", + "--------------------------------------------------------", + )), + ) + .child( + LinearLayout::new(Orientation::Horizontal) + .child(TextView::new("Transaction Pool Size: ")) + .child(TextView::new(" ").with_id("tx_pool_size")), + ) + .child( + LinearLayout::new(Orientation::Horizontal) + .child(TextView::new("Stem Pool Size: ")) + .child(TextView::new(" ").with_id("stem_pool_size")), + ) + .child( + LinearLayout::new(Orientation::Horizontal).child(TextView::new( + "--------------------------------------------------------", )), ) .child( @@ -244,23 +274,38 @@ impl TUIStatusListener for TUIStatusView { c.call_on_id("connected_peers", |t: &mut TextView| { t.set_content(stats.peer_count.to_string()); }); + c.call_on_id("disk_usage", |t: &mut TextView| { + t.set_content(stats.disk_usage_gb.clone()); + }); c.call_on_id("tip_hash", |t: &mut TextView| { - t.set_content(stats.head.last_block_h.to_string() + "..."); + t.set_content(stats.chain_stats.last_block_h.to_string() + "..."); }); c.call_on_id("chain_height", |t: &mut TextView| { - t.set_content(stats.head.height.to_string()); + t.set_content(stats.chain_stats.height.to_string()); }); c.call_on_id("basic_total_difficulty", |t: &mut TextView| { - t.set_content(stats.head.total_difficulty.to_string()); + t.set_content(stats.chain_stats.total_difficulty.to_string()); + }); + c.call_on_id("chain_timestamp", |t: &mut TextView| { + t.set_content(stats.chain_stats.latest_timestamp.to_string()); }); c.call_on_id("basic_header_tip_hash", |t: &mut TextView| { - t.set_content(stats.header_head.last_block_h.to_string() + "..."); + t.set_content(stats.header_stats.last_block_h.to_string() + "..."); }); c.call_on_id("basic_header_chain_height", |t: &mut TextView| { - t.set_content(stats.header_head.height.to_string()); + t.set_content(stats.header_stats.height.to_string()); }); c.call_on_id("basic_header_total_difficulty", |t: &mut TextView| { - t.set_content(stats.header_head.total_difficulty.to_string()); + t.set_content(stats.header_stats.total_difficulty.to_string()); + }); + c.call_on_id("basic_header_timestamp", |t: &mut TextView| { + t.set_content(stats.header_stats.latest_timestamp.to_string()); + }); + c.call_on_id("tx_pool_size", |t: &mut TextView| { + t.set_content(stats.tx_stats.tx_pool_size.to_string()); + }); + c.call_on_id("stem_pool_size", |t: &mut TextView| { + t.set_content(stats.tx_stats.stem_pool_size.to_string()); }); /*c.call_on_id("basic_mining_config_status", |t: &mut TextView| { t.set_content(basic_mining_config_status);