Skip to content

Commit d0c745f

Browse files
Finish basic logging setup with tracing (#181)
1 parent bdb562e commit d0c745f

File tree

3 files changed

+30
-91
lines changed

3 files changed

+30
-91
lines changed

crates/djls-dev/src/bin/djls-tmux.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,23 @@ fn main() -> Result<()> {
3636
)?;
3737

3838
// Split the right pane horizontally for server logs (50/50 split)
39+
// Updated to handle dated log files properly
3940
writeln!(
4041
stdin,
41-
"split-window -t djls-debug:0.1 -v -p 50 'tail -f /tmp/djls.log'"
42+
r#"split-window -t djls-debug:0.1 -v -p 50 'bash -c "log=\$(ls -t /tmp/djls.log.* 2>/dev/null | head -1); if [ -z \"\$log\" ]; then echo \"Waiting for server logs...\"; while [ -z \"\$log\" ]; do sleep 1; log=\$(ls -t /tmp/djls.log.* 2>/dev/null | head -1); done; fi; echo \"Tailing \$log\"; tail -F \"\$log\""'"#
4243
)?;
4344

4445
// Set pane titles
4546
writeln!(stdin, "select-pane -t djls-debug:0.0 -T 'Editor'")?;
46-
writeln!(stdin, "select-pane -t djls-debug:0.1 -T 'LSP DevTools'")?;
47+
writeln!(stdin, "select-pane -t djls-debug:0.1 -T 'LSP Messages'")?;
4748
writeln!(stdin, "select-pane -t djls-debug:0.2 -T 'Server Logs'")?;
4849

4950
// Enable pane borders with titles at the top
5051
writeln!(stdin, "set -t djls-debug pane-border-status top")?;
5152

53+
// Enable mouse support for scrolling and pane interaction
54+
writeln!(stdin, "set -t djls-debug mouse on")?;
55+
5256
// Add custom keybind to kill session (capital K)
5357
writeln!(stdin, "bind-key K kill-session")?;
5458

@@ -64,9 +68,9 @@ fn main() -> Result<()> {
6468
writeln!(stdin, "set -t djls-debug status-left '[#S] '")?;
6569
writeln!(stdin, "set -t djls-debug status-left-length 20")?;
6670

67-
// Right side: keybind hints
68-
writeln!(stdin, "set -t djls-debug status-right ' C-b d: detach | C-b K: kill session | C-b x: kill pane | C-b z: zoom | C-b ?: help '")?;
69-
writeln!(stdin, "set -t djls-debug status-right-length 90")?;
71+
// Right side: keybind hints - updated to include mouse info
72+
writeln!(stdin, "set -t djls-debug status-right ' Mouse: scroll/click | C-b d: detach | C-b K: kill | C-b x: kill pane | C-b z: zoom | C-b ?: help '")?;
73+
writeln!(stdin, "set -t djls-debug status-right-length 120")?;
7074

7175
// Center: window name
7276
writeln!(stdin, "set -t djls-debug status-justify centre")?;

crates/djls-server/src/logging.rs

Lines changed: 5 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
//! Logging infrastructure bridging tracing events to LSP client messages.
1+
//! Logging infrastructure for forwarding tracing events to LSP client messages.
22
//!
3-
//! This module provides both temporary dual-dispatch macros and the permanent
4-
//! `LspLayer` implementation for forwarding tracing events to the LSP client.
3+
//! This module provides the `LspLayer` implementation for forwarding tracing
4+
//! events to the LSP client through the tracing infrastructure.
55
//!
66
//! ## `LspLayer`
77
//!
@@ -10,34 +10,8 @@
1010
//! - ERROR, WARN, INFO, DEBUG → forwarded to LSP client
1111
//! - TRACE → kept server-side only (for performance)
1212
//!
13-
//! ## Temporary Macros
14-
//!
15-
//! These macros bridge the gap during our migration from `client::log_message`
16-
//! to the tracing infrastructure. They ensure messages are sent to both systems
17-
//! so we maintain LSP client visibility while building out tracing support.
18-
//!
19-
//! Each macro supports two invocation patterns to handle the different APIs:
20-
//!
21-
//! 1. String literal:
22-
//! ```rust,ignore
23-
//! log_info!("Server initialized");
24-
//! log_warn!("Configuration not found");
25-
//! log_error!("Failed to parse document");
26-
//! ```
27-
//!
28-
//! 2. Format string with arguments:
29-
//! ```rust,ignore
30-
//! log_info!("Processing {} documents", count);
31-
//! log_warn!("Timeout after {}ms for {}", ms, path);
32-
//! log_error!("Failed to open {}: {}", file, err);
33-
//! ```
34-
//!
35-
//! The difference in the macro arms exists because of how each system works:
36-
//!
37-
//! - `client::log_message` expects a single string value
38-
//! - `tracing` macros can handle format strings natively for structured logging
39-
//! - For format strings, we format once for the client but pass the original
40-
//! format string and args to tracing to preserve structured data
13+
//! The `LspLayer` automatically handles forwarding appropriate log levels
14+
//! to the LSP client while preserving structured logging data for file output.
4115
4216
use std::sync::Arc;
4317

@@ -72,7 +46,6 @@ impl LspLayer {
7246
}
7347
}
7448

75-
/// Visitor that extracts the message field from tracing events.
7649
struct MessageVisitor {
7750
message: Option<String>,
7851
}
@@ -162,39 +135,3 @@ where
162135

163136
guard
164137
}
165-
166-
#[macro_export]
167-
macro_rules! log_info {
168-
($msg:literal) => {
169-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, $msg);
170-
tracing::info!($msg);
171-
};
172-
($fmt:literal, $($arg:tt)*) => {
173-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::INFO, format!($fmt, $($arg)*));
174-
tracing::info!($fmt, $($arg)*);
175-
};
176-
}
177-
178-
#[macro_export]
179-
macro_rules! log_warn {
180-
($msg:literal) => {
181-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, $msg);
182-
tracing::warn!($msg);
183-
};
184-
($fmt:literal, $($arg:tt)*) => {
185-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::WARNING, format!($fmt, $($arg)*));
186-
tracing::warn!($fmt, $($arg)*);
187-
};
188-
}
189-
190-
#[macro_export]
191-
macro_rules! log_error {
192-
($msg:literal) => {
193-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, $msg);
194-
tracing::error!($msg);
195-
};
196-
($fmt:literal, $($arg:tt)*) => {
197-
$crate::client::log_message(tower_lsp_server::lsp_types::MessageType::ERROR, format!($fmt, $($arg)*));
198-
tracing::error!($fmt, $($arg)*);
199-
};
200-
}

