Skip to content

Commit

Permalink
rust-project: add json logging option; refactor tracing setup
Browse files Browse the repository at this point in the history
Summary: To support rust-lang/rust-analyzer#17246, I've added an argument for logging using JSON to that rust-analyzer can use these fields for progress reporting.

Reviewed By: Wilfred

Differential Revision: D57924551

fbshipit-source-id: 992e9e096fdea1eefe2b199d8dd84be7b247a732
  • Loading branch information
davidbarsky authored and facebook-github-bot committed Jun 6, 2024
1 parent c009cce commit 3349d02
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions integrations/rust-project/src/cli/develop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl Develop {
relative_paths,
mode,
check_cycles,
log_json: _,
} = command
{
let out = if stdout {
Expand Down
83 changes: 60 additions & 23 deletions integrations/rust-project/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 = <anyhow::Error as AsRef<
dyn std::error::Error + Send + Sync + 'static,
>>::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()
}
}
}

Expand Down
21 changes: 4 additions & 17 deletions integrations/rust-project/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<JsonProject>,
io_threads: IoThreads,
}

impl State {
pub(crate) fn new(
handle: Handle<Vec<Box<dyn Layer<Registry> + Send + Sync + 'static>>, Registry>,
) -> Result<Self, anyhow::Error> {
pub(crate) fn new() -> Result<Self, anyhow::Error> {
let (connection, io_threads) = Connection::stdio();

// Run the server and wait for the two threads to end (typically by trigger LSP Exit event).
Expand All @@ -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,
Expand Down Expand Up @@ -239,8 +226,8 @@ impl NotificationDispatch<'_> {
}
}

struct Server {
sender: Sender<lsp_server::Message>,
pub(crate) struct Server {
pub(crate) sender: Sender<lsp_server::Message>,
receiver: Receiver<lsp_server::Message>,
req_queue: ReqQueue<(String, Instant), ReqHandler>,
}
Expand Down

0 comments on commit 3349d02

Please sign in to comment.