From 0d74252537b6fd3ae6287486dbeec437cf021efa Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 12 May 2025 16:27:09 +0200 Subject: Allow initializing logger with additional tracing Layer --- compiler/rustc_log/src/lib.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'compiler/rustc_log/src') diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 1bb502ca3d0..404106e472c 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() -- cgit 1.4.1-3-g733a5 From fc96ca8bbad7fb4c7546fb98807e826723fc6c1d Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 11 Jun 2025 10:23:43 +0200 Subject: 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(-) (limited to 'compiler/rustc_log/src') diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 83552af5a0e..038b93dda08 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 404106e472c..8d959002b56 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() -- cgit 1.4.1-3-g733a5 From 781baafbe4501e079489f76fdd6fb439252f467d Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 12 Jun 2025 12:09:55 +0200 Subject: 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(-) (limited to 'compiler/rustc_log/src') diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 038b93dda08..0cd9e36a927 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 8d959002b56..df648bbd489 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, -- cgit 1.4.1-3-g733a5