Skip to main content

reth_provider/providers/rocksdb/
metrics.rs

1use std::{collections::HashMap, time::Duration};
2
3use itertools::Itertools;
4use metrics::{Counter, Histogram};
5use reth_db::Tables;
6use reth_metrics::Metrics;
7use strum::{EnumIter, IntoEnumIterator};
8
9pub(super) const ROCKSDB_TABLES: &[&str] = &[
10    Tables::TransactionHashNumbers.name(),
11    Tables::StoragesHistory.name(),
12    Tables::AccountsHistory.name(),
13];
14
15/// Metrics for the `RocksDB` provider.
16#[derive(Debug)]
17pub(crate) struct RocksDBMetrics {
18    operations: HashMap<(&'static str, RocksDBOperation), RocksDBOperationMetrics>,
19}
20
21impl Default for RocksDBMetrics {
22    fn default() -> Self {
23        let mut operations = ROCKSDB_TABLES
24            .iter()
25            .copied()
26            .cartesian_product(RocksDBOperation::iter())
27            .map(|(table, operation)| {
28                (
29                    (table, operation),
30                    RocksDBOperationMetrics::new_with_labels(&[
31                        ("table", table),
32                        ("operation", operation.as_str()),
33                    ]),
34                )
35            })
36            .collect::<HashMap<_, _>>();
37
38        // Add special "Batch" entry for batch write operations
39        operations.insert(
40            ("Batch", RocksDBOperation::BatchWrite),
41            RocksDBOperationMetrics::new_with_labels(&[
42                ("table", "Batch"),
43                ("operation", RocksDBOperation::BatchWrite.as_str()),
44            ]),
45        );
46
47        Self { operations }
48    }
49}
50
51impl RocksDBMetrics {
52    /// Records operation metrics with the given operation label and table name.
53    pub(crate) fn record_operation(
54        &self,
55        operation: RocksDBOperation,
56        table: &'static str,
57        duration: Duration,
58    ) {
59        let metrics =
60            self.operations.get(&(table, operation)).expect("operation metrics should exist");
61
62        metrics.calls_total.increment(1);
63        metrics.duration_seconds.record(duration.as_secs_f64());
64    }
65}
66
67/// `RocksDB` operations that are tracked
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
69pub(crate) enum RocksDBOperation {
70    Get,
71    Put,
72    Delete,
73    BatchWrite,
74}
75
76impl RocksDBOperation {
77    const fn as_str(&self) -> &'static str {
78        match self {
79            Self::Get => "get",
80            Self::Put => "put",
81            Self::Delete => "delete",
82            Self::BatchWrite => "batch-write",
83        }
84    }
85}
86
87/// Metrics for a specific `RocksDB` operation on a table
88#[derive(Metrics, Clone)]
89#[metrics(scope = "rocksdb.provider")]
90pub(crate) struct RocksDBOperationMetrics {
91    /// Total number of calls
92    calls_total: Counter,
93    /// Duration of operations
94    duration_seconds: Histogram,
95}