diff --git a/bin/reth-bench-compare/src/cli.rs b/bin/reth-bench-compare/src/cli.rs index 6c30532daf..460d536e3a 100644 --- a/bin/reth-bench-compare/src/cli.rs +++ b/bin/reth-bench-compare/src/cli.rs @@ -329,7 +329,6 @@ pub(crate) async fn run_comparison(args: Args, _ctx: CliContext) -> Result<()> { output_dir.clone(), git_manager.clone(), args.features.clone(), - args.profile, )?; // Initialize node manager let mut node_manager = NodeManager::new(&args); diff --git a/bin/reth-bench-compare/src/compilation.rs b/bin/reth-bench-compare/src/compilation.rs index 3795dc58e9..d5b74e911e 100644 --- a/bin/reth-bench-compare/src/compilation.rs +++ b/bin/reth-bench-compare/src/compilation.rs @@ -14,7 +14,6 @@ pub(crate) struct CompilationManager { output_dir: PathBuf, git_manager: GitManager, features: String, - enable_profiling: bool, } impl CompilationManager { @@ -24,9 +23,8 @@ impl CompilationManager { output_dir: PathBuf, git_manager: GitManager, features: String, - enable_profiling: bool, ) -> Result { - Ok(Self { repo_root, output_dir, git_manager, features, enable_profiling }) + Ok(Self { repo_root, output_dir, git_manager, features }) } /// Detect if the RPC endpoint is an Optimism chain @@ -102,18 +100,9 @@ impl CompilationManager { let mut cmd = Command::new("cargo"); cmd.arg("build").arg("--profile").arg("profiling"); - // Append samply feature when profiling to enable tracing span markers. - // NOTE: The `samply` feature must exist in the branch being compiled. If comparing - // against an older branch that predates the samply integration, compilation will fail - // or markers won't appear. In that case, omit --profile or ensure both branches - // include the samply feature support. - let features = if self.enable_profiling && !self.features.contains("samply") { - format!("{},samply", self.features) - } else { - self.features.clone() - }; - cmd.arg("--features").arg(&features); - info!("Using features: {}", features); + let features = &self.features; + cmd.arg("--features").arg(features); + info!("Using features: {features}"); // Add bin-specific arguments for optimism if is_optimism { diff --git a/bin/reth-bench-compare/src/node.rs b/bin/reth-bench-compare/src/node.rs index 4de48eebf4..b551a24721 100644 --- a/bin/reth-bench-compare/src/node.rs +++ b/bin/reth-bench-compare/src/node.rs @@ -211,6 +211,11 @@ impl NodeManager { cmd.arg("--"); cmd.args(reth_args); + // Enable tracing-samply + if supports_samply_flags(&reth_args[0]) { + cmd.arg("--log.samply"); + } + // Set environment variable to disable log styling cmd.env("RUST_LOG_STYLE", "never"); @@ -552,3 +557,16 @@ impl NodeManager { Ok(()) } } + +fn supports_samply_flags(bin: &str) -> bool { + let mut cmd = std::process::Command::new(bin); + // NOTE: The flag to check must come before --help. + // We pass --help as a shortcut to not execute any command. + cmd.args(["--log.samply", "--help"]); + debug!(?cmd, "Checking samply flags support"); + let Ok(output) = cmd.output() else { + return false; + }; + debug!(?output, "Samply flags support check"); + output.status.success() +} diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index 9eef353349..6baeb8679b 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -87,10 +87,6 @@ otlp = [ "reth-ethereum-cli/otlp", "reth-node-core/otlp", ] -samply = [ - "reth-ethereum-cli/samply", - "reth-node-core/samply", -] js-tracer = [ "reth-node-builder/js-tracer", "reth-node-ethereum/js-tracer", diff --git a/crates/ethereum/cli/Cargo.toml b/crates/ethereum/cli/Cargo.toml index 3000f4c67b..83f8083ae4 100644 --- a/crates/ethereum/cli/Cargo.toml +++ b/crates/ethereum/cli/Cargo.toml @@ -38,7 +38,6 @@ tempfile.workspace = true default = [] otlp = ["reth-tracing/otlp", "reth-node-core/otlp"] -samply = ["reth-tracing/samply", "reth-node-core/samply"] dev = ["reth-cli-commands/arbitrary"] diff --git a/crates/node/core/Cargo.toml b/crates/node/core/Cargo.toml index e4a3ef7120..eccccd8c14 100644 --- a/crates/node/core/Cargo.toml +++ b/crates/node/core/Cargo.toml @@ -82,7 +82,6 @@ jemalloc = ["reth-cli-util/jemalloc"] asm-keccak = ["alloy-primitives/asm-keccak"] keccak-cache-global = ["alloy-primitives/keccak-cache-global"] otlp = ["reth-tracing/otlp"] -samply = ["reth-tracing/samply"] min-error-logs = ["tracing/release_max_level_error"] min-warn-logs = ["tracing/release_max_level_warn"] diff --git a/crates/node/core/src/args/log.rs b/crates/node/core/src/args/log.rs index 20c60362d7..311e55588f 100644 --- a/crates/node/core/src/args/log.rs +++ b/crates/node/core/src/args/log.rs @@ -61,6 +61,20 @@ pub struct LogArgs { )] pub journald_filter: String, + /// Emit traces to samply. Only useful when profiling. + #[arg(long = "log.samply", global = true, hide = true)] + pub samply: bool, + + /// The filter to use for traces emitted to samply. + #[arg( + long = "log.samply.filter", + value_name = "FILTER", + global = true, + default_value = "debug", + hide = true + )] + pub samply_filter: String, + /// Sets whether or not the formatter emits ANSI terminal escape codes for colors and other /// text formatting. #[arg( @@ -129,6 +143,11 @@ impl LogArgs { tracer = tracer.with_file(file, info); } + if self.samply { + let config = self.layer_info(LogFormat::Terminal, self.samply_filter.clone(), false); + tracer = tracer.with_samply(config); + } + let guard = tracer.init_with_layers(layers)?; Ok(guard) } diff --git a/crates/optimism/bin/Cargo.toml b/crates/optimism/bin/Cargo.toml index c9d2a2f3d3..a13ab3fed9 100644 --- a/crates/optimism/bin/Cargo.toml +++ b/crates/optimism/bin/Cargo.toml @@ -30,7 +30,6 @@ workspace = true default = ["jemalloc", "otlp", "reth-optimism-evm/portable", "js-tracer", "keccak-cache-global", "asm-keccak"] otlp = ["reth-optimism-cli/otlp"] -samply = ["reth-optimism-cli/samply"] js-tracer = [ "reth-optimism-node/js-tracer", diff --git a/crates/optimism/cli/Cargo.toml b/crates/optimism/cli/Cargo.toml index 062d66dfd4..bdb680b206 100644 --- a/crates/optimism/cli/Cargo.toml +++ b/crates/optimism/cli/Cargo.toml @@ -78,7 +78,6 @@ default = [] # Opentelemtry feature to activate metrics export otlp = ["reth-tracing/otlp", "reth-node-core/otlp"] -samply = ["reth-tracing/samply", "reth-node-core/samply"] asm-keccak = [ "alloy-primitives/asm-keccak", diff --git a/crates/tracing/Cargo.toml b/crates/tracing/Cargo.toml index fd5f5f55de..5b61b1f3e1 100644 --- a/crates/tracing/Cargo.toml +++ b/crates/tracing/Cargo.toml @@ -21,14 +21,13 @@ tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "ansi" tracing-appender.workspace = true tracing-journald.workspace = true tracing-logfmt.workspace = true +tracing-samply.workspace = true # misc clap = { workspace = true, features = ["derive"] } eyre.workspace = true rolling-file.workspace = true -tracing-samply = { workspace = true, optional = true } [features] default = ["otlp"] otlp = ["reth-tracing-otlp"] -samply = ["tracing-samply"] diff --git a/crates/tracing/src/layers.rs b/crates/tracing/src/layers.rs index 44462ca7c6..dd5c7787d4 100644 --- a/crates/tracing/src/layers.rs +++ b/crates/tracing/src/layers.rs @@ -1,4 +1,4 @@ -use crate::formatter::LogFormat; +use crate::{formatter::LogFormat, LayerInfo}; #[cfg(feature = "otlp")] use reth_tracing_otlp::{span_layer, OtlpConfig}; use rolling_file::{RollingConditionBasic, RollingFileAppender}; @@ -130,6 +130,18 @@ impl Layers { Ok(guard) } + pub(crate) fn samply(&mut self, config: LayerInfo) -> eyre::Result<()> { + self.add_layer( + tracing_samply::SamplyLayer::new() + .map_err(|e| eyre::eyre!("Failed to create samply layer: {e}"))? + .with_filter(build_env_filter( + Some(config.default_directive.parse()?), + &config.filters, + )?), + ); + Ok(()) + } + /// Add OTLP spans layer to the layer collection #[cfg(feature = "otlp")] pub fn with_span_layer( diff --git a/crates/tracing/src/lib.rs b/crates/tracing/src/lib.rs index 346cc5faf1..f42e08370f 100644 --- a/crates/tracing/src/lib.rs +++ b/crates/tracing/src/lib.rs @@ -70,44 +70,51 @@ pub struct RethTracer { stdout: LayerInfo, journald: Option, file: Option<(LayerInfo, FileInfo)>, + samply: Option, } impl RethTracer { - /// Constructs a new `Tracer` with default settings. + /// Constructs a new `Tracer` with default settings. /// - /// Initializes with default stdout layer configuration. - /// Journald and file layers are not set by default. + /// Initializes with default stdout layer configuration. + /// Journald and file layers are not set by default. pub fn new() -> Self { - Self { stdout: LayerInfo::default(), journald: None, file: None } + Self { stdout: LayerInfo::default(), journald: None, file: None, samply: None } } - /// Sets a custom configuration for the stdout layer. + /// Sets a custom configuration for the stdout layer. /// - /// # Arguments - /// * `config` - The `LayerInfo` to use for the stdout layer. + /// # Arguments + /// * `config` - The `LayerInfo` to use for the stdout layer. pub fn with_stdout(mut self, config: LayerInfo) -> Self { self.stdout = config; self } - /// Sets the journald layer filter. + /// Sets the journald layer filter. /// - /// # Arguments - /// * `filter` - The `filter` to use for the journald layer. + /// # Arguments + /// * `filter` - The `filter` to use for the journald layer. pub fn with_journald(mut self, filter: String) -> Self { self.journald = Some(filter); self } - /// Sets the file layer configuration and associated file info. + /// Sets the file layer configuration and associated file info. /// /// # Arguments - /// * `config` - The `LayerInfo` to use for the file layer. - /// * `file_info` - The `FileInfo` containing details about the log file. + /// * `config` - The `LayerInfo` to use for the file layer. + /// * `file_info` - The `FileInfo` containing details about the log file. pub fn with_file(mut self, config: LayerInfo, file_info: FileInfo) -> Self { self.file = Some((config, file_info)); self } + + /// Sets the samply layer configuration. + pub fn with_samply(mut self, config: LayerInfo) -> Self { + self.samply = Some(config); + self + } } impl Default for RethTracer { @@ -224,11 +231,9 @@ impl Tracer for RethTracer { None }; - #[cfg(feature = "samply")] - layers.add_layer( - tracing_samply::SamplyLayer::new() - .map_err(|e| eyre::eyre!("Failed to create samply layer: {}", e))?, - ); + if let Some(config) = self.samply { + layers.samply(config)?; + } // The error is returned if the global default subscriber is already set, // so it's safe to ignore it