1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
// Copyright 2020 The Grin Developers // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Server stat collection types, to be used by tests, logging or GUI/TUI //! to collect information about server status use crate::util::RwLock; use std::sync::Arc; use std::time::SystemTime; use crate::core::consensus::graph_weight; use crate::core::core::hash::Hash; use crate::core::ser::ProtocolVersion; use chrono::prelude::*; 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 #[derive(Clone)] pub struct ServerStateInfo { /// Stratum stats pub stratum_stats: Arc<RwLock<StratumStats>>, } impl Default for ServerStateInfo { fn default() -> ServerStateInfo { ServerStateInfo { stratum_stats: Arc::new(RwLock::new(StratumStats::default())), } } } /// Simpler thread-unaware version of above to be populated and returned to /// consumers might be interested in, such as test results or UI #[derive(Clone)] pub struct ServerStats { /// Number of peers pub peer_count: u32, /// Chain head pub chain_stats: ChainStats, /// Header head (may differ from chain head) pub header_stats: ChainStats, /// Whether we're currently syncing pub sync_status: SyncStatus, /// Handle to current stratum server stats pub stratum_stats: StratumStats, /// Peer stats pub peer_stats: Vec<PeerStats>, /// Difficulty calculation statistics pub diff_stats: DiffStats, /// Transaction pool statistics pub tx_stats: Option<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<Utc>, } /// Transaction Statistics #[derive(Clone, Serialize, Debug)] pub struct TxStats { /// Number of transactions in the transaction pool pub tx_pool_size: usize, /// Number of transaction kernels in the transaction pool pub tx_pool_kernels: usize, /// Number of transactions in the stem pool pub stem_pool_size: usize, /// Number of transaction kernels in the stem pool pub stem_pool_kernels: usize, } /// Struct to return relevant information about stratum workers #[derive(Clone, Serialize, Debug)] pub struct WorkerStats { /// Unique ID for this worker pub id: String, /// whether stratum worker is currently connected pub is_connected: bool, /// Timestamp of most recent communication with this worker pub last_seen: SystemTime, /// which block height it starts mining pub initial_block_height: u64, /// pow difficulty this worker is using pub pow_difficulty: u64, /// number of valid shares submitted pub num_accepted: u64, /// number of invalid shares submitted pub num_rejected: u64, /// number of shares submitted too late pub num_stale: u64, /// number of valid blocks found pub num_blocks_found: u64, } /// Struct to return relevant information about the stratum server #[derive(Clone, Serialize, Debug)] pub struct StratumStats { /// whether stratum server is enabled pub is_enabled: bool, /// whether stratum server is running pub is_running: bool, /// Number of connected workers pub num_workers: usize, /// what block height we're mining at pub block_height: u64, /// current network difficulty we're working on pub network_difficulty: u64, /// cuckoo size used for mining pub edge_bits: u16, /// Individual worker status pub worker_stats: Vec<WorkerStats>, } /// Stats on the last WINDOW blocks and the difficulty calculation #[derive(Clone)] pub struct DiffStats { /// latest height pub height: u64, /// Last WINDOW block data pub last_blocks: Vec<DiffBlock>, /// Average block time for last WINDOW blocks pub average_block_time: u64, /// Average WINDOW difficulty pub average_difficulty: u64, /// WINDOW size pub window_size: u64, } /// Last n blocks for difficulty calculation purposes #[derive(Clone, Debug)] pub struct DiffBlock { /// Block height (can be negative for a new chain) pub block_height: i64, /// Block hash (may be synthetic for a new chain) pub block_hash: Hash, /// Block network difficulty pub difficulty: u64, /// Time block was found (epoch seconds) pub time: u64, /// Duration since previous block (epoch seconds) pub duration: u64, /// secondary scaling pub secondary_scaling: u32, /// is secondary pub is_secondary: bool, } /// Struct to return relevant information about peers #[derive(Clone, Debug)] pub struct PeerStats { /// Current state of peer pub state: String, /// Address pub addr: String, /// version running pub version: ProtocolVersion, /// Peer user agent string. pub user_agent: String, /// difficulty reported by peer pub total_difficulty: u64, /// height reported by peer on ping pub height: u64, /// direction pub direction: String, /// Last time we saw a ping/pong from this peer. pub last_seen: DateTime<Utc>, /// Number of bytes we've sent to the peer. pub sent_bytes_per_sec: u64, /// Number of bytes we've received from the peer. pub received_bytes_per_sec: u64, } impl PartialEq for PeerStats { fn eq(&self, other: &PeerStats) -> bool { *self.addr == other.addr } } impl PartialEq for WorkerStats { fn eq(&self, other: &WorkerStats) -> bool { *self.id == other.id } } impl PartialEq for DiffBlock { fn eq(&self, other: &DiffBlock) -> bool { self.block_height == other.block_height } } impl StratumStats { /// Calculate network hashrate pub fn network_hashrate(&self, height: u64) -> f64 { 42.0 * (self.network_difficulty as f64 / graph_weight(height, self.edge_bits as u8) as f64) / 60.0 } } impl PeerStats { /// Convert from a peer directly pub fn from_peer(peer: &p2p::Peer) -> PeerStats { // State let state = if peer.is_banned() { "Banned" } else if peer.is_connected() { "Connected" } else { "Disconnected" }; let addr = peer.info.addr.to_string(); let direction = match peer.info.direction { p2p::types::Direction::Inbound => "Inbound", p2p::types::Direction::Outbound => "Outbound", }; PeerStats { state: state.to_string(), addr: addr, version: peer.info.version, user_agent: peer.info.user_agent.clone(), total_difficulty: peer.info.total_difficulty().to_num(), height: peer.info.height(), direction: direction.to_string(), last_seen: peer.info.last_seen(), sent_bytes_per_sec: peer.last_min_sent_bytes().unwrap_or(0) / 60, received_bytes_per_sec: peer.last_min_received_bytes().unwrap_or(0) / 60, } } } impl Default for WorkerStats { fn default() -> WorkerStats { WorkerStats { id: String::from("unknown"), is_connected: false, last_seen: SystemTime::now(), initial_block_height: 0, pow_difficulty: 0, num_accepted: 0, num_rejected: 0, num_stale: 0, num_blocks_found: 0, } } } impl Default for StratumStats { fn default() -> StratumStats { StratumStats { is_enabled: false, is_running: false, num_workers: 0, block_height: 0, network_difficulty: 1000, edge_bits: 29, worker_stats: Vec::new(), } } }