From 44da381591fb9ec3d7f42efc11f95328cd66214a Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:36:20 -0400 Subject: [PATCH] feat: add initial blockchain tree metrics (#3289) --- Cargo.lock | 1 + crates/blockchain-tree/Cargo.toml | 1 + crates/blockchain-tree/src/block_buffer.rs | 8 +++++ crates/blockchain-tree/src/blockchain_tree.rs | 10 +++++++ crates/blockchain-tree/src/lib.rs | 3 ++ crates/blockchain-tree/src/metrics.rs | 22 ++++++++++++++ crates/blockchain-tree/src/shareable.rs | 29 +++++++++++++++---- 7 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 crates/blockchain-tree/src/metrics.rs diff --git a/Cargo.lock b/Cargo.lock index 8493f819d..9929ef06a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5071,6 +5071,7 @@ dependencies = [ "parking_lot 0.12.1", "reth-db", "reth-interfaces", + "reth-metrics", "reth-primitives", "reth-provider", "tokio", diff --git a/crates/blockchain-tree/Cargo.toml b/crates/blockchain-tree/Cargo.toml index f955fde9e..0a4bf9559 100644 --- a/crates/blockchain-tree/Cargo.toml +++ b/crates/blockchain-tree/Cargo.toml @@ -18,6 +18,7 @@ normal = [ reth-primitives = { workspace = true } reth-interfaces = { workspace = true } reth-db = { path = "../storage/db" } +reth-metrics = { workspace = true, features = ["common"] } reth-provider = { workspace = true } # common diff --git a/crates/blockchain-tree/src/block_buffer.rs b/crates/blockchain-tree/src/block_buffer.rs index 5905a54a9..a34427e0a 100644 --- a/crates/blockchain-tree/src/block_buffer.rs +++ b/crates/blockchain-tree/src/block_buffer.rs @@ -4,6 +4,8 @@ use std::{ collections::{btree_map::Entry, hash_map, BTreeMap, HashMap, HashSet}, num::NonZeroUsize, }; + +use crate::metrics::BlockBufferMetrics; /// Type that contains blocks by number and hash. pub type BufferedBlocks = BTreeMap>; @@ -35,6 +37,8 @@ pub struct BlockBuffer { /// /// Used as counter of amount of blocks inside buffer. pub(crate) lru: LruCache, + /// Various metrics for the block buffer. + pub(crate) metrics: BlockBufferMetrics, } impl BlockBuffer { @@ -45,6 +49,7 @@ impl BlockBuffer { parent_to_child: Default::default(), hash_to_num: Default::default(), lru: LruCache::new(NonZeroUsize::new(limit).unwrap()), + metrics: Default::default(), } } @@ -65,6 +70,7 @@ impl BlockBuffer { self.remove_from_parent(evicted_block.parent_hash, &evicted_num_hash); } } + self.metrics.blocks.set(self.len() as f64); } /// Removes the given block from the buffer and also all the children of the block. @@ -81,6 +87,7 @@ impl BlockBuffer { } taken.extend(self.remove_children(vec![parent]).into_iter()); + self.metrics.blocks.set(self.len() as f64); taken } @@ -105,6 +112,7 @@ impl BlockBuffer { } self.remove_children(remove_parent_children); + self.metrics.blocks.set(self.len() as f64); } /// Return reference to buffered blocks diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 7b013bf9b..efc7e82ce 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -2,6 +2,7 @@ use crate::{ canonical_chain::CanonicalChain, chain::{BlockChainId, BlockKind}, + metrics::TreeMetrics, AppendableChain, BlockBuffer, BlockIndices, BlockchainTreeConfig, PostStateData, TreeExternals, }; use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx}; @@ -87,6 +88,8 @@ pub struct BlockchainTree { config: BlockchainTreeConfig, /// Broadcast channel for canon state changes notifications. canon_state_notification_sender: CanonStateNotificationSender, + /// Metrics for the blockchain tree. + metrics: TreeMetrics, } /// A container that wraps chains and block indices to allow searching for block hashes across all @@ -137,6 +140,7 @@ impl BlockchainTree ), config, canon_state_notification_sender, + metrics: Default::default(), }) } @@ -1058,6 +1062,12 @@ impl BlockchainTree Ok(Some(Chain::new(blocks_and_execution))) } } + + /// Update blockchain tree metrics + pub(crate) fn update_tree_metrics(&self) { + self.metrics.sidechains.set(self.chains.len() as f64); + self.metrics.canonical_chain_height.set(self.canonical_chain().tip().number as f64); + } } #[cfg(test)] diff --git a/crates/blockchain-tree/src/lib.rs b/crates/blockchain-tree/src/lib.rs index c4f06910f..87bdcaeb2 100644 --- a/crates/blockchain-tree/src/lib.rs +++ b/crates/blockchain-tree/src/lib.rs @@ -44,4 +44,7 @@ pub use post_state_data::{PostStateData, PostStateDataRef}; pub mod block_buffer; mod canonical_chain; +/// Common blockchain tree metrics. +pub mod metrics; + pub use block_buffer::BlockBuffer; diff --git a/crates/blockchain-tree/src/metrics.rs b/crates/blockchain-tree/src/metrics.rs new file mode 100644 index 000000000..38610c5a6 --- /dev/null +++ b/crates/blockchain-tree/src/metrics.rs @@ -0,0 +1,22 @@ +use reth_metrics::{ + metrics::{self, Gauge}, + Metrics, +}; + +/// Metrics for the entire blockchain tree +#[derive(Metrics)] +#[metrics(scope = "blockchain_tree")] +pub struct TreeMetrics { + /// Total number of sidechains (not including the canonical chain) + pub sidechains: Gauge, + /// The highest block number in the canonical chain + pub canonical_chain_height: Gauge, +} + +/// Metrics for the blockchain tree block buffer +#[derive(Metrics)] +#[metrics(scope = "blockchain_tree.block_buffer")] +pub struct BlockBufferMetrics { + /// Total blocks in the block buffer + pub blocks: Gauge, +} diff --git a/crates/blockchain-tree/src/shareable.rs b/crates/blockchain-tree/src/shareable.rs index 75ced6dc9..bd3eb3247 100644 --- a/crates/blockchain-tree/src/shareable.rs +++ b/crates/blockchain-tree/src/shareable.rs @@ -41,7 +41,10 @@ impl BlockchainTreeEngine for ShareableBlockchainTree { fn buffer_block(&self, block: SealedBlockWithSenders) -> Result<(), InsertBlockError> { - self.tree.write().buffer_block(block) + let mut tree = self.tree.write(); + let res = tree.buffer_block(block); + tree.update_tree_metrics(); + res } fn insert_block( @@ -49,27 +52,41 @@ impl BlockchainTreeEngine block: SealedBlockWithSenders, ) -> Result { trace!(target: "blockchain_tree", hash=?block.hash, number=block.number, parent_hash=?block.parent_hash, "Inserting block"); - self.tree.write().insert_block(block) + let mut tree = self.tree.write(); + let res = tree.insert_block(block); + tree.update_tree_metrics(); + res } fn finalize_block(&self, finalized_block: BlockNumber) { trace!(target: "blockchain_tree", ?finalized_block, "Finalizing block"); - self.tree.write().finalize_block(finalized_block) + let mut tree = self.tree.write(); + tree.finalize_block(finalized_block); + tree.update_tree_metrics(); } fn restore_canonical_hashes(&self, last_finalized_block: BlockNumber) -> Result<(), Error> { trace!(target: "blockchain_tree", ?last_finalized_block, "Restoring canonical hashes for last finalized block"); - self.tree.write().restore_canonical_hashes(last_finalized_block) + let mut tree = self.tree.write(); + let res = tree.restore_canonical_hashes(last_finalized_block); + tree.update_tree_metrics(); + res } fn make_canonical(&self, block_hash: &BlockHash) -> Result { trace!(target: "blockchain_tree", ?block_hash, "Making block canonical"); - self.tree.write().make_canonical(block_hash) + let mut tree = self.tree.write(); + let res = tree.make_canonical(block_hash); + tree.update_tree_metrics(); + res } fn unwind(&self, unwind_to: BlockNumber) -> Result<(), Error> { trace!(target: "blockchain_tree", ?unwind_to, "Unwinding to block number"); - self.tree.write().unwind(unwind_to) + let mut tree = self.tree.write(); + let res = tree.unwind(unwind_to); + tree.update_tree_metrics(); + res } }