From 0d74252537b6fd3ae6287486dbeec437cf021efa Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 12 May 2025 16:27:09 +0200 Subject: [PATCH 1/3] Allow initializing logger with additional tracing Layer --- compiler/rustc_driver_impl/src/lib.rs | 11 +++++++++++ compiler/rustc_log/src/lib.rs | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 54a331a490444..83552af5a0ee8 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1507,6 +1507,17 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) { } } +pub fn init_logger_with_additional_layer( + early_dcx: &EarlyDiagCtxt, + cfg: rustc_log::LoggerConfig, + additional_tracing_layer: impl rustc_log::Layer + Send + Sync, +) { + if let Err(error) = rustc_log::init_logger_with_additional_layer(cfg, additional_tracing_layer) + { + early_dcx.early_fatal(error.to_string()); + } +} + /// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`]. /// Making this handler optional lets tools can install a different handler, if they wish. pub fn install_ctrlc_handler() { diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 1bb502ca3d062..404106e472ce0 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -42,7 +42,9 @@ use tracing_core::{Event, Subscriber}; use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; use tracing_subscriber::fmt::FmtContext; use tracing_subscriber::fmt::format::{self, FormatEvent, FormatFields}; -use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::layer::{Identity, SubscriberExt}; +// Re-export tracing_subscriber items so rustc_driver_impl doesn't need to depend on it. +pub use tracing_subscriber::{Layer, Registry}; /// The values of all the environment variables that matter for configuring a logger. /// Errors are explicitly preserved so that we can share error handling. @@ -72,6 +74,15 @@ impl LoggerConfig { /// Initialize the logger with the given values for the filter, coloring, and other options env variables. pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { + init_logger_with_additional_layer(cfg, Identity::new()) +} + +/// Initialize the logger with the given values for the filter, coloring, and other options env variables. +/// Additionally add a custom layer to collect logging and tracing events. +pub fn init_logger_with_additional_layer( + cfg: LoggerConfig, + additional_tracing_layer: impl Layer + Send + Sync, +) -> Result<(), Error> { let filter = match cfg.filter { Ok(env) => EnvFilter::new(env), _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), @@ -104,7 +115,7 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { }; let mut layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr) + .with_writer(io::stderr as fn() -> io::Stderr) .with_ansi(color_logs) .with_targets(true) .with_verbose_exit(verbose_entry_exit) @@ -124,7 +135,8 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { Err(_) => {} // no wraptree } - let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + let subscriber = + Registry::default().with(additional_tracing_layer).with(layer.with_filter(filter)); match cfg.backtrace { Ok(backtrace_target) => { let fmt_layer = tracing_subscriber::fmt::layer() From fc96ca8bbad7fb4c7546fb98807e826723fc6c1d Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 11 Jun 2025 10:23:43 +0200 Subject: [PATCH 2/3] Use closure to allow passing custom tracing layers The previous method, where a layer would be passed directly, required to pass a "no-op" layer when no custom layer was needed. This should have in theory worked, however having a no-op layer seems to change the way the tracing lib applies filters internally, leading to some debug!() being printed despite them being out of the minimum level for the filters. Note however that this behavior was very inconsistent, and e.g. some debug!() would get printed and some others wouldn't, for no apparent reason. --- compiler/rustc_driver_impl/src/lib.rs | 12 ++++++----- compiler/rustc_log/src/lib.rs | 30 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 83552af5a0ee8..038b93dda0849 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1507,13 +1507,15 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) { } } -pub fn init_logger_with_additional_layer( +pub fn init_logger_with_additional_layer( early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig, - additional_tracing_layer: impl rustc_log::Layer + Send + Sync, -) { - if let Err(error) = rustc_log::init_logger_with_additional_layer(cfg, additional_tracing_layer) - { + build_subscriber: F, +) where + F: FnOnce() -> T, + T: rustc_log::BuildSubscriberRet, +{ + if let Err(error) = rustc_log::init_logger_with_additional_layer(cfg, build_subscriber) { early_dcx.early_fatal(error.to_string()); } } diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 404106e472ce0..8d959002b5658 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -42,7 +42,7 @@ use tracing_core::{Event, Subscriber}; use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; use tracing_subscriber::fmt::FmtContext; use tracing_subscriber::fmt::format::{self, FormatEvent, FormatFields}; -use tracing_subscriber::layer::{Identity, SubscriberExt}; +use tracing_subscriber::layer::SubscriberExt; // Re-export tracing_subscriber items so rustc_driver_impl doesn't need to depend on it. pub use tracing_subscriber::{Layer, Registry}; @@ -74,15 +74,30 @@ impl LoggerConfig { /// Initialize the logger with the given values for the filter, coloring, and other options env variables. pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { - init_logger_with_additional_layer(cfg, Identity::new()) + init_logger_with_additional_layer(cfg, || Registry::default()) +} + +pub trait BuildSubscriberRet: + tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span> + Send + Sync +{ +} + +impl< + T: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span> + Send + Sync, +> BuildSubscriberRet for T +{ } /// Initialize the logger with the given values for the filter, coloring, and other options env variables. /// Additionally add a custom layer to collect logging and tracing events. -pub fn init_logger_with_additional_layer( +pub fn init_logger_with_additional_layer( cfg: LoggerConfig, - additional_tracing_layer: impl Layer + Send + Sync, -) -> Result<(), Error> { + build_subscriber: F, +) -> Result<(), Error> +where + F: FnOnce() -> T, + T: BuildSubscriberRet, +{ let filter = match cfg.filter { Ok(env) => EnvFilter::new(env), _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), @@ -115,7 +130,7 @@ pub fn init_logger_with_additional_layer( }; let mut layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr as fn() -> io::Stderr) + .with_writer(io::stderr) .with_ansi(color_logs) .with_targets(true) .with_verbose_exit(verbose_entry_exit) @@ -135,8 +150,7 @@ pub fn init_logger_with_additional_layer( Err(_) => {} // no wraptree } - let subscriber = - Registry::default().with(additional_tracing_layer).with(layer.with_filter(filter)); + let subscriber = build_subscriber().with(layer.with_filter(filter)); match cfg.backtrace { Ok(backtrace_target) => { let fmt_layer = tracing_subscriber::fmt::layer() From 781baafbe4501e079489f76fdd6fb439252f467d Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 12 Jun 2025 12:09:55 +0200 Subject: [PATCH 3/3] Add documentation for init_logger_with_additional_layer --- compiler/rustc_driver_impl/src/lib.rs | 7 ++++++- compiler/rustc_log/src/lib.rs | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 038b93dda0849..0cd9e36a92771 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1500,13 +1500,18 @@ pub fn init_rustc_env_logger(early_dcx: &EarlyDiagCtxt) { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose -/// the values directly rather than having to set an environment variable. +/// the logger config directly rather than having to set an environment variable. pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) { if let Err(error) = rustc_log::init_logger(cfg) { early_dcx.early_fatal(error.to_string()); } } +/// This allows tools to enable rust logging without having to magically match rustc's +/// tracing crate version. In contrast to `init_rustc_env_logger`, it allows you to +/// choose the logger config directly rather than having to set an environment variable. +/// Moreover, in contrast to `init_logger`, it allows you to add a custom tracing layer +/// via `build_subscriber`, for example `|| Registry::default().with(custom_layer)`. pub fn init_logger_with_additional_layer( early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig, diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 8d959002b5658..df648bbd48951 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -43,8 +43,7 @@ use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; use tracing_subscriber::fmt::FmtContext; use tracing_subscriber::fmt::format::{self, FormatEvent, FormatFields}; use tracing_subscriber::layer::SubscriberExt; -// Re-export tracing_subscriber items so rustc_driver_impl doesn't need to depend on it. -pub use tracing_subscriber::{Layer, Registry}; +use tracing_subscriber::{Layer, Registry}; /// The values of all the environment variables that matter for configuring a logger. /// Errors are explicitly preserved so that we can share error handling. @@ -77,6 +76,11 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { init_logger_with_additional_layer(cfg, || Registry::default()) } +/// Trait alias for the complex return type of `build_subscriber` in +/// [init_logger_with_additional_layer]. A [Registry] with any composition of [tracing::Subscriber]s +/// (e.g. `Registry::default().with(custom_layer)`) should be compatible with this type. +/// Having an alias is also useful so rustc_driver_impl does not need to explicitly depend on +/// `tracing_subscriber`. pub trait BuildSubscriberRet: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span> + Send + Sync { @@ -89,7 +93,8 @@ impl< } /// Initialize the logger with the given values for the filter, coloring, and other options env variables. -/// Additionally add a custom layer to collect logging and tracing events. +/// Additionally add a custom layer to collect logging and tracing events via `build_subscriber`, +/// for example: `|| Registry::default().with(custom_layer)`. pub fn init_logger_with_additional_layer( cfg: LoggerConfig, build_subscriber: F,