Skip to content

Commit 1ceb972

Browse files
Add logging macros for tracing migration (#176)
1 parent 7e9339b commit 1ceb972

File tree

5 files changed

+93
-55
lines changed

5 files changed

+93
-55
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ salsa = "0.23.0"
2323
serde = { version = "1.0.219", features = ["derive"] }
2424
serde_json = "1.0.140"
2525
tempfile = "3.20.0"
26+
thiserror = "2.0.12"
2627
tokio = { version = "1.45.0", features = ["full"] }
2728
toml = "0.9.2"
2829
tower-lsp-server = { version = "0.22.0", features = ["proposed"] }
29-
thiserror = "2.0.12"
30+
tracing = "0.1.41"
31+
tracing-appender = "0.2.3"
32+
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt", "time"] }
3033
which = "8.0.0"
3134

3235
[workspace.lints.clippy]

crates/djls-server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ serde = { workspace = true }
2020
serde_json = { workspace = true }
2121
tokio = { workspace = true }
2222
tower-lsp-server = { workspace = true }
23+
tracing = { workspace = true }
2324

2425
[build-dependencies]
2526
djls-dev = { workspace = true }

crates/djls-server/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod client;
22
mod db;
33
mod documents;
4+
mod logging;
45
mod queue;
56
mod server;
67
mod session;

crates/djls-server/src/logging.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//! Temporary logging macros for dual-dispatch to both LSP client and tracing.
2+
//!
3+
//! These macros bridge the gap during our migration from `client::log_message`
4+
//! to the tracing infrastructure. They ensure messages are sent to both systems
5+
//! so we maintain LSP client visibility while building out tracing support.
6+
//!
7+
//! Each macro supports two invocation patterns to handle the different APIs:
8+
//!
9+
//! 1. String literal:
10+
//! ```rust,ignore
11+
//! log_info!("Server initialized");
12+
//! log_warn!("Configuration not found");
13+
//! log_error!("Failed to parse document");
14+
//! ```
15+
//!
16+
//! 2. Format string with arguments:
17+
//! ```rust,ignore
18+
//! log_info!("Processing {} documents", count);
19+
//! log_warn!("Timeout after {}ms for {}", ms, path);
20+
//! log_error!("Failed to open {}: {}", file, err);
21+
//! ```
22+
//!
23+
//! The difference in the macro arms exists because of how each system works:
24+
//!
25+
//! - `client::log_message` expects a single string value
26+
//! - `tracing` macros can handle format strings natively for structured logging
27+
//! - For format strings, we format once for the client but pass the original
28+
//! format string and args to tracing to preserve structured data
29+
30+
#[macro_export]
31+
macro_rules! log_info {
32+
($msg:literal) => {
33+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, $msg);
34+
tracing::info!($msg);
35+
};
36+
($fmt:literal, $($arg:tt)*) => {
37+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, format!($fmt, $($arg)*));
38+
tracing::info!($fmt, $($arg)*);
39+
};
40+
}
41+
42+
#[macro_export]
43+
macro_rules! log_warn {
44+
($msg:literal) => {
45+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, $msg);
46+
tracing::warn!($msg);
47+
};
48+
($fmt:literal, $($arg:tt)*) => {
49+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, format!($fmt, $($arg)*));
50+
tracing::warn!($fmt, $($arg)*);
51+
};
52+
}
53+
54+
#[macro_export]
55+
macro_rules! log_error {
56+
($msg:literal) => {
57+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, $msg);
58+
tracing::error!($msg);
59+
};
60+
($fmt:literal, $($arg:tt)*) => {
61+
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, format!($fmt, $($arg)*));
62+
tracing::error!($fmt, $($arg)*);
63+
};
64+
}

crates/djls-server/src/server.rs

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use tower_lsp_server::lsp_types::DidOpenTextDocumentParams;
1313
use tower_lsp_server::lsp_types::InitializeParams;
1414
use tower_lsp_server::lsp_types::InitializeResult;
1515
use tower_lsp_server::lsp_types::InitializedParams;
16-
use tower_lsp_server::lsp_types::MessageType;
1716
use tower_lsp_server::lsp_types::OneOf;
1817
use tower_lsp_server::lsp_types::SaveOptions;
1918
use tower_lsp_server::lsp_types::ServerCapabilities;
@@ -25,7 +24,8 @@ use tower_lsp_server::lsp_types::WorkspaceFoldersServerCapabilities;
2524
use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
2625
use tower_lsp_server::LanguageServer;
2726

28-
use crate::client;
27+
use crate::log_error;
28+
use crate::log_info;
2929
use crate::queue::Queue;
3030
use crate::session::Session;
3131

@@ -55,10 +55,7 @@ impl DjangoLanguageServer {
5555
if let Some(s) = &*session {
5656
f(s)
5757
} else {
58-
client::log_message(
59-
MessageType::ERROR,
60-
"Attempted to access session before initialization",
61-
);
58+
log_error!("Attempted to access session before initialization");
6259
R::default()
6360
}
6461
}
@@ -72,10 +69,7 @@ impl DjangoLanguageServer {
7269
if let Some(s) = &mut *session {
7370
f(s)
7471
} else {
75-
client::log_message(
76-
MessageType::ERROR,
77-
"Attempted to access session before initialization",
78-
);
72+
log_error!("Attempted to access session before initialization");
7973
R::default()
8074
}
8175
}
@@ -88,16 +82,16 @@ impl DjangoLanguageServer {
8882
let session_arc = Arc::clone(&self.session);
8983

9084
if let Err(e) = self.queue.submit(async move { f(session_arc).await }).await {
91-
client::log_message(MessageType::ERROR, format!("Failed to submit task: {e}"));
85+
log_error!("Failed to submit task: {}", e);
9286
} else {
93-
client::log_message(MessageType::INFO, "Task submitted successfully");
87+
log_info!("Task submitted successfully");
9488
}
9589
}
9690
}
9791

