diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 585cd79167..c59db335b7 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -114,8 +114,6 @@ pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0; pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5; -pub const TRANSACTION_LOG_MESSAGES_BYTES_LIMIT: usize = 100 * 1000; - type BankStatusCache = StatusCache>; #[frozen_abi(digest = "4nZ6EdivqQPcnrnXisbjuTjpcUBoHLDEQWvbZQDCoQQR")] pub type BankSlotDelta = SlotDelta>; @@ -2531,22 +2529,6 @@ impl Bank { cache.remove(pubkey); } - pub fn truncate_log_messages( - log_messages: &mut TransactionLogMessages, - max_bytes: usize, - truncate_message: String, - ) { - let mut size = 0; - for (i, line) in log_messages.iter().enumerate() { - size += line.len(); - if size > max_bytes { - log_messages.truncate(i); - log_messages.push(truncate_message); - return; - } - } - } - #[allow(clippy::type_complexity)] pub fn load_and_execute_transactions( &self, @@ -2647,17 +2629,11 @@ impl Bank { ); if enable_log_recording { - let mut log_messages: TransactionLogMessages = + let log_messages: TransactionLogMessages = Rc::try_unwrap(log_collector.unwrap_or_default()) .unwrap_or_default() .into(); - Self::truncate_log_messages( - &mut log_messages, - TRANSACTION_LOG_MESSAGES_BYTES_LIMIT, - String::from("<< Transaction log truncated to 100KB >>\n"), - ); - transaction_logs.push(log_messages); } @@ -10432,55 +10408,6 @@ pub(crate) mod tests { assert_eq!(old_hash, new_bank1_hash); } - #[test] - fn test_truncate_log_messages() { - let mut messages = vec![ - String::from("This is line one\n"), - String::from("This is line two\n"), - String::from("This is line three\n"), - ]; - - // messages under limit - Bank::truncate_log_messages( - &mut messages, - 10000, - String::from("<< Transaction log truncated to 10,000 bytes >>\n"), - ); - assert_eq!(messages.len(), 3); - - // messages truncated to two lines - let maxsize = messages.get(0).unwrap().len() + messages.get(1).unwrap().len(); - Bank::truncate_log_messages( - &mut messages, - maxsize, - String::from("<< Transaction log truncated >>\n"), - ); - assert_eq!(messages.len(), 3); - assert_eq!( - messages.get(2).unwrap(), - "<< Transaction log truncated >>\n" - ); - - // messages truncated to one line - let mut messages = vec![ - String::from("Line 1\n"), - String::from("Line 2\n"), - String::from("Line 3\n"), - ]; - - let maxsize = messages.get(0).unwrap().len() + 4; - Bank::truncate_log_messages( - &mut messages, - maxsize, - String::from("<< Transaction log truncated >>\n"), - ); - assert_eq!(messages.len(), 2); - assert_eq!( - messages.get(1).unwrap(), - "<< Transaction log truncated >>\n" - ); - } - #[test] fn test_program_is_native_loader() { let (genesis_config, mint_keypair) = create_genesis_config(50000); diff --git a/runtime/src/log_collector.rs b/runtime/src/log_collector.rs index 9bb138dac4..c089bc1c30 100644 --- a/runtime/src/log_collector.rs +++ b/runtime/src/log_collector.rs @@ -1,18 +1,58 @@ use std::cell::RefCell; +const LOG_MESSAGES_BYTES_LIMIT: usize = 10 * 1000; + +#[derive(Default)] +struct LogCollectorInner { + messages: Vec, + bytes_written: usize, + limit_warning: bool, +} + #[derive(Default)] pub struct LogCollector { - messages: RefCell>, + inner: RefCell, } impl LogCollector { pub fn log(&self, message: &str) { - self.messages.borrow_mut().push(message.to_string()) + let mut inner = self.inner.borrow_mut(); + + if inner.bytes_written + message.len() >= LOG_MESSAGES_BYTES_LIMIT { + if !inner.limit_warning { + inner.limit_warning = true; + inner.messages.push(String::from("Log truncated")); + } + } else { + inner.bytes_written += message.len(); + inner.messages.push(message.to_string()); + } } } impl Into> for LogCollector { fn into(self) -> Vec { - self.messages.into_inner() + self.inner.into_inner().messages + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + #[test] + fn test_log_messages_bytes_limit() { + let lc = LogCollector::default(); + + for _i in 0..LOG_MESSAGES_BYTES_LIMIT * 2 { + lc.log("x"); + } + + let logs: Vec<_> = lc.into(); + assert_eq!(logs.len(), LOG_MESSAGES_BYTES_LIMIT); + for log in logs.iter().take(LOG_MESSAGES_BYTES_LIMIT - 1) { + assert_eq!(*log, "x".to_string()); + } + assert_eq!(logs.last(), Some(&"Log truncated".to_string())); } }