crates/djls-server/src/server.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
2525
use tower_lsp_server::LanguageServer;
2626
use tracing_appender::non_blocking::WorkerGuard;
2727

28-
use crate::log_error;
29-
use crate::log_info;
3028
use crate::queue::Queue;
3129
use crate::session::Session;
3230

@@ -58,7 +56,7 @@ impl DjangoLanguageServer {
5856
if let Some(s) = &*session {
5957
f(s)
6058
} else {
61-
log_error!("Attempted to access session before initialization");
59+
tracing::error!("Attempted to access session before initialization");
6260
R::default()
6361
}
6462
}
@@ -72,7 +70,7 @@ impl DjangoLanguageServer {
7270
if let Some(s) = &mut *session {
7371
f(s)
7472
} else {
75-
log_error!("Attempted to access session before initialization");
73+
tracing::error!("Attempted to access session before initialization");
7674
R::default()
7775
}
7876
}
@@ -85,16 +83,16 @@ impl DjangoLanguageServer {
8583
let session_arc = Arc::clone(&self.session);
8684

8785
if let Err(e) = self.queue.submit(async move { f(session_arc).await }).await {
88-
log_error!("Failed to submit task: {}", e);
86+
tracing::error!("Failed to submit task: {}", e);
8987
} else {
90-
log_info!("Task submitted successfully");
88+
tracing::info!("Task submitted successfully");
9189
}
9290
}
9391
}
9492

