From 4a036dd8f50392274a0d6696473fc865e690f898 Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 27 Mar 2024 00:28:01 -0500 Subject: [PATCH] language server: use `tracing` and `tracing-subscriber` --- .cargo/config.toml | 3 + Cargo.lock | 97 +++++++++++++++++++ crates/language-server/Cargo.toml | 3 + crates/language-server/src/backend.rs | 2 +- .../language-server/src/handlers/request.rs | 2 +- crates/language-server/src/language_server.rs | 2 +- crates/language-server/src/logger.rs | 88 ++++++++++------- crates/language-server/src/main.rs | 6 +- crates/language-server/src/util.rs | 2 +- crates/language-server/src/workspace.rs | 2 +- 10 files changed, 161 insertions(+), 46 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..bbfc28a44 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +rustflags = ["--cfg", "tokio_unstable"] + diff --git a/Cargo.lock b/Cargo.lock index f2f185eba..ef2f1757d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,6 +765,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1310,6 +1319,9 @@ dependencies = [ "tokio-macros", "tokio-stream", "tower-lsp", + "tracing", + "tracing-appender", + "tracing-subscriber", "url", "vfs 0.12.0", ] @@ -2272,6 +2284,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.0" @@ -2306,6 +2328,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.45" @@ -2395,6 +2423,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parity-scale-codec" version = "3.4.0" @@ -2561,6 +2595,12 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3592,6 +3632,37 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -3823,6 +3894,18 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.27" @@ -3844,6 +3927,17 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.18" @@ -3851,12 +3945,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", + "nu-ansi-term", "once_cell", "regex", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-log", ] [[package]] diff --git a/crates/language-server/Cargo.toml b/crates/language-server/Cargo.toml index 0351f3845..0b5260b54 100644 --- a/crates/language-server/Cargo.toml +++ b/crates/language-server/Cargo.toml @@ -49,3 +49,6 @@ console-subscriber = "0.2.0" vfs = "0.12.0" rust-embed = "8.3.0" futures-batch = "0.6.1" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +tracing-appender = "0.2.3" diff --git a/crates/language-server/src/backend.rs b/crates/language-server/src/backend.rs index 785cebb02..93fdd526a 100644 --- a/crates/language-server/src/backend.rs +++ b/crates/language-server/src/backend.rs @@ -24,7 +24,7 @@ use crate::globals::LANGUAGE_ID; use crate::language_server::MessageReceivers; use crate::workspace::{IngotFileContext, SyncableInputFile, Workspace}; -use log::info; +use tracing::info; // use tokio_stream::StreamExt; diff --git a/crates/language-server/src/handlers/request.rs b/crates/language-server/src/handlers/request.rs index b5951ec23..483e7d928 100644 --- a/crates/language-server/src/handlers/request.rs +++ b/crates/language-server/src/handlers/request.rs @@ -6,7 +6,7 @@ use hir_analysis::{ name_resolution::{EarlyResolvedPath, NameRes}, HirAnalysisDb, }; -use log::info; +use tracing::info; use salsa::Snapshot; use tokio::sync::RwLock; diff --git a/crates/language-server/src/language_server.rs b/crates/language-server/src/language_server.rs index 843ca47bd..300e23140 100644 --- a/crates/language-server/src/language_server.rs +++ b/crates/language-server/src/language_server.rs @@ -1,9 +1,9 @@ -use log::{error, info}; use lsp_types::{ DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, DidCloseTextDocumentParams, FileSystemWatcher, GlobPattern, InitializeParams, InitializeResult, Registration, }; +use tracing::{error, info}; use tower_lsp::{jsonrpc::Result, Client, LanguageServer}; diff --git a/crates/language-server/src/logger.rs b/crates/language-server/src/logger.rs index a05fdee90..14318f418 100644 --- a/crates/language-server/src/logger.rs +++ b/crates/language-server/src/logger.rs @@ -1,55 +1,69 @@ -use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; +use std::io::Write; + use lsp_types::MessageType; use tokio::task::yield_now; use tower_lsp::Client; +use tracing_subscriber::fmt::writer::MakeWriterExt; +use tracing_subscriber::fmt::MakeWriter; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::prelude::*; -pub struct Logger { - pub(crate) level: Level, +pub async fn handle_log_messages( + mut rx: tokio::sync::mpsc::UnboundedReceiver<(String, MessageType)>, + client: Client, +) -> tokio::sync::mpsc::UnboundedReceiver { + loop { + if let Some((message, message_type)) = rx.recv().await { + client.log_message(message_type, message).await; + yield_now().await; + } + } +} + +#[derive(Clone)] +pub struct LoggerLayer { log_sender: tokio::sync::mpsc::UnboundedSender<(String, MessageType)>, } -impl log::Log for Logger { - fn enabled(&self, metadata: &Metadata) -> bool { - let logger = self; - metadata.level() <= logger.level +impl Write for LoggerLayer { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let message = String::from_utf8_lossy(buf).to_string(); + let _ = self.log_sender.send((message, MessageType::LOG)); + Ok(buf.len()) } - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - let message = format!("{} - {}", record.level(), record.args()); - let message_type = match record.level() { - log::Level::Error => MessageType::ERROR, - log::Level::Warn => MessageType::WARNING, - log::Level::Info => MessageType::INFO, - log::Level::Debug => MessageType::LOG, - log::Level::Trace => MessageType::LOG, - }; - self.log_sender.send((message, message_type)).unwrap(); - } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) } +} - fn flush(&self) {} +impl MakeWriter<'_> for LoggerLayer { + type Writer = Self; + fn make_writer(&self) -> Self::Writer { + self.clone() + } } pub fn setup_logger( - level: Level, -) -> Result, SetLoggerError> { + level: tracing::Level, +) -> Result, Box> +{ let (log_sender, log_receiver) = tokio::sync::mpsc::unbounded_channel::<(String, MessageType)>(); - let logger = Logger { level, log_sender }; - let static_logger = Box::leak(Box::new(logger)); - log::set_logger(static_logger)?; - log::set_max_level(LevelFilter::Debug); - Ok(log_receiver) -} + let logger = LoggerLayer { log_sender }; + let logger = logger.with_max_level(level); -pub async fn handle_log_messages( - mut rx: tokio::sync::mpsc::UnboundedReceiver<(String, MessageType)>, - client: Client, -) -> tokio::sync::mpsc::UnboundedReceiver { - loop { - let (message, message_type) = rx.recv().await.unwrap(); - client.log_message(message_type, message).await; - yield_now().await; - } + let pretty_logger = tracing_subscriber::fmt::layer() + .event_format(tracing_subscriber::fmt::format::format().pretty()) + .with_ansi(false) + .with_writer(logger); + + let console_layer = console_subscriber::spawn(); + + tracing_subscriber::registry() + .with(pretty_logger) + .with(console_layer) + .init(); + + Ok(log_receiver) } diff --git a/crates/language-server/src/main.rs b/crates/language-server/src/main.rs index 26b66553f..e07c86cec 100644 --- a/crates/language-server/src/main.rs +++ b/crates/language-server/src/main.rs @@ -12,6 +12,7 @@ mod workspace; use backend::Backend; use db::Jar; +use tracing::Level; use language_server::Server; @@ -25,9 +26,8 @@ mod handlers { async fn main() { let stdin = tokio::io::stdin(); let stdout = tokio::io::stdout(); - console_subscriber::init(); + let rx = setup_logger(Level::INFO).unwrap(); - // let message_channels = language_server::MessageChannels::new(); let (message_senders, message_receivers) = language_server::setup_message_channels(); let (service, socket) = tower_lsp::LspService::build(|client| Server::new(client, message_senders)).finish(); @@ -36,8 +36,6 @@ async fn main() { let client = server.client.clone(); let backend = Backend::new(client, message_receivers); - let rx = setup_logger(log::Level::Info).unwrap(); - // separate runtime for the backend // let backend_runtime = tokio::runtime::Builder::new_multi_thread() // .worker_threads(4) diff --git a/crates/language-server/src/util.rs b/crates/language-server/src/util.rs index eb7e393c3..b76278814 100644 --- a/crates/language-server/src/util.rs +++ b/crates/language-server/src/util.rs @@ -4,8 +4,8 @@ use common::{ }; use fxhash::FxHashMap; use hir::{hir_def::scope_graph::ScopeId, span::LazySpan, SpannedHirDb}; -use log::error; use lsp_types::Position; +use tracing::error; use url::Url; pub fn calculate_line_offsets(text: &str) -> Vec { diff --git a/crates/language-server/src/workspace.rs b/crates/language-server/src/workspace.rs index 21420a4a2..2dd8c087d 100644 --- a/crates/language-server/src/workspace.rs +++ b/crates/language-server/src/workspace.rs @@ -10,8 +10,8 @@ use common::{ InputFile, InputIngot, }; use hir::{hir_def::TopLevelMod, lower::map_file_to_mod, LowerHirDb}; -use log::info; use patricia_tree::StringPatriciaMap; +use tracing::info; use crate::db::LanguageServerDatabase;