mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-04 09:20:41 +00:00
Add logging macros for tracing migration (#176)
This commit is contained in:
parent
7e9339ba86
commit
1ceb972f0e
5 changed files with 93 additions and 55 deletions
|
@ -23,10 +23,13 @@ salsa = "0.23.0"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
tempfile = "3.20.0"
|
tempfile = "3.20.0"
|
||||||
|
thiserror = "2.0.12"
|
||||||
tokio = { version = "1.45.0", features = ["full"] }
|
tokio = { version = "1.45.0", features = ["full"] }
|
||||||
toml = "0.9.2"
|
toml = "0.9.2"
|
||||||
tower-lsp-server = { version = "0.22.0", features = ["proposed"] }
|
tower-lsp-server = { version = "0.22.0", features = ["proposed"] }
|
||||||
thiserror = "2.0.12"
|
tracing = "0.1.41"
|
||||||
|
tracing-appender = "0.2.3"
|
||||||
|
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt", "time"] }
|
||||||
which = "8.0.0"
|
which = "8.0.0"
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
[workspace.lints.clippy]
|
||||||
|
|
|
@ -20,6 +20,7 @@ serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tower-lsp-server = { workspace = true }
|
tower-lsp-server = { workspace = true }
|
||||||
|
tracing = { workspace = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
djls-dev = { workspace = true }
|
djls-dev = { workspace = true }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod client;
|
mod client;
|
||||||
mod db;
|
mod db;
|
||||||
mod documents;
|
mod documents;
|
||||||
|
mod logging;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod server;
|
mod server;
|
||||||
mod session;
|
mod session;
|
||||||
|
|
64
crates/djls-server/src/logging.rs
Normal file
64
crates/djls-server/src/logging.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
//! Temporary logging macros for dual-dispatch to both LSP client and tracing.
|
||||||
|
//!
|
||||||
|
//! These macros bridge the gap during our migration from `client::log_message`
|
||||||
|
//! to the tracing infrastructure. They ensure messages are sent to both systems
|
||||||
|
//! so we maintain LSP client visibility while building out tracing support.
|
||||||
|
//!
|
||||||
|
//! Each macro supports two invocation patterns to handle the different APIs:
|
||||||
|
//!
|
||||||
|
//! 1. String literal:
|
||||||
|
//! ```rust,ignore
|
||||||
|
//! log_info!("Server initialized");
|
||||||
|
//! log_warn!("Configuration not found");
|
||||||
|
//! log_error!("Failed to parse document");
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! 2. Format string with arguments:
|
||||||
|
//! ```rust,ignore
|
||||||
|
//! log_info!("Processing {} documents", count);
|
||||||
|
//! log_warn!("Timeout after {}ms for {}", ms, path);
|
||||||
|
//! log_error!("Failed to open {}: {}", file, err);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The difference in the macro arms exists because of how each system works:
|
||||||
|
//!
|
||||||
|
//! - `client::log_message` expects a single string value
|
||||||
|
//! - `tracing` macros can handle format strings natively for structured logging
|
||||||
|
//! - For format strings, we format once for the client but pass the original
|
||||||
|
//! format string and args to tracing to preserve structured data
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_info {
|
||||||
|
($msg:literal) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, $msg);
|
||||||
|
tracing::info!($msg);
|
||||||
|
};
|
||||||
|
($fmt:literal, $($arg:tt)*) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, format!($fmt, $($arg)*));
|
||||||
|
tracing::info!($fmt, $($arg)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_warn {
|
||||||
|
($msg:literal) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, $msg);
|
||||||
|
tracing::warn!($msg);
|
||||||
|
};
|
||||||
|
($fmt:literal, $($arg:tt)*) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, format!($fmt, $($arg)*));
|
||||||
|
tracing::warn!($fmt, $($arg)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_error {
|
||||||
|
($msg:literal) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, $msg);
|
||||||
|
tracing::error!($msg);
|
||||||
|
};
|
||||||
|
($fmt:literal, $($arg:tt)*) => {
|
||||||
|
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, format!($fmt, $($arg)*));
|
||||||
|
tracing::error!($fmt, $($arg)*);
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,7 +13,6 @@ use tower_lsp_server::lsp_types::DidOpenTextDocumentParams;
|
||||||
use tower_lsp_server::lsp_types::InitializeParams;
|
use tower_lsp_server::lsp_types::InitializeParams;
|
||||||
use tower_lsp_server::lsp_types::InitializeResult;
|
use tower_lsp_server::lsp_types::InitializeResult;
|
||||||
use tower_lsp_server::lsp_types::InitializedParams;
|
use tower_lsp_server::lsp_types::InitializedParams;
|
||||||
use tower_lsp_server::lsp_types::MessageType;
|
|
||||||
use tower_lsp_server::lsp_types::OneOf;
|
use tower_lsp_server::lsp_types::OneOf;
|
||||||
use tower_lsp_server::lsp_types::SaveOptions;
|
use tower_lsp_server::lsp_types::SaveOptions;
|
||||||
use tower_lsp_server::lsp_types::ServerCapabilities;
|
use tower_lsp_server::lsp_types::ServerCapabilities;
|
||||||
|
@ -25,7 +24,8 @@ use tower_lsp_server::lsp_types::WorkspaceFoldersServerCapabilities;
|
||||||
use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
|
use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
|
||||||
use tower_lsp_server::LanguageServer;
|
use tower_lsp_server::LanguageServer;
|
||||||
|
|
||||||
use crate::client;
|
use crate::log_error;
|
||||||
|
use crate::log_info;
|
||||||
use crate::queue::Queue;
|
use crate::queue::Queue;
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
|
|
||||||
|
@ -55,10 +55,7 @@ impl DjangoLanguageServer {
|
||||||
if let Some(s) = &*session {
|
if let Some(s) = &*session {
|
||||||
f(s)
|
f(s)
|
||||||
} else {
|
} else {
|
||||||
client::log_message(
|
log_error!("Attempted to access session before initialization");
|
||||||
MessageType::ERROR,
|
|
||||||
"Attempted to access session before initialization",
|
|
||||||
);
|
|
||||||
R::default()
|
R::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,10 +69,7 @@ impl DjangoLanguageServer {
|
||||||
if let Some(s) = &mut *session {
|
if let Some(s) = &mut *session {
|
||||||
f(s)
|
f(s)
|
||||||
} else {
|
} else {
|
||||||
client::log_message(
|
log_error!("Attempted to access session before initialization");
|
||||||
MessageType::ERROR,
|
|
||||||
"Attempted to access session before initialization",
|
|
||||||
);
|
|
||||||
R::default()
|
R::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,16 +82,16 @@ impl DjangoLanguageServer {
|
||||||
let session_arc = Arc::clone(&self.session);
|
let session_arc = Arc::clone(&self.session);
|
||||||
|
|
||||||
if let Err(e) = self.queue.submit(async move { f(session_arc).await }).await {
|
if let Err(e) = self.queue.submit(async move { f(session_arc).await }).await {
|
||||||
client::log_message(MessageType::ERROR, format!("Failed to submit task: {e}"));
|
log_error!("Failed to submit task: {}", e);
|
||||||
} else {
|
} else {
|
||||||
client::log_message(MessageType::INFO, "Task submitted successfully");
|
log_info!("Task submitted successfully");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageServer for DjangoLanguageServer {
|
impl LanguageServer for DjangoLanguageServer {
|
||||||
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
|
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
|
||||||
client::log_message(MessageType::INFO, "Initializing server...");
|
log_info!("Initializing server...");
|
||||||
|
|
||||||
let session = Session::new(¶ms);
|
let session = Session::new(¶ms);
|
||||||
|
|
||||||
|
@ -145,10 +139,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
async fn initialized(&self, _params: InitializedParams) {
|
async fn initialized(&self, _params: InitializedParams) {
|
||||||
client::log_message(
|
log_info!("Server received initialized notification.");
|
||||||
MessageType::INFO,
|
|
||||||
"Server received initialized notification.",
|
|
||||||
);
|
|
||||||
|
|
||||||
self.with_session_task(|session_arc| async move {
|
self.with_session_task(|session_arc| async move {
|
||||||
let project_path_and_venv = {
|
let project_path_and_venv = {
|
||||||
|
@ -168,16 +159,13 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((path_display, venv_path)) = project_path_and_venv {
|
if let Some((path_display, venv_path)) = project_path_and_venv {
|
||||||
client::log_message(
|
log_info!(
|
||||||
MessageType::INFO,
|
"Task: Starting initialization for project at: {}",
|
||||||
format!("Task: Starting initialization for project at: {path_display}"),
|
path_display
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref path) = venv_path {
|
if let Some(ref path) = venv_path {
|
||||||
client::log_message(
|
log_info!("Using virtual environment from config: {}", path);
|
||||||
MessageType::INFO,
|
|
||||||
format!("Using virtual environment from config: {path}"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let init_result = {
|
let init_result = {
|
||||||
|
@ -197,17 +185,13 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
|
|
||||||
match init_result {
|
match init_result {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
client::log_message(
|
log_info!("Task: Successfully initialized project: {}", path_display);
|
||||||
MessageType::INFO,
|
|
||||||
format!("Task: Successfully initialized project: {path_display}"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
client::log_message(
|
log_error!(
|
||||||
MessageType::ERROR,
|
"Task: Failed to initialize Django project at {}: {}",
|
||||||
format!(
|
path_display,
|
||||||
"Task: Failed to initialize Django project at {path_display}: {e}"
|
e
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clear project on error
|
// Clear project on error
|
||||||
|
@ -218,10 +202,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client::log_message(
|
log_info!("Task: No project instance found to initialize.");
|
||||||
MessageType::INFO,
|
|
||||||
"Task: No project instance found to initialize.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -233,10 +214,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_open(&self, params: DidOpenTextDocumentParams) {
|
async fn did_open(&self, params: DidOpenTextDocumentParams) {
|
||||||
client::log_message(
|
log_info!("Opened document: {:?}", params.text_document.uri);
|
||||||
MessageType::INFO,
|
|
||||||
format!("Opened document: {:?}", params.text_document.uri),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
let db = session.db();
|
let db = session.db();
|
||||||
|
@ -246,10 +224,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||||
client::log_message(
|
log_info!("Changed document: {:?}", params.text_document.uri);
|
||||||
MessageType::INFO,
|
|
||||||
format!("Changed document: {:?}", params.text_document.uri),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
let db = session.db();
|
let db = session.db();
|
||||||
|
@ -259,10 +234,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_close(&self, params: DidCloseTextDocumentParams) {
|
async fn did_close(&self, params: DidCloseTextDocumentParams) {
|
||||||
client::log_message(
|
log_info!("Closed document: {:?}", params.text_document.uri);
|
||||||
MessageType::INFO,
|
|
||||||
format!("Closed document: {:?}", params.text_document.uri),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
session.documents_mut().handle_did_close(¶ms);
|
session.documents_mut().handle_did_close(¶ms);
|
||||||
|
@ -290,10 +262,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
|
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
|
||||||
client::log_message(
|
log_info!("Configuration change detected. Reloading settings...");
|
||||||
MessageType::INFO,
|
|
||||||
"Configuration change detected. Reloading settings...",
|
|
||||||
);
|
|
||||||
|
|
||||||
let project_path = self
|
let project_path = self
|
||||||
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
|
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
|
||||||
|
@ -305,7 +274,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
session.set_settings(new_settings);
|
session.set_settings(new_settings);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
client::log_message(MessageType::ERROR, format!("Error loading settings: {e}"));
|
log_error!("Error loading settings: {}", e);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue