Files
grin-node/servers/src/common/stats.rs
T
2019-10-02 09:40:20 +01:00

260 lines
7.1 KiB
Rust

// Copyright 2019 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,
/// sync header 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: 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 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 {
/// 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 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 mut state = "Disconnected";
if peer.is_connected() {
state = "Connected";
}
if peer.is_banned() {
state = "Banned";
}
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(),
}
}
}