From 15efe33aae7421e383b275bbd21c453f551535ee Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:11:27 -0500 Subject: [PATCH] feat: make NodeState generic over DB with DatabaseMetadata --- bin/reth/src/node/events.rs | 36 +++--- .../db/src/abstraction/database_metrics.rs | 51 ++++++++- .../storage/db/src/implementation/mdbx/mod.rs | 106 +++++++++++++----- crates/storage/db/src/lib.rs | 15 ++- 4 files changed, 157 insertions(+), 51 deletions(-) diff --git a/bin/reth/src/node/events.rs b/bin/reth/src/node/events.rs index 0fb17f43b33c3..27fcd51abac47 100644 --- a/bin/reth/src/node/events.rs +++ b/bin/reth/src/node/events.rs @@ -3,7 +3,7 @@ use crate::node::cl_events::ConsensusLayerHealthEvent; use futures::Stream; use reth_beacon_consensus::BeaconConsensusEngineEvent; -use reth_db::DatabaseEnv; +use reth_db::{database::Database, database_metrics::DatabaseMetadata}; use reth_interfaces::consensus::ForkchoiceState; use reth_network::{NetworkEvent, NetworkHandle}; use reth_network_api::PeersInfo; @@ -28,11 +28,11 @@ use tracing::{info, warn}; const INFO_MESSAGE_INTERVAL: Duration = Duration::from_secs(25); /// The current high-level state of the node. -struct NodeState { +struct NodeState { /// Database environment. /// Used for freelist calculation reported in the "Status" log message. /// See [EventHandler::poll]. - db: Arc, + db: Arc, /// Connection to the network. network: Option, /// The stage currently being executed. @@ -41,12 +41,8 @@ struct NodeState { latest_block: Option, } -impl NodeState { - fn new( - db: Arc, - network: Option, - latest_block: Option, - ) -> Self { +impl NodeState { + fn new(db: Arc, network: Option, latest_block: Option) -> Self { Self { db, network, current_stage: None, latest_block } } @@ -200,6 +196,12 @@ impl NodeState { } } +impl> NodeState { + fn freelist(&self) -> Option { + self.db.metadata().get("freelist").copied() + } +} + /// Helper type for formatting of optional fields: /// - If [Some(x)], then `x` is written /// - If [None], then `None` is written @@ -270,13 +272,14 @@ impl From for NodeEvent { /// Displays relevant information to the user from components of the node, and periodically /// displays the high-level status of the node. -pub async fn handle_events( +pub async fn handle_events( network: Option, latest_block_number: Option, events: E, - db: Arc, + db: Arc, ) where E: Stream + Unpin, + DB: DatabaseMetadata + 'static, { let state = NodeState::new(db, network, latest_block_number); @@ -290,17 +293,18 @@ pub async fn handle_events( /// Handles events emitted by the node and logs them accordingly. #[pin_project::pin_project] -struct EventHandler { - state: NodeState, +struct EventHandler { + state: NodeState, #[pin] events: E, #[pin] info_interval: Interval, } -impl Future for EventHandler +impl Future for EventHandler where E: Stream + Unpin, + DB: DatabaseMetadata + 'static, { type Output = (); @@ -308,7 +312,7 @@ where let mut this = self.project(); while this.info_interval.poll_tick(cx).is_ready() { - let freelist = OptionalField(this.state.db.freelist().ok()); + let freelist = OptionalField(this.state.freelist()); if let Some(CurrentStage { stage_id, eta, checkpoint, target }) = &this.state.current_stage @@ -428,7 +432,7 @@ impl Display for Eta { f, "{}", humantime::format_duration(Duration::from_secs(remaining.as_secs())) - ) + ); } } diff --git a/crates/storage/db/src/abstraction/database_metrics.rs b/crates/storage/db/src/abstraction/database_metrics.rs index 29265aac59549..b8198ebdb4cdd 100644 --- a/crates/storage/db/src/abstraction/database_metrics.rs +++ b/crates/storage/db/src/abstraction/database_metrics.rs @@ -1,11 +1,40 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; + +use metrics::{counter, gauge, histogram, Label}; use crate::database::Database; /// Extends [Database], adding a function that can be used as a hook for metric reporting. pub trait DatabaseMetrics: Database { /// Reports metrics for the database. - fn report_metrics(&self); + fn report_metrics(&self) { + for (name, value, labels) in self.gauge_metrics() { + gauge!(name, value, labels); + } + + for (name, value, labels) in self.counter_metrics() { + counter!(name, value, labels); + } + + for (name, value, labels) in self.histogram_metrics() { + histogram!(name, value, labels); + } + } + + /// Returns a list of [Gauge](metrics::Gauge) metrics for the database. + fn gauge_metrics(&self) -> Vec<(&'static str, f64, Vec