feat: switch samply feature for CLI flags (#20586)

This commit is contained in:
DaniPopes
2025-12-27 12:16:49 -03:00
committed by GitHub
parent a852084b43
commit e595b58c28
12 changed files with 78 additions and 45 deletions

View File

@@ -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);

View File

@@ -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<Self> {
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 {

View File

@@ -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()
}

View File

@@ -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",

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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)
}

View File

@@ -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",

View File

@@ -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",

View File

@@ -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"]

View File

@@ -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(

View File

@@ -70,44 +70,51 @@ pub struct RethTracer {
stdout: LayerInfo,
journald: Option<String>,
file: Option<(LayerInfo, FileInfo)>,
samply: Option<LayerInfo>,
}
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