nautilus_model/defi/
reporting.rs1use std::{fmt::Display, time::Instant};
19
20use thousands::Separable;
21
22#[derive(Debug, Clone)]
23pub enum BlockchainSyncReportItems {
24 Blocks,
25 PoolCreatedEvents,
26 PoolEvents,
27 PoolProfiling,
28}
29
30impl Display for BlockchainSyncReportItems {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(f, "{self:?}")
33 }
34}
35
36#[derive(Debug, Clone)]
38pub struct BlockchainSyncReporter {
39 item: BlockchainSyncReportItems,
40 start_time: Instant,
41 last_progress_time: Instant,
42 from_block: u64,
43 blocks_processed: u64,
44 blocks_since_last_report: u64,
45 total_blocks: u64,
46 progress_update_interval: u64,
47 next_progress_threshold: u64,
48}
49
50impl BlockchainSyncReporter {
51 #[must_use]
53 pub fn new(
54 item: BlockchainSyncReportItems,
55 from_block: u64,
56 total_blocks: u64,
57 update_interval: u64,
58 ) -> Self {
59 let now = Instant::now();
60 Self {
61 item,
62 start_time: now,
63 last_progress_time: now,
64 from_block,
65 blocks_processed: 0,
66 blocks_since_last_report: 0,
67 total_blocks,
68 progress_update_interval: update_interval,
69 next_progress_threshold: from_block + update_interval,
70 }
71 }
72
73 pub fn update(&mut self, batch_size: usize) {
75 self.blocks_processed += batch_size as u64;
76 self.blocks_since_last_report += batch_size as u64;
77 }
78
79 #[must_use]
81 pub fn should_log_progress(&self, block_number: u64, current_block: u64) -> bool {
82 let block_threshold_reached =
83 block_number >= self.next_progress_threshold || block_number >= current_block;
84 let time_threshold_reached = self.last_progress_time.elapsed().as_secs_f64() >= 1.0;
86
87 block_threshold_reached && time_threshold_reached
88 }
89
90 pub fn log_progress(&mut self, block_number: u64) {
92 let elapsed = self.start_time.elapsed();
93 let interval_elapsed = self.last_progress_time.elapsed();
94
95 let avg_rate = if elapsed.as_secs_f64() > 0.0 {
97 self.blocks_processed as f64 / elapsed.as_secs_f64()
98 } else {
99 0.0
100 };
101
102 let current_rate = if interval_elapsed.as_secs_f64() > 0.001 {
103 self.blocks_since_last_report as f64 / interval_elapsed.as_secs_f64()
105 } else {
106 0.0
107 };
108
109 let blocks_completed = block_number.saturating_sub(self.from_block);
111 let progress_pct = (blocks_completed as f64 / self.total_blocks as f64 * 100.0).min(100.0);
112
113 tracing::info!(
114 "Syncing {} progress: {:.1}% | Block: {} | Rate: {} blocks/s | Avg: {} blocks/s",
115 self.item,
116 progress_pct,
117 block_number.separate_with_commas(),
118 (current_rate.round() as u64).separate_with_commas(),
119 (avg_rate.round() as u64).separate_with_commas(),
120 );
121
122 self.next_progress_threshold = block_number + self.progress_update_interval;
123 self.last_progress_time = Instant::now();
124 self.blocks_since_last_report = 0;
125 }
126
127 pub fn log_final_stats(&self) {
129 let total_elapsed = self.start_time.elapsed();
130 let avg_rate = self.blocks_processed as f64 / total_elapsed.as_secs_f64();
131 tracing::info!(
132 "Finished syncing {} | Total: {} blocks in {:.1}s | Avg rate: {} blocks/s",
133 self.item,
134 self.blocks_processed.separate_with_commas(),
135 total_elapsed.as_secs_f64(),
136 (avg_rate.round() as u64).separate_with_commas(),
137 );
138 }
139}