diff --git a/Cargo.lock b/Cargo.lock index 4ae1ab2070e..73d3529b221 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4452,6 +4452,9 @@ dependencies = [ "serde_json", "smallvec 1.6.1", "tempfile", + "tracing", + "tracing-subscriber", + "tracing-tree", ] [[package]] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 1b9a35e6491..44c2c3b1786 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -19,6 +19,13 @@ tempfile = "3" itertools = "0.9" regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } +tracing = "0.1" +tracing-tree = "0.1.6" + +[dependencies.tracing-subscriber] +version = "0.2.13" +default-features = false +features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] [dev-dependencies] expect-test = "1.0" diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d7978c4a022..2c43489e989 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -95,7 +95,19 @@ mod visit_lib; pub fn main() { rustc_driver::set_sigpipe_handler(); rustc_driver::install_ice_hook(); + + // When using CI artifacts (with `download_stage1 = true`), tracing is unconditionally built + // with `--features=static_max_level_info`, which disables almost all rustdoc logging. To avoid + // this, compile our own version of `tracing` that logs all levels. + // NOTE: this compiles both versions of tracing unconditionally, because + // - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and + // - Otherwise, there's no warning that logging is being ignored when `download_stage1 = true`. + // NOTE: The reason this doesn't show double logging when `download_stage1 = false` and + // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one + // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). + init_logging(); rustc_driver::init_env_logger("RUSTDOC_LOG"); + let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() { Some(args) => main_args(&args), _ => Err(ErrorReported), @@ -103,6 +115,68 @@ pub fn main() { process::exit(exit_code); } +fn init_logging() { + use std::io; + + // FIXME remove these and use winapi 0.3 instead + // Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs, rustc_driver/lib.rs + #[cfg(unix)] + fn stdout_isatty() -> bool { + extern crate libc; + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } + } + + #[cfg(windows)] + fn stdout_isatty() -> bool { + extern crate winapi; + use winapi::um::consoleapi::GetConsoleMode; + use winapi::um::processenv::GetStdHandle; + use winapi::um::winbase::STD_OUTPUT_HANDLE; + + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } + } + + let color_logs = match std::env::var("RUSTDOC_LOG_COLOR") { + Ok(value) => match value.as_ref() { + "always" => true, + "never" => false, + "auto" => stdout_isatty(), + _ => early_error( + ErrorOutputType::default(), + &format!( + "invalid log color value '{}': expected one of always, never, or auto", + value + ), + ), + }, + Err(std::env::VarError::NotPresent) => stdout_isatty(), + Err(std::env::VarError::NotUnicode(_value)) => early_error( + ErrorOutputType::default(), + "non-Unicode log color value: expected one of always, never, or auto", + ), + }; + let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); + let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) + .with_indent_lines(true) + .with_ansi(color_logs) + .with_targets(true) + .with_wraparound(10) + .with_verbose_exit(true) + .with_verbose_entry(true) + .with_indent_amount(2); + #[cfg(parallel_compiler)] + let layer = layer.with_thread_ids(true).with_thread_names(true); + + use tracing_subscriber::layer::SubscriberExt; + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); +} + fn get_args() -> Option> { env::args_os() .enumerate()