mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-30 01:28:21 -05:00
feat(pruner): metrics (#4023)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -5650,6 +5650,7 @@ dependencies = [
|
||||
"rayon",
|
||||
"reth-db",
|
||||
"reth-interfaces",
|
||||
"reth-metrics",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-stages",
|
||||
|
||||
@@ -386,7 +386,6 @@ impl<Ext: RethCliExt> Command<Ext> {
|
||||
db.clone(),
|
||||
self.chain.clone(),
|
||||
prune_config.block_interval,
|
||||
tree_config.max_reorg_depth(),
|
||||
prune_config.parts,
|
||||
BatchSizes::default(),
|
||||
)
|
||||
|
||||
@@ -469,7 +469,6 @@ where
|
||||
db.clone(),
|
||||
self.base_config.chain_spec.clone(),
|
||||
5,
|
||||
0,
|
||||
PruneModes::default(),
|
||||
BatchSizes::default(),
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ reth-primitives.workspace = true
|
||||
reth-db.workspace = true
|
||||
reth-provider.workspace = true
|
||||
reth-interfaces.workspace = true
|
||||
reth-metrics.workspace = true
|
||||
|
||||
# misc
|
||||
tracing.workspace = true
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod error;
|
||||
mod metrics;
|
||||
mod pruner;
|
||||
|
||||
pub use error::PrunerError;
|
||||
use metrics::Metrics;
|
||||
pub use pruner::{BatchSizes, Pruner, PrunerResult, PrunerWithResult};
|
||||
|
||||
36
crates/prune/src/metrics.rs
Normal file
36
crates/prune/src/metrics.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use reth_metrics::{metrics, metrics::Histogram, Metrics};
|
||||
use reth_primitives::PrunePart;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct Metrics {
|
||||
pub(crate) pruner: PrunerMetrics,
|
||||
prune_parts: HashMap<PrunePart, PrunerPartMetrics>,
|
||||
}
|
||||
|
||||
impl Metrics {
|
||||
/// Returns existing or initializes a new instance of [PrunerPartMetrics] for the provided
|
||||
/// [PrunePart].
|
||||
pub(crate) fn get_prune_part_metrics(
|
||||
&mut self,
|
||||
prune_part: PrunePart,
|
||||
) -> &mut PrunerPartMetrics {
|
||||
self.prune_parts.entry(prune_part).or_insert_with(|| {
|
||||
PrunerPartMetrics::new_with_labels(&[("part", prune_part.to_string())])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Metrics)]
|
||||
#[metrics(scope = "pruner")]
|
||||
pub(crate) struct PrunerMetrics {
|
||||
/// Pruning duration
|
||||
pub(crate) duration_seconds: Histogram,
|
||||
}
|
||||
|
||||
#[derive(Metrics)]
|
||||
#[metrics(scope = "pruner.parts")]
|
||||
pub(crate) struct PrunerPartMetrics {
|
||||
/// Pruning duration for this part
|
||||
pub(crate) duration_seconds: Histogram,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Support for pruning.
|
||||
|
||||
use crate::PrunerError;
|
||||
use crate::{Metrics, PrunerError};
|
||||
use rayon::prelude::*;
|
||||
use reth_db::{database::Database, tables};
|
||||
use reth_primitives::{
|
||||
@@ -10,7 +10,7 @@ use reth_provider::{
|
||||
BlockReader, DatabaseProviderRW, ProviderFactory, PruneCheckpointReader, PruneCheckpointWriter,
|
||||
TransactionsProvider,
|
||||
};
|
||||
use std::{ops::RangeInclusive, sync::Arc};
|
||||
use std::{ops::RangeInclusive, sync::Arc, time::Instant};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
/// Result of [Pruner::run] execution
|
||||
@@ -33,14 +33,11 @@ impl Default for BatchSizes {
|
||||
|
||||
/// Pruning routine. Main pruning logic happens in [Pruner::run].
|
||||
pub struct Pruner<DB> {
|
||||
metrics: Metrics,
|
||||
provider_factory: ProviderFactory<DB>,
|
||||
/// Minimum pruning interval measured in blocks. All prune parts are checked and, if needed,
|
||||
/// pruned, when the chain advances by the specified number of blocks.
|
||||
min_block_interval: u64,
|
||||
/// Maximum prune depth. Used to determine the pruning target for parts that are needed during
|
||||
/// the reorg, e.g. changesets.
|
||||
#[allow(dead_code)]
|
||||
max_prune_depth: u64,
|
||||
/// Last pruned block number. Used in conjunction with `min_block_interval` to determine
|
||||
/// when the pruning needs to be initiated.
|
||||
last_pruned_block_number: Option<BlockNumber>,
|
||||
@@ -54,14 +51,13 @@ impl<DB: Database> Pruner<DB> {
|
||||
db: DB,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
min_block_interval: u64,
|
||||
max_prune_depth: u64,
|
||||
modes: PruneModes,
|
||||
batch_sizes: BatchSizes,
|
||||
) -> Self {
|
||||
Self {
|
||||
metrics: Metrics::default(),
|
||||
provider_factory: ProviderFactory::new(db, chain_spec),
|
||||
min_block_interval,
|
||||
max_prune_depth,
|
||||
last_pruned_block_number: None,
|
||||
modes,
|
||||
batch_sizes,
|
||||
@@ -70,29 +66,48 @@ impl<DB: Database> Pruner<DB> {
|
||||
|
||||
/// Run the pruner
|
||||
pub fn run(&mut self, tip_block_number: BlockNumber) -> PrunerResult {
|
||||
let start = Instant::now();
|
||||
|
||||
let provider = self.provider_factory.provider_rw()?;
|
||||
|
||||
if let Some((to_block, prune_mode)) =
|
||||
self.modes.prune_target_block_receipts(tip_block_number)?
|
||||
{
|
||||
let part_start = Instant::now();
|
||||
self.prune_receipts(&provider, to_block, prune_mode)?;
|
||||
self.metrics
|
||||
.get_prune_part_metrics(PrunePart::Receipts)
|
||||
.duration_seconds
|
||||
.record(part_start.elapsed())
|
||||
}
|
||||
|
||||
if let Some((to_block, prune_mode)) =
|
||||
self.modes.prune_target_block_transaction_lookup(tip_block_number)?
|
||||
{
|
||||
let part_start = Instant::now();
|
||||
self.prune_transaction_lookup(&provider, to_block, prune_mode)?;
|
||||
self.metrics
|
||||
.get_prune_part_metrics(PrunePart::TransactionLookup)
|
||||
.duration_seconds
|
||||
.record(part_start.elapsed())
|
||||
}
|
||||
|
||||
if let Some((to_block, prune_mode)) =
|
||||
self.modes.prune_target_block_sender_recovery(tip_block_number)?
|
||||
{
|
||||
let part_start = Instant::now();
|
||||
self.prune_transaction_senders(&provider, to_block, prune_mode)?;
|
||||
self.metrics
|
||||
.get_prune_part_metrics(PrunePart::SenderRecovery)
|
||||
.duration_seconds
|
||||
.record(part_start.elapsed())
|
||||
}
|
||||
|
||||
provider.commit()?;
|
||||
|
||||
self.last_pruned_block_number = Some(tip_block_number);
|
||||
|
||||
self.metrics.pruner.duration_seconds.record(start.elapsed());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -323,7 +338,7 @@ mod tests {
|
||||
fn is_pruning_needed() {
|
||||
let db = create_test_rw_db();
|
||||
let pruner =
|
||||
Pruner::new(db, MAINNET.clone(), 5, 0, PruneModes::default(), BatchSizes::default());
|
||||
Pruner::new(db, MAINNET.clone(), 5, PruneModes::default(), BatchSizes::default());
|
||||
|
||||
// No last pruned block number was set before
|
||||
let first_block_number = 1;
|
||||
@@ -370,7 +385,6 @@ mod tests {
|
||||
tx.inner_raw(),
|
||||
MAINNET.clone(),
|
||||
5,
|
||||
0,
|
||||
PruneModes { receipts: Some(prune_mode), ..Default::default() },
|
||||
BatchSizes {
|
||||
// Less than total amount of blocks to prune to test the batching logic
|
||||
@@ -431,7 +445,6 @@ mod tests {
|
||||
tx.inner_raw(),
|
||||
MAINNET.clone(),
|
||||
5,
|
||||
0,
|
||||
PruneModes { transaction_lookup: Some(prune_mode), ..Default::default() },
|
||||
BatchSizes {
|
||||
// Less than total amount of blocks to prune to test the batching logic
|
||||
@@ -498,7 +511,6 @@ mod tests {
|
||||
tx.inner_raw(),
|
||||
MAINNET.clone(),
|
||||
5,
|
||||
0,
|
||||
PruneModes { sender_recovery: Some(prune_mode), ..Default::default() },
|
||||
BatchSizes {
|
||||
// Less than total amount of blocks to prune to test the batching logic
|
||||
|
||||
Reference in New Issue
Block a user