Skip to content

Commit 500e74f

Browse files
Move log directory creation logic to djls-conf function
- Changed LOG_DIR static back to log_dir() function returning Result - Moved directory creation logic from djls-server to djls-conf - Updated init_tracing to return Result and use log_dir()? - Added proper error handling with anyhow::Context - Added comprehensive documentation with Errors and Panics sections - Added test to verify directory creation Co-authored-by: joshuadavidthomas <19896267+joshuadavidthomas@users.noreply.github.com>
1 parent a44c727 commit 500e74f

3 files changed

Lines changed: 42 additions & 19 deletions

File tree

crates/djls-conf/src/lib.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ pub mod tagspecs;
22

33
use std::fs;
44
use std::path::Path;
5-
use std::sync::LazyLock;
65

6+
use anyhow::Context;
77
use camino::{Utf8Path, Utf8PathBuf};
88
use config::Config;
99
use config::ConfigError as ExternalConfigError;
@@ -137,15 +137,27 @@ impl Settings {
137137
}
138138
}
139139

140-
/// The log directory for the application.
140+
/// Get the log directory for the application and ensure it exists.
141141
///
142142
/// Returns the XDG cache directory (e.g., ~/.cache/djls on Linux) if available,
143-
/// otherwise falls back to /tmp.
144-
pub static LOG_DIR: LazyLock<Utf8PathBuf> = LazyLock::new(|| {
145-
ProjectDirs::from("", "", "djls")
146-
.map(|proj_dirs| Utf8PathBuf::from_path_buf(proj_dirs.cache_dir().to_path_buf()).unwrap())
147-
.unwrap_or_else(|| Utf8PathBuf::from("/tmp"))
148-
});
143+
/// otherwise falls back to /tmp. Creates the directory if it doesn't exist.
144+
///
145+
/// # Errors
146+
///
147+
/// Returns an error if the directory cannot be created.
148+
///
149+
/// # Panics
150+
///
151+
/// Panics if the XDG cache directory path contains invalid UTF-8.
152+
pub fn log_dir() -> anyhow::Result<Utf8PathBuf> {
153+
let dir = ProjectDirs::from("", "", "djls")
154+
.map_or_else(|| Utf8PathBuf::from("/tmp"), |proj_dirs| Utf8PathBuf::from_path_buf(proj_dirs.cache_dir().to_path_buf()).unwrap());
155+
156+
fs::create_dir_all(&dir)
157+
.with_context(|| format!("Failed to create log directory: {dir}"))?;
158+
159+
Ok(dir)
160+
}
149161

150162
#[cfg(test)]
151163
mod tests {
@@ -669,11 +681,18 @@ args = [
669681

670682
#[test]
671683
fn test_log_dir_returns_path() {
672-
let dir = &*LOG_DIR;
684+
let dir = log_dir().unwrap();
673685
// Either it's the XDG cache dir or /tmp
674686
assert!(dir.as_str().contains("djls") || dir == "/tmp");
675687
}
676688

689+
#[test]
690+
fn test_log_dir_creates_directory() {
691+
// Test that the function creates the directory
692+
let dir = log_dir().unwrap();
693+
assert!(dir.exists());
694+
}
695+
677696
#[test]
678697
fn test_log_dir_xdg_pattern() {
679698
// Verify that if ProjectDirs is available, it returns a proper path

crates/djls-server/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ use tower_lsp_server::Server;
1515
pub use crate::server::DjangoLanguageServer;
1616
pub use crate::session::Session;
1717

18+
/// Run the Django language server.
19+
///
20+
/// # Panics
21+
///
22+
/// Panics if the logging system cannot be initialized (e.g., unable to create log directory).
1823
pub fn run() -> Result<()> {
1924
if std::io::stdin().is_terminal() {
2025
eprintln!(
@@ -55,7 +60,8 @@ pub fn run() -> Result<()> {
5560
client.log_message(message_type, message).await;
5661
});
5762
}
58-
});
63+
})
64+
.expect("Failed to initialize logging");
5965

6066
DjangoLanguageServer::new(client, log_guard)
6167
})

crates/djls-server/src/logging.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,15 @@ where
111111
/// - `EnvFilter`: respects `RUST_LOG` env var, defaults to "info"
112112
///
113113
/// Returns a `WorkerGuard` that must be kept alive for the file logging to work.
114-
pub fn init_tracing<F>(send_message: F) -> WorkerGuard
114+
///
115+
/// # Errors
116+
///
117+
/// Returns an error if the log directory cannot be created.
118+
pub fn init_tracing<F>(send_message: F) -> anyhow::Result<WorkerGuard>
115119
where
116120
F: Fn(lsp_types::MessageType, String) + Send + Sync + 'static,
117121
{
118-
// Get log directory from djls-conf
119-
let log_dir = &*djls_conf::LOG_DIR;
120-
121-
// Ensure the log directory exists
122-
if let Err(e) = std::fs::create_dir_all(log_dir) {
123-
eprintln!("Warning: Failed to create log directory {log_dir}: {e}");
124-
}
122+
let log_dir = djls_conf::log_dir()?;
125123

126124
let file_appender = tracing_appender::rolling::daily(log_dir.as_std_path(), "djls.log");
127125
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
@@ -142,5 +140,5 @@ where
142140

143141
Registry::default().with(file_layer).with(lsp_layer).init();
144142

145-
guard
143+
Ok(guard)
146144
}

0 commit comments

Comments
 (0)