From 2f81cdf38c3e14b1ad3756be040225f014c0b175 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 13:30:16 +0000 Subject: [PATCH 1/8] feat(resharding): implemented state-stats state-viewer command --- Cargo.lock | 1 + core/o11y/src/env_filter.rs | 3 +- core/o11y/src/subscriber.rs | 1 + core/store/src/flat/manager.rs | 4 +- neard/src/cli.rs | 4 +- tools/state-viewer/Cargo.toml | 7 +- tools/state-viewer/src/cli.rs | 17 ++++ tools/state-viewer/src/commands.rs | 133 +++++++++++++++++++++++++++++ 8 files changed, 162 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 494c7f2d04a..050c55657b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6651,6 +6651,7 @@ dependencies = [ "ansi_term", "anyhow", "borsh 1.0.0", + "bytesize", "chrono", "clap 4.2.4", "cloud-storage", diff --git a/core/o11y/src/env_filter.rs b/core/o11y/src/env_filter.rs index 8a6582e1ce6..a5a9081bee8 100644 --- a/core/o11y/src/env_filter.rs +++ b/core/o11y/src/env_filter.rs @@ -12,7 +12,8 @@ const DEFAULT_RUST_LOG: &str = "tokio_reactor=info,\ db=info,\ delay_detector=info,\ near-performance-metrics=info,\ - warn"; + state_viewer=info,\ + warn"; // why is the default warn?? #[non_exhaustive] #[derive(thiserror::Error, Debug)] diff --git a/core/o11y/src/subscriber.rs b/core/o11y/src/subscriber.rs index 3a80acde853..e838677384a 100644 --- a/core/o11y/src/subscriber.rs +++ b/core/o11y/src/subscriber.rs @@ -243,6 +243,7 @@ pub async fn default_subscriber_with_opentelemetry( node_public_key: PublicKey, account_id: Option, ) -> DefaultSubscriberGuard { + println!("env filter {env_filter:#?}"); let color_output = use_color_output(options); // Do not lock the `stderr` here to allow for things like `dbg!()` work during development. diff --git a/core/store/src/flat/manager.rs b/core/store/src/flat/manager.rs index c9de6f8a2a3..4bf5640bf9b 100644 --- a/core/store/src/flat/manager.rs +++ b/core/store/src/flat/manager.rs @@ -1,6 +1,7 @@ use crate::flat::{ store_helper, BlockInfo, FlatStorageReadyStatus, FlatStorageStatus, POISONED_LOCK_ERR, }; +use itertools::Itertools; use near_primitives::block::Block; use near_primitives::errors::StorageError; use near_primitives::hash::CryptoHash; @@ -64,7 +65,7 @@ impl FlatStorageManager { ); } - /// Creates flat storage instance for shard `shard_id`. The function also checks that + /// Creates flat storage instance for shard `shard_uid`. The function also checks that /// the shard's flat storage state hasn't been set before, otherwise it panics. /// TODO (#7327): this behavior may change when we implement support for state sync /// and resharding. @@ -191,6 +192,7 @@ impl FlatStorageManager { ) -> Option { let flat_storage = { let flat_storages = self.0.flat_storages.lock().expect(POISONED_LOCK_ERR); + tracing::info!(target: "store", flat_storages=?flat_storages.keys().collect_vec(), "flat storages"); // It is possible that flat storage state does not exist yet because it is being created in // background. match flat_storages.get(&shard_uid) { diff --git a/neard/src/cli.rs b/neard/src/cli.rs index 25ef154069e..a7b8cb7f2a7 100644 --- a/neard/src/cli.rs +++ b/neard/src/cli.rs @@ -51,6 +51,8 @@ impl NeardCmd { pub(super) fn parse_and_run() -> anyhow::Result<()> { let neard_cmd: Self = clap::Parser::parse(); + println!("env filter {:?}", make_env_filter(neard_cmd.opts.verbose_target())?); + // Enable logging of the current thread. let _subscriber_guard = default_subscriber( make_env_filter(neard_cmd.opts.verbose_target())?, @@ -62,7 +64,7 @@ impl NeardCmd { target: "neard", version = crate::NEARD_VERSION, build = crate::NEARD_BUILD, - latest_protocol = near_primitives::version::PROTOCOL_VERSION + latest_protocol = near_primitives::version::PROTOCOL_VERSION, ); #[cfg(feature = "test_features")] diff --git a/tools/state-viewer/Cargo.toml b/tools/state-viewer/Cargo.toml index d376fb2da79..7c2e03b9e53 100644 --- a/tools/state-viewer/Cargo.toml +++ b/tools/state-viewer/Cargo.toml @@ -13,6 +13,7 @@ actix.workspace = true ansi_term.workspace = true anyhow.workspace = true borsh.workspace = true +bytesize.workspace = true chrono.workspace = true clap.workspace = true cloud-storage.workspace = true @@ -51,11 +52,7 @@ testlib.workspace = true insta.workspace = true [features] -sandbox = [ - "node-runtime/sandbox", - "near-chain/sandbox", - "near-client/sandbox", -] +sandbox = ["node-runtime/sandbox", "near-chain/sandbox", "near-client/sandbox"] nightly = [ "nightly_protocol", "near-chain-configs/nightly", diff --git a/tools/state-viewer/src/cli.rs b/tools/state-viewer/src/cli.rs index 754ac6cbb14..0b25e394086 100644 --- a/tools/state-viewer/src/cli.rs +++ b/tools/state-viewer/src/cli.rs @@ -83,6 +83,9 @@ pub enum StateViewerSubCommand { StateChanges(StateChangesCmd), /// Dump or apply state parts. StateParts(StatePartsCmd), + /// Iterates over the Flat State and prints some statistics. + /// e.g. large accounts, total, average and median size, median account + StateStats(StateStatsCmd), /// Benchmark how long does it take to iterate the trie. TrieIterationBenchmark(TrieIterationBenchmarkCmd), /// View head of the storage. @@ -101,6 +104,8 @@ impl StateViewerSubCommand { mode: Mode, temperature: Temperature, ) { + let _span = tracing::debug_span!(target: "state_viewer", "aaa", value=4).entered(); + let near_config = load_config(home_dir, genesis_validation) .unwrap_or_else(|e| panic!("Error loading config: {:#}", e)); @@ -144,6 +149,7 @@ impl StateViewerSubCommand { StateViewerSubCommand::State => state(home_dir, near_config, store), StateViewerSubCommand::StateChanges(cmd) => cmd.run(home_dir, near_config, store), StateViewerSubCommand::StateParts(cmd) => cmd.run(home_dir, near_config, store), + StateViewerSubCommand::StateStats(cmd) => cmd.run(home_dir, near_config, store), StateViewerSubCommand::ViewChain(cmd) => cmd.run(near_config, store), StateViewerSubCommand::ViewTrie(cmd) => cmd.run(store), StateViewerSubCommand::TrieIterationBenchmark(cmd) => cmd.run(near_config, store), @@ -617,6 +623,17 @@ impl StatePartsCmd { ); } } + +#[derive(clap::Parser)] +pub struct StateStatsCmd {} + +impl StateStatsCmd { + pub fn run(self, home_dir: &Path, near_config: NearConfig, store: Store) { + tracing::info!(target: "state_viewer", "hello world!"); + print_state_stats(home_dir, store, near_config); + } +} + #[derive(clap::Parser)] pub struct ViewChainCmd { #[clap(long)] diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index 606a067bff1..a6a4d5c14b3 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -7,6 +7,7 @@ use crate::state_dump::state_dump_redis; use crate::tx_dump::dump_tx_from_block; use crate::{apply_chunk, epoch_info}; use ansi_term::Color::Red; +use bytesize::ByteSize; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::ApplyTransactionResult; @@ -23,15 +24,18 @@ use near_primitives::hash::CryptoHash; use near_primitives::shard_layout::ShardLayout; use near_primitives::shard_layout::ShardUId; use near_primitives::sharding::ChunkHash; +use near_primitives::state::FlatStateValue; use near_primitives::state_record::StateRecord; use near_primitives::trie_key::TrieKey; use near_primitives::types::{chunk_extra::ChunkExtra, BlockHeight, ShardId, StateRoot}; use near_primitives_core::types::Gas; use near_store::test_utils::create_test_store; +use near_store::TrieStorage; use near_store::{DBCol, Store, Trie, TrieCache, TrieCachingStorage, TrieConfig, TrieDBStorage}; use nearcore::{NearConfig, NightshadeRuntime}; use node_runtime::adapter::ViewRuntimeAdapter; use serde_json::json; +use std::collections::BinaryHeap; use std::collections::HashMap; use std::fs::{self, File}; use std::io::Write; @@ -1057,6 +1061,135 @@ pub(crate) fn clear_cache(store: Store) { store_update.commit().unwrap(); } +#[derive(PartialEq, Eq)] +pub struct StateStatsStateRecord { + key: Vec, + value: Vec, +} + +impl StateStatsStateRecord { + pub fn size(&self) -> usize { + self.key.len() + self.value.len() + } +} + +impl Ord for StateStatsStateRecord { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.size().cmp(&other.size()) + } +} + +impl PartialOrd for StateStatsStateRecord { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl std::fmt::Debug for StateStatsStateRecord { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let state_record = StateRecord::from_raw_key_value(self.key.clone(), self.value.clone()); + state_record.fmt(f) + } +} + +#[derive(Default)] +pub struct StateStats { + pub total_size: ByteSize, + pub total_count: usize, + + pub top_state_records: BinaryHeap, + + pub middle_state_record: Option, +} + +impl core::fmt::Debug for StateStats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let average_size = + self.total_size.as_u64().checked_div(self.total_count as u64).map(ByteSize::b); + f.debug_struct("StateStats") + .field("total_size", &self.total_size) + .field("total_count", &self.total_count) + .field("average_size", &average_size) + .field("top_state_records", &self.top_state_records) + .finish() + } +} + +impl StateStats { + pub fn new() -> Self { + Self::default() + } + + pub fn push(&mut self, key: Vec, value: Vec) -> () { + self.total_size += key.len() as u64 + value.len() as u64; + self.total_count += 1; + + self.top_state_records.push(StateStatsStateRecord { key, value }); + if self.top_state_records.len() > 5 { + self.top_state_records.pop(); + } + } +} + +fn read_flat_state_value( + trie_storage: &TrieDBStorage, + flat_state_value: FlatStateValue, +) -> Vec { + match flat_state_value { + FlatStateValue::Ref(val) => trie_storage.retrieve_raw_bytes(&val.hash).unwrap().to_vec(), + FlatStateValue::Inlined(val) => val, + } +} + +pub(crate) fn print_state_stats(home_dir: &Path, store: Store, near_config: NearConfig) { + let (epoch_manager, runtime, _, block_header) = + load_trie(store.clone(), home_dir, &near_config); + + let block_hash = *block_header.hash(); + let shard_layout = epoch_manager.get_shard_layout_from_prev_block(&block_hash).unwrap(); + + for shard_uid in shard_layout.get_shard_uids() { + let flat_storage_manager = runtime.get_flat_storage_manager(); + flat_storage_manager.create_flat_storage_for_shard(shard_uid).unwrap(); + let trie_storage = TrieDBStorage::new(store.clone(), shard_uid); + let chunk_view = flat_storage_manager.chunk_view(shard_uid, block_hash).unwrap(); + + let mut state_stats = StateStats::new(); + + let iter = chunk_view.iter_flat_state_entries(None, None); + for item in iter { + let Ok((key, value)) = item else { + continue; + }; + + let value = read_flat_state_value(&trie_storage, value); + + state_stats.push(key, value); + } + + let middle_size = state_stats.total_size.as_u64() / 2; + + let mut current_size = 0; + let iter = chunk_view.iter_flat_state_entries(None, None); + for item in iter { + let Ok((key, value)) = item else { + continue; + }; + + let value = read_flat_state_value(&trie_storage, value); + + current_size += key.len() + value.len(); + if middle_size <= current_size as u64 { + let state_record = StateRecord::from_raw_key_value(key, value); + state_stats.middle_state_record = state_record; + break; + } + } + + tracing::info!(target: "state_viewer", ?shard_uid, "{state_stats:#?}") + } +} + #[cfg(test)] mod tests { use near_chain::types::RuntimeAdapter; From 7046e2e83c7190161374bac926a0d983d06731dd Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 15:06:10 +0000 Subject: [PATCH 2/8] prettify --- tools/state-viewer/src/commands.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index a6a4d5c14b3..9bd1045a474 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -25,6 +25,7 @@ use near_primitives::shard_layout::ShardLayout; use near_primitives::shard_layout::ShardUId; use near_primitives::sharding::ChunkHash; use near_primitives::state::FlatStateValue; +use near_primitives::state_record::state_record_to_account_id; use near_primitives::state_record::StateRecord; use near_primitives::trie_key::TrieKey; use near_primitives::types::{chunk_extra::ChunkExtra, BlockHeight, ShardId, StateRoot}; @@ -1088,7 +1089,14 @@ impl PartialOrd for StateStatsStateRecord { impl std::fmt::Debug for StateStatsStateRecord { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let state_record = StateRecord::from_raw_key_value(self.key.clone(), self.value.clone()); - state_record.fmt(f) + + let Some(state_record) = state_record else { return None::.fmt(f) }; + + f.debug_struct("StateStatsStateRecord") + .field("account_id", state_record_to_account_id(&state_record)) + .field("type", &state_record.get_type_string()) + .field("size", &self.size()) + .finish() } } @@ -1186,7 +1194,8 @@ pub(crate) fn print_state_stats(home_dir: &Path, store: Store, near_config: Near } } - tracing::info!(target: "state_viewer", ?shard_uid, "{state_stats:#?}") + tracing::info!(target: "state_viewer", "{shard_uid:?}"); + tracing::info!(target: "state_viewer", "{state_stats:#?}"); } } From a8459aa502cb2cc2baee18eca10c45376d697136 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 15:43:28 +0000 Subject: [PATCH 3/8] cleanup --- core/o11y/src/subscriber.rs | 1 - core/store/src/flat/manager.rs | 1 - neard/src/cli.rs | 4 +--- tools/state-viewer/src/cli.rs | 3 --- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/core/o11y/src/subscriber.rs b/core/o11y/src/subscriber.rs index e838677384a..3a80acde853 100644 --- a/core/o11y/src/subscriber.rs +++ b/core/o11y/src/subscriber.rs @@ -243,7 +243,6 @@ pub async fn default_subscriber_with_opentelemetry( node_public_key: PublicKey, account_id: Option, ) -> DefaultSubscriberGuard { - println!("env filter {env_filter:#?}"); let color_output = use_color_output(options); // Do not lock the `stderr` here to allow for things like `dbg!()` work during development. diff --git a/core/store/src/flat/manager.rs b/core/store/src/flat/manager.rs index 4bf5640bf9b..acd82224d81 100644 --- a/core/store/src/flat/manager.rs +++ b/core/store/src/flat/manager.rs @@ -192,7 +192,6 @@ impl FlatStorageManager { ) -> Option { let flat_storage = { let flat_storages = self.0.flat_storages.lock().expect(POISONED_LOCK_ERR); - tracing::info!(target: "store", flat_storages=?flat_storages.keys().collect_vec(), "flat storages"); // It is possible that flat storage state does not exist yet because it is being created in // background. match flat_storages.get(&shard_uid) { diff --git a/neard/src/cli.rs b/neard/src/cli.rs index a7b8cb7f2a7..25ef154069e 100644 --- a/neard/src/cli.rs +++ b/neard/src/cli.rs @@ -51,8 +51,6 @@ impl NeardCmd { pub(super) fn parse_and_run() -> anyhow::Result<()> { let neard_cmd: Self = clap::Parser::parse(); - println!("env filter {:?}", make_env_filter(neard_cmd.opts.verbose_target())?); - // Enable logging of the current thread. let _subscriber_guard = default_subscriber( make_env_filter(neard_cmd.opts.verbose_target())?, @@ -64,7 +62,7 @@ impl NeardCmd { target: "neard", version = crate::NEARD_VERSION, build = crate::NEARD_BUILD, - latest_protocol = near_primitives::version::PROTOCOL_VERSION, + latest_protocol = near_primitives::version::PROTOCOL_VERSION ); #[cfg(feature = "test_features")] diff --git a/tools/state-viewer/src/cli.rs b/tools/state-viewer/src/cli.rs index 0b25e394086..05ce91dfd79 100644 --- a/tools/state-viewer/src/cli.rs +++ b/tools/state-viewer/src/cli.rs @@ -104,8 +104,6 @@ impl StateViewerSubCommand { mode: Mode, temperature: Temperature, ) { - let _span = tracing::debug_span!(target: "state_viewer", "aaa", value=4).entered(); - let near_config = load_config(home_dir, genesis_validation) .unwrap_or_else(|e| panic!("Error loading config: {:#}", e)); @@ -629,7 +627,6 @@ pub struct StateStatsCmd {} impl StateStatsCmd { pub fn run(self, home_dir: &Path, near_config: NearConfig, store: Store) { - tracing::info!(target: "state_viewer", "hello world!"); print_state_stats(home_dir, store, near_config); } } From d540b476b956c863435a96c44be7cb30d62ba253 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 15:45:27 +0000 Subject: [PATCH 4/8] nits --- core/store/src/flat/manager.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/store/src/flat/manager.rs b/core/store/src/flat/manager.rs index acd82224d81..13ab49cc062 100644 --- a/core/store/src/flat/manager.rs +++ b/core/store/src/flat/manager.rs @@ -1,7 +1,6 @@ use crate::flat::{ store_helper, BlockInfo, FlatStorageReadyStatus, FlatStorageStatus, POISONED_LOCK_ERR, }; -use itertools::Itertools; use near_primitives::block::Block; use near_primitives::errors::StorageError; use near_primitives::hash::CryptoHash; From 99cf526ddad83071822a30fa193b30f0d1f67db9 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 15:51:53 +0000 Subject: [PATCH 5/8] reverse ordering --- tools/state-viewer/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index 9bd1045a474..dede7bd5ea6 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -1076,7 +1076,7 @@ impl StateStatsStateRecord { impl Ord for StateStatsStateRecord { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.size().cmp(&other.size()) + self.size().cmp(&other.size()).reverse() } } From e03b43a3bc7bfb415844743cec8a041ee5afc1b8 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 15:58:48 +0000 Subject: [PATCH 6/8] bytesize --- tools/state-viewer/src/commands.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index dede7bd5ea6..3d700a8d6d7 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -1069,8 +1069,8 @@ pub struct StateStatsStateRecord { } impl StateStatsStateRecord { - pub fn size(&self) -> usize { - self.key.len() + self.value.len() + pub fn size(&self) -> ByteSize { + ByteSize::b(self.key.len() as u64 + self.value.len() as u64) } } From bb8706ef404f67e049368be2988e82cb4b6328c1 Mon Sep 17 00:00:00 2001 From: wacban Date: Fri, 3 Nov 2023 16:09:28 +0000 Subject: [PATCH 7/8] prettify more --- tools/state-viewer/src/commands.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index 3d700a8d6d7..c5207268d7f 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -1093,7 +1093,7 @@ impl std::fmt::Debug for StateStatsStateRecord { let Some(state_record) = state_record else { return None::.fmt(f) }; f.debug_struct("StateStatsStateRecord") - .field("account_id", state_record_to_account_id(&state_record)) + .field("account_id", &state_record_to_account_id(&state_record).as_str()) .field("type", &state_record.get_type_string()) .field("size", &self.size()) .finish() @@ -1107,17 +1107,22 @@ pub struct StateStats { pub top_state_records: BinaryHeap, - pub middle_state_record: Option, + pub middle_state_record: Option, } impl core::fmt::Debug for StateStats { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let average_size = - self.total_size.as_u64().checked_div(self.total_count as u64).map(ByteSize::b); + let average_size = self + .total_size + .as_u64() + .checked_div(self.total_count as u64) + .map(ByteSize::b) + .unwrap_or_default(); f.debug_struct("StateStats") .field("total_size", &self.total_size) .field("total_count", &self.total_count) .field("average_size", &average_size) + .field("middle_state_record", &self.middle_state_record.as_ref().unwrap()) .field("top_state_records", &self.top_state_records) .finish() } @@ -1188,8 +1193,7 @@ pub(crate) fn print_state_stats(home_dir: &Path, store: Store, near_config: Near current_size += key.len() + value.len(); if middle_size <= current_size as u64 { - let state_record = StateRecord::from_raw_key_value(key, value); - state_stats.middle_state_record = state_record; + state_stats.middle_state_record = Some(StateStatsStateRecord { key, value }); break; } } From 9a31eaff8dacd5a9352ee80d21d154aa39c3befa Mon Sep 17 00:00:00 2001 From: wacban Date: Mon, 6 Nov 2023 10:32:27 +0000 Subject: [PATCH 8/8] nits --- core/o11y/src/env_filter.rs | 2 +- tools/state-viewer/src/cli.rs | 2 +- tools/state-viewer/src/commands.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/o11y/src/env_filter.rs b/core/o11y/src/env_filter.rs index a5a9081bee8..1787a33d972 100644 --- a/core/o11y/src/env_filter.rs +++ b/core/o11y/src/env_filter.rs @@ -13,7 +13,7 @@ const DEFAULT_RUST_LOG: &str = "tokio_reactor=info,\ delay_detector=info,\ near-performance-metrics=info,\ state_viewer=info,\ - warn"; // why is the default warn?? + warn"; #[non_exhaustive] #[derive(thiserror::Error, Debug)] diff --git a/tools/state-viewer/src/cli.rs b/tools/state-viewer/src/cli.rs index 05ce91dfd79..8457f1fa2dd 100644 --- a/tools/state-viewer/src/cli.rs +++ b/tools/state-viewer/src/cli.rs @@ -84,7 +84,7 @@ pub enum StateViewerSubCommand { /// Dump or apply state parts. StateParts(StatePartsCmd), /// Iterates over the Flat State and prints some statistics. - /// e.g. large accounts, total, average and median size, median account + /// e.g. large accounts, total, average and median size, middle account StateStats(StateStatsCmd), /// Benchmark how long does it take to iterate the trie. TrieIterationBenchmark(TrieIterationBenchmarkCmd), diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index c5207268d7f..8aea507d72d 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -1186,6 +1186,7 @@ pub(crate) fn print_state_stats(home_dir: &Path, store: Store, near_config: Near let iter = chunk_view.iter_flat_state_entries(None, None); for item in iter { let Ok((key, value)) = item else { + tracing::warn!(target: "state_viewer", ?item, "error in iter item"); continue; };