Skip to content

Commit

Permalink
feat(anvil): more flexible configuration LogCollector (foundry-rs#8328
Browse files Browse the repository at this point in the history
)

* wip

* separate console.log events under node::console

* rename

* fix

* fix: clippy + docs
  • Loading branch information
klkvr authored Jul 2, 2024
1 parent 20b3da1 commit f56616f
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 8 deletions.
5 changes: 5 additions & 0 deletions crates/anvil/src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ impl NodeArgs {
.with_transaction_order(self.order)
.with_genesis(self.init)
.with_steps_tracing(self.evm_opts.steps_tracing)
.with_print_logs(!self.evm_opts.disable_console_log)
.with_auto_impersonate(self.evm_opts.auto_impersonate)
.with_ipc(self.ipc)
.with_code_size_limit(self.evm_opts.code_size_limit)
Expand Down Expand Up @@ -507,6 +508,10 @@ pub struct AnvilEvmArgs {
#[arg(long, visible_alias = "tracing")]
pub steps_tracing: bool,

/// Disable printing of `console.log` invocations to stdout.
#[arg(long, visible_alias = "no-console-log")]
pub disable_console_log: bool,

/// Enable autoImpersonate on startup
#[arg(long, visible_alias = "auto-impersonate")]
pub auto_impersonate: bool,
Expand Down
11 changes: 11 additions & 0 deletions crates/anvil/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ pub struct NodeConfig {
pub ipc_path: Option<Option<String>>,
/// Enable transaction/call steps tracing for debug calls returning geth-style traces
pub enable_steps_tracing: bool,
/// Enable printing of `console.log` invocations.
pub print_logs: bool,
/// Enable auto impersonation of accounts on startup
pub enable_auto_impersonate: bool,
/// Configure the code size limit
Expand Down Expand Up @@ -404,6 +406,7 @@ impl Default for NodeConfig {
blob_excess_gas_and_price: None,
enable_tracing: true,
enable_steps_tracing: false,
print_logs: true,
enable_auto_impersonate: false,
no_storage_caching: false,
server_config: Default::default(),
Expand Down Expand Up @@ -789,6 +792,13 @@ impl NodeConfig {
self
}

/// Sets whether to print `console.log` invocations to stdout.
#[must_use]
pub fn with_print_logs(mut self, print_logs: bool) -> Self {
self.print_logs = print_logs;
self
}

/// Sets whether to enable autoImpersonate
#[must_use]
pub fn with_auto_impersonate(mut self, enable_auto_impersonate: bool) -> Self {
Expand Down Expand Up @@ -949,6 +959,7 @@ impl NodeConfig {
fees,
Arc::new(RwLock::new(fork)),
self.enable_steps_tracing,
self.print_logs,
self.prune_history,
self.transaction_block_keeper,
self.block_time,
Expand Down
4 changes: 4 additions & 0 deletions crates/anvil/src/eth/backend/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub struct TransactionExecutor<'a, Db: ?Sized, Validator: TransactionValidator>
/// Cumulative blob gas used by all executed transactions
pub blob_gas_used: u128,
pub enable_steps_tracing: bool,
pub print_logs: bool,
/// Precompiles to inject to the EVM.
pub precompile_factory: Option<Arc<dyn PrecompileFactory>>,
}
Expand Down Expand Up @@ -304,6 +305,9 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator
if self.enable_steps_tracing {
inspector = inspector.with_steps_tracing();
}
if self.print_logs {
inspector = inspector.with_log_collector();
}

let exec_result = {
let mut evm =
Expand Down
20 changes: 14 additions & 6 deletions crates/anvil/src/eth/backend/mem/inspector.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Anvil specific [`revm::Inspector`] implementation
use crate::{eth::macros::node_info, revm::Database};
use crate::revm::Database;
use alloy_primitives::{Address, Log};
use foundry_evm::{
call_inspectors,
Expand All @@ -22,15 +22,17 @@ use foundry_evm::{
pub struct Inspector {
pub tracer: Option<TracingInspector>,
/// collects all `console.sol` logs
pub log_collector: LogCollector,
pub log_collector: Option<LogCollector>,
}

impl Inspector {
/// Called after the inspecting the evm
///
/// This will log all `console.sol` logs
pub fn print_logs(&self) {
print_logs(&self.log_collector.logs)
if let Some(collector) = &self.log_collector {
print_logs(&collector.logs);
}
}

/// Configures the `Tracer` [`revm::Inspector`]
Expand All @@ -44,6 +46,12 @@ impl Inspector {
self.tracer = Some(TracingInspector::new(TracingInspectorConfig::all()));
self
}

/// Configures the `Tracer` [`revm::Inspector`]
pub fn with_log_collector(mut self) -> Self {
self.log_collector = Some(Default::default());
self
}
}

impl<DB: Database> revm::Inspector<DB> for Inspector {
Expand All @@ -66,15 +74,15 @@ impl<DB: Database> revm::Inspector<DB> for Inspector {
}

fn log(&mut self, ecx: &mut EvmContext<DB>, log: &Log) {
call_inspectors!([&mut self.tracer, Some(&mut self.log_collector)], |inspector| {
call_inspectors!([&mut self.tracer, &mut self.log_collector], |inspector| {
inspector.log(ecx, log);
});
}

fn call(&mut self, ecx: &mut EvmContext<DB>, inputs: &mut CallInputs) -> Option<CallOutcome> {
call_inspectors!(
#[ret]
[&mut self.tracer, Some(&mut self.log_collector)],
[&mut self.tracer, &mut self.log_collector],
|inspector| inspector.call(ecx, inputs).map(Some),
);
None
Expand Down Expand Up @@ -160,6 +168,6 @@ impl<DB: Database> InspectorExt<DB> for Inspector {}
/// Prints all the logs
pub fn print_logs(logs: &[Log]) {
for log in decode_console_logs(logs) {
node_info!("{}", log);
tracing::info!(target: crate::logging::EVM_CONSOLE_LOG_TARGET, "{}", log);
}
}
5 changes: 5 additions & 0 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pub struct Backend {
/// keeps track of active snapshots at a specific block
active_snapshots: Arc<Mutex<HashMap<U256, (u64, B256)>>>,
enable_steps_tracing: bool,
print_logs: bool,
/// How to keep history state
prune_state_history_config: PruneStateHistoryConfig,
/// max number of blocks with transactions in memory
Expand All @@ -187,6 +188,7 @@ impl Backend {
fees: FeeManager,
fork: Arc<RwLock<Option<ClientFork>>>,
enable_steps_tracing: bool,
print_logs: bool,
prune_state_history_config: PruneStateHistoryConfig,
transaction_block_keeper: Option<usize>,
automine_block_time: Option<Duration>,
Expand Down Expand Up @@ -239,6 +241,7 @@ impl Backend {
genesis,
active_snapshots: Arc::new(Mutex::new(Default::default())),
enable_steps_tracing,
print_logs,
prune_state_history_config,
transaction_block_keeper,
node_config,
Expand Down Expand Up @@ -898,6 +901,7 @@ impl Backend {
gas_used: 0,
blob_gas_used: 0,
enable_steps_tracing: self.enable_steps_tracing,
print_logs: self.print_logs,
precompile_factory: self.precompile_factory.clone(),
};

Expand Down Expand Up @@ -969,6 +973,7 @@ impl Backend {
gas_used: 0,
blob_gas_used: 0,
enable_steps_tracing: self.enable_steps_tracing,
print_logs: self.print_logs,
precompile_factory: self.precompile_factory.clone(),
};
let executed_tx = executor.execute();
Expand Down
12 changes: 10 additions & 2 deletions crates/anvil/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use tracing_subscriber::{layer::Context, Layer};
/// The target that identifies the events intended to be logged to stdout
pub(crate) const NODE_USER_LOG_TARGET: &str = "node::user";

/// The target that identifies the events coming from the `console.log` invocations.
pub(crate) const EVM_CONSOLE_LOG_TARGET: &str = "node::console";

/// A logger that listens for node related events and displays them.
///
/// This layer is intended to be used as filter for `NODE_USER_LOG_TARGET` events that will
Expand All @@ -30,15 +33,20 @@ where
S: tracing::Subscriber,
{
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
if self.state.is_enabled() && metadata.target() == NODE_USER_LOG_TARGET {
if self.state.is_enabled() &&
(metadata.target() == NODE_USER_LOG_TARGET ||
metadata.target() == EVM_CONSOLE_LOG_TARGET)
{
Interest::always()
} else {
Interest::never()
}
}

fn enabled(&self, metadata: &Metadata<'_>, _ctx: Context<'_, S>) -> bool {
self.state.is_enabled() && metadata.target() == NODE_USER_LOG_TARGET
self.state.is_enabled() &&
(metadata.target() == NODE_USER_LOG_TARGET ||
metadata.target() == EVM_CONSOLE_LOG_TARGET)
}
}

Expand Down

0 comments on commit f56616f

Please sign in to comment.