diff --git a/Cargo.toml b/Cargo.toml index dba9c8df68cc..5802540c36bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -280,7 +280,7 @@ tower = "0.4" tower-layer = "0.3.1" tower-service = "0.3.2" tracing = "0.1.22" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } triomphe = "0.1.11" trybuild = "1.0.56" twox-hash = "1.6.1" diff --git a/integrations/rust-project/src/cli/develop.rs b/integrations/rust-project/src/cli/develop.rs index 0407a5fe43a6..8f973012962f 100644 --- a/integrations/rust-project/src/cli/develop.rs +++ b/integrations/rust-project/src/cli/develop.rs @@ -80,6 +80,7 @@ impl Develop { relative_paths, mode, check_cycles, + log_json: _, } = command { let out = if stdout { diff --git a/integrations/rust-project/src/main.rs b/integrations/rust-project/src/main.rs index 8429dbe3c4a3..bb9f5a8b98f3 100644 --- a/integrations/rust-project/src/main.rs +++ b/integrations/rust-project/src/main.rs @@ -24,9 +24,9 @@ use std::path::PathBuf; use clap::ArgAction; use clap::Parser; use clap::Subcommand; +use progress::ProgressLayer; use tracing_subscriber::filter::LevelFilter; use tracing_subscriber::layer::SubscriberExt; -use tracing_subscriber::reload; use tracing_subscriber::EnvFilter; use tracing_subscriber::Layer; @@ -79,6 +79,10 @@ enum Command { #[clap(long = "stdout", conflicts_with = "out")] stdout: bool, + /// Log in a JSON format. + #[clap(long, default_value = "false")] + log_json: bool, + /// Use a `rustup`-managed sysroot instead of a `.buckconfig`-managed sysroot. /// /// This option requires the presence of `rustc` in the `$PATH`, as rust-project @@ -123,46 +127,79 @@ enum Command { } fn main() -> Result<(), anyhow::Error> { + let opt = Opt::parse(); + let filter = EnvFilter::builder() .with_default_directive(LevelFilter::INFO.into()) .from_env()?; - let fmt = tracing_subscriber::fmt::layer() - .with_ansi(io::stderr().is_terminal()) - .with_writer(io::stderr); - - let (layer, reload_handle) = reload::Layer::new(vec![fmt.with_filter(filter).boxed()]); - - let subscriber = tracing_subscriber::registry().with(layer); - tracing::subscriber::set_global_default(subscriber)?; - - let cli = Opt::parse(); - - if cli.version { + if opt.version { println!("{}", build_info()); return Ok(()); } - let Some(command) = cli.command else { + let Some(command) = opt.command else { eprintln!("Expected a subcommand, see --help for more information."); return Ok(()); }; + let fmt = tracing_subscriber::fmt::layer() + .with_ansi(io::stderr().is_terminal()) + .with_writer(io::stderr); + match command { - Command::New { name, kind, path } => cli::New { name, kind, path }.run(), - Command::Check { - mode, - use_clippy, - saved_file, - } => cli::Check::new(mode, use_clippy, saved_file).run(), - c @ Command::Develop { .. } => { + c @ Command::Develop { log_json, .. } => { + if log_json { + let subscriber = + tracing_subscriber::registry().with(fmt.json().with_filter(filter)); + tracing::subscriber::set_global_default(subscriber)?; + } else { + let subscriber = tracing_subscriber::registry().with(fmt.with_filter(filter)); + tracing::subscriber::set_global_default(subscriber)?; + }; + let (develop, input, out) = cli::Develop::from_command(c); - develop.run_as_cli(input, out) + match develop.run_as_cli(input, out) { + Ok(_) => Ok(()), + Err(e) => { + tracing::error!( + error = >::as_ref(&e), + source = e.source() + ); + Ok(()) + } + } } Command::LspServer => { - let state = server::State::new(reload_handle)?; + let state = server::State::new()?; + let sender = state.server.sender.clone(); + + let progress = ProgressLayer::new(sender); + + let subscriber = tracing_subscriber::registry() + .with(fmt.with_filter(filter)) + .with(progress); + tracing::subscriber::set_global_default(subscriber)?; + state.run() } + Command::New { name, kind, path } => { + let subscriber = tracing_subscriber::registry().with(fmt.with_filter(filter)); + tracing::subscriber::set_global_default(subscriber)?; + + cli::New { name, kind, path }.run() + } + Command::Check { + mode, + use_clippy, + saved_file, + } => { + let subscriber = tracing_subscriber::registry().with(fmt.with_filter(filter)); + tracing::subscriber::set_global_default(subscriber)?; + cli::Check::new(mode, use_clippy, saved_file).run() + } } } diff --git a/integrations/rust-project/src/server.rs b/integrations/rust-project/src/server.rs index f546ee211b7b..96d72e8e9689 100644 --- a/integrations/rust-project/src/server.rs +++ b/integrations/rust-project/src/server.rs @@ -25,26 +25,20 @@ use serde::Deserialize; use serde::Serialize; use tracing::info; use tracing::warn; -use tracing_subscriber::reload::Handle; -use tracing_subscriber::Layer; -use tracing_subscriber::Registry; use crate::cli::Develop; use crate::json_project::Crate; use crate::json_project::JsonProject; -use crate::progress::ProgressLayer; use crate::target::Target; pub(crate) struct State { - server: Server, + pub(crate) server: Server, projects: Vec, io_threads: IoThreads, } impl State { - pub(crate) fn new( - handle: Handle + Send + Sync + 'static>>, Registry>, - ) -> Result { + pub(crate) fn new() -> Result { let (connection, io_threads) = Connection::stdio(); // Run the server and wait for the two threads to end (typically by trigger LSP Exit event). @@ -62,13 +56,6 @@ impl State { req_queue: ReqQueue::default(), }; - handle - .modify(|layers| { - let progress = ProgressLayer::new(sender); - layers.push(progress.boxed()) - }) - .expect("Unable to update subscriber"); - let state = State { server, io_threads, @@ -239,8 +226,8 @@ impl NotificationDispatch<'_> { } } -struct Server { - sender: Sender, +pub(crate) struct Server { + pub(crate) sender: Sender, receiver: Receiver, req_queue: ReqQueue<(String, Instant), ReqHandler>, }