From 900fe7ea4e77ff7fa102468261b55d80c03a713d Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:55:21 +0200 Subject: [PATCH] feat: make NodeState generic over DB with DatabaseMetadata (#5691) --- bin/reth/src/node/events.rs | 35 ++++--- .../db/src/abstraction/database_metrics.rs | 62 +++++++++++- .../storage/db/src/implementation/mdbx/mod.rs | 97 +++++++++++++------ crates/storage/db/src/lib.rs | 11 ++- 4 files changed, 157 insertions(+), 48 deletions(-) diff --git a/bin/reth/src/node/events.rs b/bin/reth/src/node/events.rs index 0fb17f43b33c..c6d206de6dcd 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; @@ -17,7 +17,6 @@ use std::{ fmt::{Display, Formatter}, future::Future, pin::Pin, - sync::Arc, task::{Context, Poll}, time::{Duration, Instant}, }; @@ -28,11 +27,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: DB, /// Connection to the network. network: Option, /// The stage currently being executed. @@ -41,12 +40,8 @@ struct NodeState { latest_block: Option, } -impl NodeState { - fn new( - db: Arc, - network: Option, - latest_block: Option, - ) -> Self { +impl NodeState { + fn new(db: DB, network: Option, latest_block: Option) -> Self { Self { db, network, current_stage: None, latest_block } } @@ -200,6 +195,12 @@ impl NodeState { } } +impl NodeState { + fn freelist(&self) -> Option { + self.db.metadata().freelist_size() + } +} + /// Helper type for formatting of optional fields: /// - If [Some(x)], then `x` is written /// - If [None], then `None` is written @@ -270,13 +271,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: DB, ) where E: Stream + Unpin, + DB: DatabaseMetadata + Database + 'static, { let state = NodeState::new(db, network, latest_block_number); @@ -290,17 +292,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 + Database + 'static, { type Output = (); @@ -308,7 +311,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 diff --git a/crates/storage/db/src/abstraction/database_metrics.rs b/crates/storage/db/src/abstraction/database_metrics.rs index 717e1b342072..10f0e476ea6a 100644 --- a/crates/storage/db/src/abstraction/database_metrics.rs +++ b/crates/storage/db/src/abstraction/database_metrics.rs @@ -1,10 +1,38 @@ +use metrics::{counter, gauge, histogram, Label}; use std::sync::Arc; /// Represents a type that can report metrics, used mainly with the database. The `report_metrics` /// method can be used as a prometheus hook. pub trait DatabaseMetrics { /// 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