diff --git a/.config/zepter.yaml b/.config/zepter.yaml index dcc18676c4..a79b3bc47a 100644 --- a/.config/zepter.yaml +++ b/.config/zepter.yaml @@ -12,7 +12,7 @@ workflows: # Check that `A` activates the features of `B`. "propagate-feature", # These are the features to check: - "--features=std,op,dev,asm-keccak,jemalloc,jemalloc-prof,tracy-allocator,serde-bincode-compat,serde,test-utils,arbitrary,bench,alloy-compat,min-error-logs,min-warn-logs,min-info-logs,min-debug-logs,min-trace-logs,otlp,js-tracer,portable,keccak-cache-global", + "--features=std,op,dev,asm-keccak,jemalloc,jemalloc-prof,tracy-allocator,tracy,serde-bincode-compat,serde,test-utils,arbitrary,bench,alloy-compat,min-error-logs,min-warn-logs,min-info-logs,min-debug-logs,min-trace-logs,otlp,js-tracer,portable,keccak-cache-global", # Do not try to add a new section to `[features]` of `A` only because `B` exposes that feature. There are edge-cases where this is still needed, but we can add them manually. "--left-side-feature-missing=ignore", # Ignore the case that `A` it outside of the workspace. Otherwise it will report errors in external dependencies that we have no influence on. diff --git a/Cargo.lock b/Cargo.lock index a1fbbb678c..38828faaaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7923,6 +7923,7 @@ dependencies = [ "rand 0.8.5", "rand 0.9.2", "reth-fs-util", + "reth-tracing", "secp256k1 0.30.0", "serde", "snmalloc-rs", @@ -11037,6 +11038,8 @@ dependencies = [ "tracing-logfmt", "tracing-samply", "tracing-subscriber 0.3.22", + "tracing-tracy", + "tracy-client", ] [[package]] @@ -13347,6 +13350,17 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-tracy" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" +dependencies = [ + "tracing-core", + "tracing-subscriber 0.3.22", + "tracy-client", +] + [[package]] name = "tracy-client" version = "0.18.3" diff --git a/Cargo.toml b/Cargo.toml index ffa874a671..0210182cd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -734,6 +734,7 @@ tracing-journald = "0.3" tracing-logfmt = "0.3.3" tracing-samply = "0.1" tracing-subscriber = { version = "0.3", default-features = false } +tracing-tracy = "0.11" triehash = "0.8" typenum = "1.15.0" vergen = "9.0.4" diff --git a/bin/reth-bench-compare/Cargo.toml b/bin/reth-bench-compare/Cargo.toml index e390806157..ecc5a40478 100644 --- a/bin/reth-bench-compare/Cargo.toml +++ b/bin/reth-bench-compare/Cargo.toml @@ -71,7 +71,11 @@ jemalloc = [ "reth-node-core/jemalloc", ] jemalloc-prof = ["reth-cli-util/jemalloc-prof"] -tracy-allocator = ["reth-cli-util/tracy-allocator"] +tracy-allocator = ["reth-cli-util/tracy-allocator", "tracy"] +tracy = [ + "reth-node-core/tracy", + "reth-tracing/tracy", +] min-error-logs = [ "tracing/release_max_level_error", diff --git a/bin/reth-bench/Cargo.toml b/bin/reth-bench/Cargo.toml index 303b4656f2..bfc0051fab 100644 --- a/bin/reth-bench/Cargo.toml +++ b/bin/reth-bench/Cargo.toml @@ -85,7 +85,11 @@ jemalloc = [ "reth-node-core/jemalloc", ] jemalloc-prof = ["reth-cli-util/jemalloc-prof"] -tracy-allocator = ["reth-cli-util/tracy-allocator"] +tracy-allocator = ["reth-cli-util/tracy-allocator", "tracy"] +tracy = [ + "reth-node-core/tracy", + "reth-tracing/tracy", +] min-error-logs = [ "tracing/release_max_level_error", diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index 63fa878888..94cf2334eb 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -131,6 +131,11 @@ jemalloc-unprefixed = [ tracy-allocator = [ "reth-cli-util/tracy-allocator", "reth-ethereum-cli/tracy-allocator", + "tracy", +] +tracy = [ + "reth-ethereum-cli/tracy", + "reth-node-core/tracy", ] # Because jemalloc is default and preferred over snmalloc when both features are diff --git a/crates/cli/util/Cargo.toml b/crates/cli/util/Cargo.toml index 5dabb7cfb6..3e7fbed45b 100644 --- a/crates/cli/util/Cargo.toml +++ b/crates/cli/util/Cargo.toml @@ -26,7 +26,8 @@ rand_08.workspace = true thiserror.workspace = true serde.workspace = true -tracy-client = { workspace = true, optional = true, features = ["demangle"] } +tracy-client = { workspace = true, optional = true } +reth-tracing = { workspace = true, optional = true } [dev-dependencies] rand.workspace = true @@ -46,7 +47,7 @@ jemalloc-prof = ["jemalloc", "tikv-jemallocator?/profiling"] jemalloc-unprefixed = ["jemalloc", "tikv-jemallocator?/unprefixed_malloc_on_supported_platforms"] # Wraps the selected allocator in the tracy profiling allocator -tracy-allocator = ["dep:tracy-client"] +tracy-allocator = ["dep:tracy-client", "dep:reth-tracing"] snmalloc = ["dep:snmalloc-rs"] diff --git a/crates/cli/util/src/allocator.rs b/crates/cli/util/src/allocator.rs index 753c987324..004404a0e8 100644 --- a/crates/cli/util/src/allocator.rs +++ b/crates/cli/util/src/allocator.rs @@ -25,7 +25,6 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(feature = "tracy-allocator")] { type AllocatorWrapper = tracy_client::ProfiledAllocator; - tracy_client::register_demangler!(); const fn new_allocator_wrapper() -> AllocatorWrapper { AllocatorWrapper::new(AllocatorInner {}, 100) } diff --git a/crates/cli/util/src/lib.rs b/crates/cli/util/src/lib.rs index 12c3cdf1e4..b7605e9516 100644 --- a/crates/cli/util/src/lib.rs +++ b/crates/cli/util/src/lib.rs @@ -8,6 +8,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg))] +#[cfg(feature = "tracy-allocator")] +use reth_tracing as _; + pub mod allocator; pub mod cancellation; diff --git a/crates/ethereum/cli/Cargo.toml b/crates/ethereum/cli/Cargo.toml index 2d78c518c7..524a094647 100644 --- a/crates/ethereum/cli/Cargo.toml +++ b/crates/ethereum/cli/Cargo.toml @@ -58,7 +58,8 @@ jemalloc-symbols = [ "jemalloc-prof", "reth-node-metrics/jemalloc-symbols", ] -tracy-allocator = [] +tracy-allocator = ["tracy"] +tracy = ["reth-tracing/tracy", "reth-node-core/tracy"] # Because jemalloc is default and preferred over snmalloc when both features are # enabled, `--no-default-features` should be used when enabling snmalloc or diff --git a/crates/node/core/Cargo.toml b/crates/node/core/Cargo.toml index eccccd8c14..c421d8bacc 100644 --- a/crates/node/core/Cargo.toml +++ b/crates/node/core/Cargo.toml @@ -82,6 +82,7 @@ jemalloc = ["reth-cli-util/jemalloc"] asm-keccak = ["alloy-primitives/asm-keccak"] keccak-cache-global = ["alloy-primitives/keccak-cache-global"] otlp = ["reth-tracing/otlp"] +tracy = ["reth-tracing/tracy"] 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 311e55588f..d396b4ad19 100644 --- a/crates/node/core/src/args/log.rs +++ b/crates/node/core/src/args/log.rs @@ -75,6 +75,20 @@ pub struct LogArgs { )] pub samply_filter: String, + /// Emit traces to tracy. Only useful when profiling. + #[arg(long = "log.tracy", global = true, hide = true)] + pub tracy: bool, + + /// The filter to use for traces emitted to tracy. + #[arg( + long = "log.tracy.filter", + value_name = "FILTER", + global = true, + default_value = "debug", + hide = true + )] + pub tracy_filter: String, + /// Sets whether or not the formatter emits ANSI terminal escape codes for colors and other /// text formatting. #[arg( @@ -148,6 +162,12 @@ impl LogArgs { tracer = tracer.with_samply(config); } + #[cfg(feature = "tracy")] + if self.tracy { + let config = self.layer_info(LogFormat::Terminal, self.tracy_filter.clone(), false); + tracer = tracer.with_tracy(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 88253d7ee9..ecaa339ab8 100644 --- a/crates/optimism/bin/Cargo.toml +++ b/crates/optimism/bin/Cargo.toml @@ -38,7 +38,8 @@ js-tracer = [ jemalloc = ["reth-cli-util/jemalloc", "reth-optimism-cli/jemalloc"] jemalloc-prof = ["jemalloc", "reth-cli-util/jemalloc-prof", "reth-optimism-cli/jemalloc-prof"] jemalloc-symbols = ["jemalloc-prof", "reth-optimism-cli/jemalloc-symbols"] -tracy-allocator = ["reth-cli-util/tracy-allocator"] +tracy-allocator = ["reth-cli-util/tracy-allocator", "tracy"] +tracy = ["reth-optimism-cli/tracy"] asm-keccak = ["reth-optimism-cli/asm-keccak", "reth-optimism-node/asm-keccak"] keccak-cache-global = [ diff --git a/crates/optimism/cli/Cargo.toml b/crates/optimism/cli/Cargo.toml index 6c3b69fa31..1c56c07b94 100644 --- a/crates/optimism/cli/Cargo.toml +++ b/crates/optimism/cli/Cargo.toml @@ -99,6 +99,8 @@ jemalloc-symbols = [ "reth-node-metrics/jemalloc-symbols", ] +tracy = ["reth-tracing/tracy", "reth-node-core/tracy"] + dev = [ "dep:proptest", "reth-cli-commands/arbitrary", diff --git a/crates/tracing/Cargo.toml b/crates/tracing/Cargo.toml index 5b61b1f3e1..595e76765c 100644 --- a/crates/tracing/Cargo.toml +++ b/crates/tracing/Cargo.toml @@ -22,6 +22,8 @@ tracing-appender.workspace = true tracing-journald.workspace = true tracing-logfmt.workspace = true tracing-samply.workspace = true +tracing-tracy = { workspace = true, optional = true } +tracy-client = { workspace = true, optional = true, features = ["demangle"] } # misc clap = { workspace = true, features = ["derive"] } @@ -31,3 +33,4 @@ rolling-file.workspace = true [features] default = ["otlp"] otlp = ["reth-tracing-otlp"] +tracy = ["tracing-tracy", "tracy-client"] diff --git a/crates/tracing/src/layers.rs b/crates/tracing/src/layers.rs index dd5c7787d4..2b0d72eb5c 100644 --- a/crates/tracing/src/layers.rs +++ b/crates/tracing/src/layers.rs @@ -142,6 +142,15 @@ impl Layers { Ok(()) } + #[cfg(feature = "tracy")] + pub(crate) fn tracy(&mut self, config: LayerInfo) -> eyre::Result<()> { + self.add_layer(tracing_tracy::TracyLayer::default().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 f42e08370f..762867ab9c 100644 --- a/crates/tracing/src/lib.rs +++ b/crates/tracing/src/lib.rs @@ -48,6 +48,9 @@ pub use tracing; pub use tracing_appender; pub use tracing_subscriber; +#[cfg(feature = "tracy")] +tracy_client::register_demangler!(); + // Re-export our types pub use formatter::LogFormat; pub use layers::{FileInfo, FileWorkerGuard, Layers}; @@ -71,6 +74,8 @@ pub struct RethTracer { journald: Option, file: Option<(LayerInfo, FileInfo)>, samply: Option, + #[cfg(feature = "tracy")] + tracy: Option, } impl RethTracer { @@ -79,7 +84,14 @@ impl RethTracer { /// 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, samply: None } + Self { + stdout: LayerInfo::default(), + journald: None, + file: None, + samply: None, + #[cfg(feature = "tracy")] + tracy: None, + } } /// Sets a custom configuration for the stdout layer. @@ -115,6 +127,13 @@ impl RethTracer { self.samply = Some(config); self } + + /// Sets the tracy layer configuration. + #[cfg(feature = "tracy")] + pub fn with_tracy(mut self, config: LayerInfo) -> Self { + self.tracy = Some(config); + self + } } impl Default for RethTracer { @@ -235,6 +254,11 @@ impl Tracer for RethTracer { layers.samply(config)?; } + #[cfg(feature = "tracy")] + if let Some(config) = self.tracy { + layers.tracy(config)?; + } + // The error is returned if the global default subscriber is already set, // so it's safe to ignore it let _ = tracing_subscriber::registry().with(layers.into_inner()).try_init();