@@ -105,40 +105,63 @@ where
105105/// Initialize the dual-layer tracing subscriber.
106106///
107107/// Sets up:
108- /// - File layer: writes to XDG cache directory (e.g., ~/.cache/djls/djls.log on Linux) with daily rotation,
109- /// falls back to /tmp/djls.log if XDG cache directory is not available
108+ /// - File layer: writes to XDG cache directory (e.g., ~/.cache/djls/djls.log on Linux) with daily rotation.
109+ /// Falls back to /tmp/djls.log if XDG cache directory is not available.
110+ /// If file logging cannot be initialized, falls back to stderr.
110111/// - LSP layer: forwards INFO+ messages to the client
111112/// - `EnvFilter`: respects `RUST_LOG` env var, defaults to "info"
112113///
113- /// Returns a `WorkerGuard` that must be kept alive for the file logging to work.
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 >
114+ /// Returns a `WorkerGuard` that must be kept alive for the logging to work.
115+ pub fn init_tracing < F > ( send_message : F ) -> WorkerGuard
119116where
120117 F : Fn ( lsp_types:: MessageType , String ) + Send + Sync + ' static ,
121118{
122- let log_dir = djls_conf:: log_dir ( ) ?;
123-
124- let file_appender = tracing_appender:: rolling:: daily ( log_dir. as_std_path ( ) , "djls.log" ) ;
125- let ( non_blocking, guard) = tracing_appender:: non_blocking ( file_appender) ;
126-
127119 let env_filter = EnvFilter :: try_from_default_env ( ) . unwrap_or_else ( |_| EnvFilter :: new ( "info" ) ) ;
128- let file_layer = fmt:: layer ( )
129- . with_writer ( non_blocking)
130- . with_ansi ( false )
131- . with_thread_ids ( true )
132- . with_thread_names ( true )
133- . with_target ( true )
134- . with_file ( true )
135- . with_line_number ( true )
136- . with_filter ( env_filter) ;
137120
138121 let lsp_layer =
139122 LspLayer :: new ( send_message) . with_filter ( tracing_subscriber:: filter:: LevelFilter :: INFO ) ;
140123
141- Registry :: default ( ) . with ( file_layer) . with ( lsp_layer) . init ( ) ;
124+ match djls_conf:: log_dir ( ) {
125+ Ok ( log_dir) => {
126+ let file_appender = tracing_appender:: rolling:: daily ( log_dir. as_std_path ( ) , "djls.log" ) ;
127+ let ( non_blocking, guard) = tracing_appender:: non_blocking ( file_appender) ;
128+
129+ let file_layer = fmt:: layer ( )
130+ . with_writer ( non_blocking)
131+ . with_ansi ( false )
132+ . with_thread_ids ( true )
133+ . with_thread_names ( true )
134+ . with_target ( true )
135+ . with_file ( true )
136+ . with_line_number ( true )
137+ . with_filter ( env_filter) ;
142138
143- Ok ( guard)
139+ Registry :: default ( ) . with ( file_layer) . with ( lsp_layer) . init ( ) ;
140+
141+ guard
142+ }
143+ Err ( e) => {
144+ eprintln ! ( "Warning: Failed to initialize file logging: {e}" ) ;
145+ eprintln ! ( "Falling back to stderr logging..." ) ;
146+
147+ let ( non_blocking, guard) = tracing_appender:: non_blocking ( std:: io:: stderr ( ) ) ;
148+
149+ let stderr_layer = fmt:: layer ( )
150+ . with_writer ( non_blocking)
151+ . with_ansi ( false )
152+ . with_thread_ids ( true )
153+ . with_thread_names ( true )
154+ . with_target ( true )
155+ . with_file ( true )
156+ . with_line_number ( true )
157+ . with_filter ( env_filter) ;
158+
159+ Registry :: default ( )
160+ . with ( stderr_layer)
161+ . with ( lsp_layer)
162+ . init ( ) ;
163+
164+ guard
165+ }
166+ }
144167}
0 commit comments