reth_trie/trie_cursor/
metrics.rs1use super::{TrieCursor, TrieStorageCursor};
2use crate::{BranchNodeCompact, Nibbles};
3use alloy_primitives::B256;
4use reth_storage_errors::db::DatabaseError;
5use std::time::{Duration, Instant};
6use tracing::debug_span;
7
8#[cfg(feature = "metrics")]
9use crate::TrieType;
10#[cfg(feature = "metrics")]
11use reth_metrics::metrics::{self, Histogram};
12
13#[cfg(feature = "metrics")]
17#[derive(Clone, Debug)]
18pub struct TrieCursorMetrics {
19 overall_duration: Histogram,
21 next_histogram: Histogram,
23 seek_histogram: Histogram,
25 seek_exact_histogram: Histogram,
27}
28
29#[cfg(feature = "metrics")]
30impl TrieCursorMetrics {
31 pub fn new(trie_type: TrieType) -> Self {
33 let trie_type_str = trie_type.as_str();
34
35 Self {
36 overall_duration: metrics::histogram!(
37 "trie.cursor.overall_duration",
38 "type" => trie_type_str
39 ),
40 next_histogram: metrics::histogram!(
41 "trie.cursor.operations",
42 "type" => trie_type_str,
43 "operation" => "next"
44 ),
45 seek_histogram: metrics::histogram!(
46 "trie.cursor.operations",
47 "type" => trie_type_str,
48 "operation" => "seek"
49 ),
50 seek_exact_histogram: metrics::histogram!(
51 "trie.cursor.operations",
52 "type" => trie_type_str,
53 "operation" => "seek_exact"
54 ),
55 }
56 }
57
58 pub fn record(&mut self, cache: &mut TrieCursorMetricsCache) {
63 self.next_histogram.record(cache.next_count as f64);
64 self.seek_histogram.record(cache.seek_count as f64);
65 self.seek_exact_histogram.record(cache.seek_exact_count as f64);
66 self.overall_duration.record(cache.total_duration.as_secs_f64());
67 cache.reset();
68 }
69}
70
71#[derive(Debug, Copy, Clone)]
73pub struct TrieCursorMetricsCache {
74 pub next_count: usize,
76 pub seek_count: usize,
78 pub seek_exact_count: usize,
80 pub total_duration: Duration,
82}
83
84impl Default for TrieCursorMetricsCache {
85 fn default() -> Self {
86 Self { next_count: 0, seek_count: 0, seek_exact_count: 0, total_duration: Duration::ZERO }
87 }
88}
89
90impl TrieCursorMetricsCache {
91 pub const fn reset(&mut self) {
93 self.next_count = 0;
94 self.seek_count = 0;
95 self.seek_exact_count = 0;
96 self.total_duration = Duration::ZERO;
97 }
98
99 pub fn extend(&mut self, other: &Self) {
103 self.next_count += other.next_count;
104 self.seek_count += other.seek_count;
105 self.seek_exact_count += other.seek_exact_count;
106 self.total_duration += other.total_duration;
107 }
108
109 pub fn record_span(&self, name: &'static str) {
111 let _span = debug_span!(
112 target: "trie::trie_cursor",
113 "Trie cursor metrics",
114 name,
115 next_count = self.next_count,
116 seek_count = self.seek_count,
117 seek_exact_count = self.seek_exact_count,
118 total_duration = self.total_duration.as_secs_f64(),
119 )
120 .entered();
121 }
122}
123
124#[derive(Debug)]
131pub struct InstrumentedTrieCursor<'metrics, C> {
132 cursor: C,
134 metrics: &'metrics mut TrieCursorMetricsCache,
136}
137
138impl<'metrics, C> InstrumentedTrieCursor<'metrics, C> {
139 pub const fn new(cursor: C, metrics: &'metrics mut TrieCursorMetricsCache) -> Self {
141 Self { cursor, metrics }
142 }
143}
144
145impl<'metrics, C: TrieCursor> TrieCursor for InstrumentedTrieCursor<'metrics, C> {
146 fn seek_exact(
147 &mut self,
148 key: Nibbles,
149 ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
150 let start = Instant::now();
151 self.metrics.seek_exact_count += 1;
152 let result = self.cursor.seek_exact(key);
153 self.metrics.total_duration += start.elapsed();
154 result
155 }
156
157 fn seek(
158 &mut self,
159 key: Nibbles,
160 ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
161 let start = Instant::now();
162 self.metrics.seek_count += 1;
163 let result = self.cursor.seek(key);
164 self.metrics.total_duration += start.elapsed();
165 result
166 }
167
168 fn next(&mut self) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
169 let start = Instant::now();
170 self.metrics.next_count += 1;
171 let result = self.cursor.next();
172 self.metrics.total_duration += start.elapsed();
173 result
174 }
175
176 fn current(&mut self) -> Result<Option<Nibbles>, DatabaseError> {
177 self.cursor.current()
178 }
179
180 fn reset(&mut self) {
181 self.cursor.reset()
182 }
183}
184
185impl<'metrics, C: TrieStorageCursor> TrieStorageCursor for InstrumentedTrieCursor<'metrics, C> {
186 fn set_hashed_address(&mut self, hashed_address: B256) {
187 self.cursor.set_hashed_address(hashed_address)
188 }
189}