9593
impl LanguageServer for DjangoLanguageServer {
9694
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
97-
log_info!("Initializing server...");
95+
tracing::info!("Initializing server...");
9896

9997
let session = Session::new(&params);
10098

@@ -142,7 +140,7 @@ impl LanguageServer for DjangoLanguageServer {
142140

143141
#[allow(clippy::too_many_lines)]
144142
async fn initialized(&self, _params: InitializedParams) {
145-
log_info!("Server received initialized notification.");
143+
tracing::info!("Server received initialized notification.");
146144

147145
self.with_session_task(|session_arc| async move {
148146
let project_path_and_venv = {
@@ -162,13 +160,13 @@ impl LanguageServer for DjangoLanguageServer {
162160
};
163161

164162
if let Some((path_display, venv_path)) = project_path_and_venv {
165-
log_info!(
163+
tracing::info!(
166164
"Task: Starting initialization for project at: {}",
167165
path_display
168166
);
169167

170168
if let Some(ref path) = venv_path {
171-
log_info!("Using virtual environment from config: {}", path);
169+
tracing::info!("Using virtual environment from config: {}", path);
172170
}
173171

174172
let init_result = {
@@ -188,10 +186,10 @@ impl LanguageServer for DjangoLanguageServer {
188186

189187
match init_result {
190188
Ok(()) => {
191-
log_info!("Task: Successfully initialized project: {}", path_display);
189+
tracing::info!("Task: Successfully initialized project: {}", path_display);
192190
}
193191
Err(e) => {
194-
log_error!(
192+
tracing::error!(
195193
"Task: Failed to initialize Django project at {}: {}",
196194
path_display,
197195
e
@@ -205,7 +203,7 @@ impl LanguageServer for DjangoLanguageServer {
205203
}
206204
}
207205
} else {
208-
log_info!("Task: No project instance found to initialize.");
206+
tracing::info!("Task: No project instance found to initialize.");
209207
}
210208
Ok(())
211209
})
@@ -217,7 +215,7 @@ impl LanguageServer for DjangoLanguageServer {
217215
}
218216

219217
async fn did_open(&self, params: DidOpenTextDocumentParams) {
220-
log_info!("Opened document: {:?}", params.text_document.uri);
218+
tracing::info!("Opened document: {:?}", params.text_document.uri);
221219

222220
self.with_session_mut(|session| {
223221
let db = session.db();
@@ -227,7 +225,7 @@ impl LanguageServer for DjangoLanguageServer {
227225
}
228226

229227
async fn did_change(&self, params: DidChangeTextDocumentParams) {
230-
log_info!("Changed document: {:?}", params.text_document.uri);
228+
tracing::info!("Changed document: {:?}", params.text_document.uri);
231229

232230
self.with_session_mut(|session| {
233231
let db = session.db();
@@ -237,7 +235,7 @@ impl LanguageServer for DjangoLanguageServer {
237235
}
238236

239237
async fn did_close(&self, params: DidCloseTextDocumentParams) {
240-
log_info!("Closed document: {:?}", params.text_document.uri);
238+
tracing::info!("Closed document: {:?}", params.text_document.uri);
241239

242240
self.with_session_mut(|session| {
243241
session.documents_mut().handle_did_close(&params);
@@ -265,7 +263,7 @@ impl LanguageServer for DjangoLanguageServer {
265263
}
266264

267265
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
268-
log_info!("Configuration change detected. Reloading settings...");
266+
tracing::info!("Configuration change detected. Reloading settings...");
269267

270268
let project_path = self
271269
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
@@ -277,7 +275,7 @@ impl LanguageServer for DjangoLanguageServer {
277275
session.set_settings(new_settings);
278276
}
279277
Err(e) => {
280-
log_error!("Error loading settings: {}", e);
278+
tracing::error!("Error loading settings: {}", e);
281279
}
282280
})
283281
.await;

0 commit comments

Comments
 (0)