Skip to content

Commit cbef92e

Browse files
authored
chore(l1): improve logging on the import subcommand. (#4201)
**Motivation** Logging in general, and specifically in the `import` subcommand is quite messy. **Description** - Improves the logging phrasing - Instead of logging for each block, logs a summary every 10 seconds - Logs the total time that it took. - Some misc log additions and downgrades This is how it looks: ``` 2025-08-28T17:27:12.121079Z INFO ethrex_storage::store: Opening storage engine engine=Libmdbx path=/Users/mpaulucci/Library/Application-Support/ethrex 2025-08-28T17:27:12.158692Z INFO ethrex_storage::store: Storing genesis block hash=0xbbe3…971b 2025-08-28T17:27:12.159567Z INFO ethrex::initializers: Initiating blockchain evm=levm 2025-08-28T17:27:12.159726Z INFO ethrex::cli: Importing blocks from file path=./hoodi-1k.rlp 2025-08-28T17:27:22.415021Z INFO ethrex::cli: Import progress processed=151 total=1000 percent=15.1 2025-08-28T17:27:32.602179Z INFO ethrex::cli: Import progress processed=180 total=1000 percent=18.0 ```
1 parent 09c6def commit cbef92e

File tree

8 files changed

+75
-41
lines changed

8 files changed

+75
-41
lines changed

cmd/ethrex/bench/build_block_benchmark.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ pub fn build_block_benchmark(c: &mut Criterion<GasMeasurement>) {
256256
EvmEngine::LEVM,
257257
store_with_genesis.clone(),
258258
BlockchainType::L1, // TODO: Should we support L2?
259+
false,
259260
);
260261
fill_mempool(&block_chain, accounts).await;
261262

cmd/ethrex/cli.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,14 +401,15 @@ pub async fn import_blocks(
401401
evm: EvmEngine,
402402
blockchain_type: BlockchainType,
403403
) -> Result<(), ChainError> {
404+
let start_time = Instant::now();
404405
let data_dir = init_datadir(data_dir);
405406
let store = init_store(&data_dir, genesis).await;
406-
let blockchain = init_blockchain(evm, store.clone(), blockchain_type);
407+
let blockchain = init_blockchain(evm, store.clone(), blockchain_type, false);
407408
let path_metadata = metadata(path).expect("Failed to read path");
408409

409410
// If it's an .rlp file it will be just one chain, but if it's a directory there can be multiple chains.
410411
let chains: Vec<Vec<Block>> = if path_metadata.is_dir() {
411-
info!("Importing blocks from directory: {path}");
412+
info!(path = %path, "Importing blocks from directory");
412413
let mut entries: Vec<_> = read_dir(path)
413414
.expect("Failed to read blocks directory")
414415
.map(|res| res.expect("Failed to open file in directory").path())
@@ -421,26 +422,36 @@ pub async fn import_blocks(
421422
.iter()
422423
.map(|entry| {
423424
let path_str = entry.to_str().expect("Couldn't convert path to string");
424-
info!("Importing blocks from chain file: {path_str}");
425+
info!(path = %path_str, "Importing blocks from file");
425426
utils::read_chain_file(path_str)
426427
})
427428
.collect()
428429
} else {
429-
info!("Importing blocks from chain file: {path}");
430+
info!(path = %path, "Importing blocks from file");
430431
vec![utils::read_chain_file(path)]
431432
};
432433

434+
let mut total_blocks_imported = 0;
433435
for blocks in chains {
434436
let size = blocks.len();
435437
let mut numbers_and_hashes = blocks
436438
.iter()
437439
.map(|b| (b.header.number, b.hash()))
438440
.collect::<Vec<_>>();
439441
// Execute block by block
440-
for block in &blocks {
442+
let mut last_progress_log = Instant::now();
443+
for (index, block) in blocks.iter().enumerate() {
441444
let hash = block.hash();
442445
let number = block.header.number;
443-
info!("Adding block {number} with hash {hash:#x}.");
446+
447+
// Log progress every 10 seconds
448+
if last_progress_log.elapsed() >= Duration::from_secs(10) {
449+
let processed = index + 1;
450+
let percent = (((processed as f64 / size as f64) * 100.0) * 10.0).round() / 10.0;
451+
info!(processed, total = size, percent, "Import progress");
452+
last_progress_log = Instant::now();
453+
}
454+
444455
// Check if the block is already in the blockchain, if it is do nothing, if not add it
445456
let block_number = store.get_block_number(hash).await.map_err(|_e| {
446457
ChainError::Custom(String::from(
@@ -476,8 +487,15 @@ pub async fn import_blocks(
476487
.await?;
477488
}
478489

479-
info!("Added {size} blocks to blockchain");
490+
total_blocks_imported += size;
480491
}
492+
493+
let total_duration = start_time.elapsed();
494+
info!(
495+
blocks = total_blocks_imported,
496+
seconds = total_duration.as_secs_f64(),
497+
"Import completed"
498+
);
481499
Ok(())
482500
}
483501

@@ -516,6 +534,8 @@ pub async fn export_blocks(
516534
let mut file = File::create(path).expect("Failed to open file");
517535
let mut buffer = vec![];
518536
let mut last_output = Instant::now();
537+
// Denominator for percent completed; avoid division by zero
538+
let denom = end.saturating_sub(start) + 1;
519539
for n in start..=end {
520540
let block = store
521541
.get_block_by_number(n)
@@ -526,11 +546,13 @@ pub async fn export_blocks(
526546
block.encode(&mut buffer);
527547
// Exporting the whole chain can take a while, so we need to show some output in the meantime
528548
if last_output.elapsed() > Duration::from_secs(5) {
529-
info!("Exporting block {n}/{end}, {}% done", n * 100 / end);
549+
let completed = n.saturating_sub(start) + 1;
550+
let percent = (completed * 100) / denom;
551+
info!(n, end, percent, "Exporting blocks");
530552
last_output = Instant::now();
531553
}
532554
file.write_all(&buffer).expect("Failed to write to file");
533555
buffer.clear();
534556
}
535-
info!("Exported {} blocks to file {path}", end - start);
557+
info!(blocks = end.saturating_sub(start), path = %path, "Exported blocks to file");
536558
}

cmd/ethrex/initializers.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use std::{
3535
};
3636
use tokio::sync::Mutex;
3737
use tokio_util::{sync::CancellationToken, task::TaskTracker};
38-
use tracing::{error, info, warn};
38+
use tracing::{debug, error, info, warn};
3939
use tracing_subscriber::{
4040
EnvFilter, Layer, Registry, filter::Directive, fmt, layer::SubscriberExt,
4141
};
@@ -115,9 +115,10 @@ pub fn init_blockchain(
115115
evm_engine: EvmEngine,
116116
store: Store,
117117
blockchain_type: BlockchainType,
118+
perf_logs_enabled: bool,
118119
) -> Arc<Blockchain> {
119-
info!("Initiating blockchain with EVM: {}", evm_engine);
120-
Blockchain::new(evm_engine, store, blockchain_type).into()
120+
info!(evm = %evm_engine, "Initiating blockchain");
121+
Blockchain::new(evm_engine, store, blockchain_type, perf_logs_enabled).into()
121122
}
122123

123124
#[allow(clippy::too_many_arguments)]
@@ -250,7 +251,7 @@ pub fn get_bootnodes(opts: &Options, network: &Network, data_dir: &str) -> Vec<N
250251

251252
bootnodes.extend(network.get_bootnodes());
252253

253-
info!("Reading known peers from config file");
254+
debug!("Loading known peers from config");
254255

255256
match read_node_config_file(data_dir) {
256257
Ok(Some(ref mut config)) => bootnodes.append(&mut config.known_peers),
@@ -312,7 +313,7 @@ pub fn get_local_p2p_node(opts: &Options, signer: &SecretKey) -> Node {
312313
// TODO Find a proper place to show node information
313314
// https://github.com/lambdaclass/ethrex/issues/836
314315
let enode = node.enode_url();
315-
info!("Node: {enode}");
316+
info!(enode = %enode, "Local node initialized");
316317

317318
node
318319
}
@@ -384,7 +385,7 @@ pub async fn init_l1(
384385
#[cfg(feature = "sync-test")]
385386
set_sync_block(&store).await;
386387

387-
let blockchain = init_blockchain(opts.evm, store.clone(), BlockchainType::L1);
388+
let blockchain = init_blockchain(opts.evm, store.clone(), BlockchainType::L1, true);
388389

389390
let signer = get_signer(&data_dir);
390391

cmd/ethrex/l2/initializers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ pub async fn init_l2(opts: L2Options) -> eyre::Result<()> {
157157
let store = init_store(&data_dir, genesis).await;
158158
let rollup_store = init_rollup_store(&rollup_store_dir).await;
159159

160-
let blockchain = init_blockchain(opts.node_opts.evm, store.clone(), BlockchainType::L2);
160+
let blockchain = init_blockchain(opts.node_opts.evm, store.clone(), BlockchainType::L2, true);
161161

162162
let signer = get_signer(&data_dir);
163163

@@ -264,7 +264,7 @@ pub async fn init_l2(opts: L2Options) -> eyre::Result<()> {
264264
}
265265
info!("Server shut down started...");
266266
let node_config_path = PathBuf::from(data_dir + "/node_config.json");
267-
info!("Storing config at {:?}...", node_config_path);
267+
info!(path = %node_config_path.display(), "Storing node config");
268268
cancel_token.cancel();
269269
let node_config = NodeConfigFile::new(peer_table, local_node_record.lock().await.clone()).await;
270270
store_node_config_file(node_config, node_config_path).await;

crates/blockchain/blockchain.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub struct Blockchain {
6464
/// This will be set to true once the initial sync has taken place and wont be set to false after
6565
/// This does not reflect whether there is an ongoing sync process
6666
is_synced: AtomicBool,
67+
/// Whether performance logs should be emitted
68+
pub perf_logs_enabled: bool,
6769
pub r#type: BlockchainType,
6870
}
6971

@@ -86,13 +88,19 @@ fn log_batch_progress(batch_size: u32, current_block: u32) {
8688
}
8789

8890
impl Blockchain {
89-
pub fn new(evm_engine: EvmEngine, store: Store, blockchain_type: BlockchainType) -> Self {
91+
pub fn new(
92+
evm_engine: EvmEngine,
93+
store: Store,
94+
blockchain_type: BlockchainType,
95+
perf_logs_enabled: bool,
96+
) -> Self {
9097
Self {
9198
evm_engine,
9299
storage: store,
93100
mempool: Mempool::new(),
94101
is_synced: AtomicBool::new(false),
95102
r#type: blockchain_type,
103+
perf_logs_enabled,
96104
}
97105
}
98106

@@ -103,6 +111,7 @@ impl Blockchain {
103111
mempool: Mempool::new(),
104112
is_synced: AtomicBool::new(false),
105113
r#type: BlockchainType::default(),
114+
perf_logs_enabled: false,
106115
}
107116
}
108117

@@ -411,7 +420,10 @@ impl Blockchain {
411420
let merkleized = Instant::now();
412421
let result = self.store_block(block, account_updates_list, res).await;
413422
let stored = Instant::now();
414-
Self::print_add_block_logs(block, since, executed, merkleized, stored);
423+
424+
if self.perf_logs_enabled {
425+
Self::print_add_block_logs(block, since, executed, merkleized, stored);
426+
}
415427
result
416428
}
417429

@@ -459,7 +471,7 @@ impl Blockchain {
459471
"".to_string()
460472
};
461473

462-
info!("{}{}", base_log, extra_log);
474+
debug!("{}{}", base_log, extra_log);
463475
}
464476
}
465477

@@ -600,15 +612,17 @@ impl Blockchain {
600612
METRICS_BLOCKS.set_latest_gigagas(throughput);
601613
);
602614

603-
info!(
604-
"[METRICS] Executed and stored: Range: {}, Last block num: {}, Last block gas limit: {}, Total transactions: {}, Total Gas: {}, Throughput: {} Gigagas/s",
605-
blocks_len,
606-
last_block_number,
607-
last_block_gas_limit,
608-
transactions_count,
609-
total_gas_used,
610-
throughput
611-
);
615+
if self.perf_logs_enabled {
616+
info!(
617+
"[METRICS] Executed and stored: Range: {}, Last block num: {}, Last block gas limit: {}, Total transactions: {}, Total Gas: {}, Throughput: {} Gigagas/s",
618+
blocks_len,
619+
last_block_number,
620+
last_block_gas_limit,
621+
transactions_count,
622+
total_gas_used,
623+
throughput
624+
);
625+
}
612626

613627
Ok(())
614628
}

crates/storage/store.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::{
2424
collections::{BTreeMap, HashMap},
2525
sync::RwLock,
2626
};
27-
use tracing::{error, info, instrument};
27+
use tracing::{debug, error, info, instrument};
2828
/// Number of state trie segments to fetch concurrently during state sync
2929
pub const STATE_TRIE_SEGMENTS: usize = 2;
3030
/// Maximum amount of reads from the snapshot in a single transaction to avoid performance hits due to long-living reads
@@ -73,12 +73,12 @@ impl Store {
7373
self.engine.apply_updates(update_batch).await
7474
}
7575

76-
pub fn new(_path: &str, engine_type: EngineType) -> Result<Self, StoreError> {
77-
info!("Starting storage engine ({engine_type:?})");
76+
pub fn new(path: &str, engine_type: EngineType) -> Result<Self, StoreError> {
77+
info!(engine = ?engine_type, path = %path, "Opening storage engine");
7878
let store = match engine_type {
7979
#[cfg(feature = "libmdbx")]
8080
EngineType::Libmdbx => Self {
81-
engine: Arc::new(LibmdbxStore::new(_path)?),
81+
engine: Arc::new(LibmdbxStore::new(path)?),
8282
chain_config: Default::default(),
8383
latest_block_header: Arc::new(RwLock::new(BlockHeader::default())),
8484
},
@@ -89,7 +89,6 @@ impl Store {
8989
},
9090
};
9191

92-
info!("Started store engine");
9392
Ok(store)
9493
}
9594

@@ -569,7 +568,7 @@ impl Store {
569568
}
570569

571570
pub async fn add_initial_state(&self, genesis: Genesis) -> Result<(), StoreError> {
572-
info!("Storing initial state from genesis");
571+
debug!("Storing initial state from genesis");
573572

574573
// Obtain genesis block
575574
let genesis_block = genesis.get_block();
@@ -613,10 +612,7 @@ impl Store {
613612
debug_assert_eq!(genesis_state_root, genesis_block.header.state_root);
614613

615614
// Store genesis block
616-
info!(
617-
"Storing genesis block with number {} and hash {}",
618-
genesis_block_number, genesis_hash
619-
);
615+
info!(hash = %genesis_hash, "Storing genesis block");
620616

621617
self.add_block(genesis_block).await?;
622618
self.update_earliest_block_number(genesis_block_number)

fixtures/network/hoodi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
participants:
22
- el_type: ethrex
3-
el_image: ethrex:latest
3+
el_image: ethrex:local
44
cl_type: lighthouse
55
cl_image: sigp/lighthouse:v7.0.1
66
count: 1

tooling/ef_tests/blockchain/test_runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub async fn run_ef_test(
9797
check_prestate_against_db(test_key, test, &store);
9898

9999
// Blockchain EF tests are meant for L1.
100-
let blockchain = Blockchain::new(evm, store.clone(), BlockchainType::L1);
100+
let blockchain = Blockchain::new(evm, store.clone(), BlockchainType::L1, false);
101101

102102
// Early return if the exception is in the rlp decoding of the block
103103
for bf in &test.blocks {

0 commit comments

Comments
 (0)