@@ -13,7 +13,7 @@ use std::path::{Path, PathBuf};
1313use std:: sync:: { Arc , Mutex } ;
1414use std:: time:: SystemTime ;
1515
16- use log:: { Level , LevelFilter , Log , Metadata , Record } ;
16+ use log:: { error , Level , LevelFilter , Log , Metadata , Record } ;
1717
1818struct LoggerState {
1919 file : LineWriter < File > ,
@@ -35,7 +35,7 @@ struct LoggerState {
3535///
3636/// Example: `[2025-12-04T10:30:45Z INFO ldk_server:42] Starting up...`
3737///
38- /// The logger does a native size/time-based rotation and retains the last 5 logs by default, if `max_rotated_files ` is unset.
38+ /// The logger does a native size/time-based rotation and retains the last 5 logs by default, if `log_max_files ` is unset.
3939pub struct ServerLogger {
4040 /// The maximum log level to display
4141 level : LevelFilter ,
@@ -127,9 +127,15 @@ impl ServerLogger {
127127
128128 /// Flushes the current file, renames it with a timestamp, opens a fresh log,
129129 /// and synchronously deletes older log files.
130- fn rotate ( & self , state : & mut LoggerState ) -> Result < ( ) , io:: Error > {
130+ fn rotate (
131+ & self , state : & mut LoggerState , system_time_now : SystemTime ,
132+ ) -> Result < ( ) , io:: Error > {
131133 state. file . flush ( ) ?;
132- let log_file_path = self . log_file_path . as_ref ( ) . unwrap ( ) ;
134+ let log_file_path = if let Some ( path) = self . log_file_path . as_ref ( ) {
135+ path
136+ } else {
137+ return Ok ( ( ) ) ;
138+ } ;
133139
134140 let now = chrono:: Utc :: now ( ) . format ( "%Y-%m-%dT%H-%M-%SZ" ) . to_string ( ) ;
135141 let mut new_path = log_file_path. to_path_buf ( ) . into_os_string ( ) ;
@@ -144,12 +150,7 @@ impl ServerLogger {
144150
145151 // Reset our rotation triggers for the new file
146152 state. bytes_written = 0 ;
147- state. created_at = SystemTime :: now ( ) ;
148-
149- // Clean up old log files
150- if let Err ( e) = cleanup_old_logs ( log_file_path, state. log_max_files ) {
151- eprintln ! ( "Failed to clean up old log files: {}" , e) ;
152- }
153+ state. created_at = system_time_now;
153154
154155 Ok ( ( ) )
155156 }
@@ -185,6 +186,8 @@ impl Log for ServerLogger {
185186 } ,
186187 } ;
187188
189+ let mut cleanup_max_files = None ;
190+
188191 if let Some ( state_mutex) = & self . state {
189192 // Log to file
190193 let log_bytes = log_line. len ( ) + 1 ;
@@ -205,15 +208,26 @@ impl Log for ServerLogger {
205208 }
206209
207210 if needs_rotation {
208- if let Err ( e) = self . rotate ( & mut state) {
209- eprintln ! ( "Failed to rotate log file: {}" , e) ;
211+ if let Err ( e) = self . rotate ( & mut state, now) {
212+ error ! ( "Failed to rotate log file: {e}" ) ;
213+ } else {
214+ cleanup_max_files = Some ( state. log_max_files ) ;
210215 }
211216 }
212217
213218 let _ = writeln ! ( state. file, "{}" , log_line) ;
214219 state. bytes_written += log_bytes;
215220 }
216221 }
222+
223+ // Clean up old log files
224+ if let ( Some ( log_max_files) , Some ( log_file_path) ) =
225+ ( cleanup_max_files, & self . log_file_path )
226+ {
227+ if let Err ( e) = cleanup_old_logs ( log_file_path, log_max_files) {
228+ error ! ( "Failed to clean up old log files: {e}" ) ;
229+ }
230+ }
217231 }
218232 }
219233
@@ -276,7 +290,9 @@ fn cleanup_old_logs(log_file_path: &Path, max_files: usize) -> io::Result<()> {
276290 . collect ( ) ;
277291
278292 // Sort by modification time (oldest first)
279- entries. sort_by_key ( |e| e. metadata ( ) . and_then ( |m| m. modified ( ) ) . unwrap_or ( SystemTime :: now ( ) ) ) ;
293+ entries. sort_by_cached_key ( |e| {
294+ e. metadata ( ) . and_then ( |m| m. modified ( ) ) . unwrap_or ( SystemTime :: now ( ) )
295+ } ) ;
280296
281297 if entries. len ( ) > max_files {
282298 for entry in entries. iter ( ) . take ( entries. len ( ) - max_files) {
0 commit comments