9892
impl LanguageServer for DjangoLanguageServer {
9993
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
100-
client::log_message(MessageType::INFO, "Initializing server...");
94+
log_info!("Initializing server...");
10195

10296
let session = Session::new(&params);
10397

@@ -145,10 +139,7 @@ impl LanguageServer for DjangoLanguageServer {
145139

146140
#[allow(clippy::too_many_lines)]
147141
async fn initialized(&self, _params: InitializedParams) {
148-
client::log_message(
149-
MessageType::INFO,
150-
"Server received initialized notification.",
151-
);
142+
log_info!("Server received initialized notification.");
152143

153144
self.with_session_task(|session_arc| async move {
154145
let project_path_and_venv = {
@@ -168,16 +159,13 @@ impl LanguageServer for DjangoLanguageServer {
168159
};
169160

170161
if let Some((path_display, venv_path)) = project_path_and_venv {
171-
client::log_message(
172-
MessageType::INFO,
173-
format!("Task: Starting initialization for project at: {path_display}"),
162+
log_info!(
163+
"Task: Starting initialization for project at: {}",
164+
path_display
174165
);
175166

176167
if let Some(ref path) = venv_path {
177-
client::log_message(
178-
MessageType::INFO,
179-
format!("Using virtual environment from config: {path}"),
180-
);
168+
log_info!("Using virtual environment from config: {}", path);
181169
}
182170

183171
let init_result = {
@@ -197,17 +185,13 @@ impl LanguageServer for DjangoLanguageServer {
197185

198186
match init_result {
199187
Ok(()) => {
200-
client::log_message(
201-
MessageType::INFO,
202-
format!("Task: Successfully initialized project: {path_display}"),
203-
);
188+
log_info!("Task: Successfully initialized project: {}", path_display);
204189
}
205190
Err(e) => {
206-
client::log_message(
207-
MessageType::ERROR,
208-
format!(
209-
"Task: Failed to initialize Django project at {path_display}: {e}"
210-
),
191+
log_error!(
192+
"Task: Failed to initialize Django project at {}: {}",
193+
path_display,
194+
e
211195
);
212196

213197
// Clear project on error
@@ -218,10 +202,7 @@ impl LanguageServer for DjangoLanguageServer {
218202
}
219203
}
220204
} else {
221-
client::log_message(
222-
MessageType::INFO,
223-
"Task: No project instance found to initialize.",
224-
);
205+
log_info!("Task: No project instance found to initialize.");
225206
}
226207
Ok(())
227208
})
@@ -233,10 +214,7 @@ impl LanguageServer for DjangoLanguageServer {
233214
}
234215

235216
async fn did_open(&self, params: DidOpenTextDocumentParams) {
236-
client::log_message(
237-
MessageType::INFO,
238-
format!("Opened document: {:?}", params.text_document.uri),
239-
);
217+
log_info!("Opened document: {:?}", params.text_document.uri);
240218

241219
self.with_session_mut(|session| {
242220
let db = session.db();
@@ -246,10 +224,7 @@ impl LanguageServer for DjangoLanguageServer {
246224
}
247225

248226
async fn did_change(&self, params: DidChangeTextDocumentParams) {
249-
client::log_message(
250-
MessageType::INFO,
251-
format!("Changed document: {:?}", params.text_document.uri),
252-
);
227+
log_info!("Changed document: {:?}", params.text_document.uri);
253228

254229
self.with_session_mut(|session| {
255230
let db = session.db();
@@ -259,10 +234,7 @@ impl LanguageServer for DjangoLanguageServer {
259234
}
260235

261236
async fn did_close(&self, params: DidCloseTextDocumentParams) {
262-
client::log_message(
263-
MessageType::INFO,
264-
format!("Closed document: {:?}", params.text_document.uri),
265-
);
237+
log_info!("Closed document: {:?}", params.text_document.uri);
266238

267239
self.with_session_mut(|session| {
268240
session.documents_mut().handle_did_close(&params);
@@ -290,10 +262,7 @@ impl LanguageServer for DjangoLanguageServer {
290262
}
291263

292264
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
293-
client::log_message(
294-
MessageType::INFO,
295-
"Configuration change detected. Reloading settings...",
296-
);
265+
log_info!("Configuration change detected. Reloading settings...");
297266

298267
let project_path = self
299268
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
@@ -305,7 +274,7 @@ impl LanguageServer for DjangoLanguageServer {
305274
session.set_settings(new_settings);
306275
}
307276
Err(e) => {
308-
client::log_message(MessageType::ERROR, format!("Error loading settings: {e}"));
277+
log_error!("Error loading settings: {}", e);
309278
}
310279
})
311280
.await;

0 commit comments

Comments
 (0)