Implement configurable native size/time log rotation & deletion#189
Implement configurable native size/time log rotation & deletion#189Anyitechs wants to merge 2 commits intolightningdevkit:mainfrom
Conversation
|
🎉 This PR is now ready for review! |
|
I would rather keep the old version. I like all the handling for the different signals in |
As we discussed elsewhere, this is now dropped entirely as we're moving to doing the rotation ourselves rather than relying on the user to configure |
|
🔔 1st Reminder Hey @benthecarman! This PR has been waiting for your review. |
| /// Maximum size of the log file before it gets rotated (50 MB) | ||
| const MAX_LOG_SIZE_BYTES: usize = 50 * 1024 * 1024; | ||
| /// Maximum age of the log file before it gets rotated (24 hours) | ||
| const ROTATION_INTERVAL_SECS: u64 = 24 * 60 * 60; |
There was a problem hiding this comment.
these should be configurable
| state.created_at = SystemTime::now(); | ||
|
|
||
| // Spawn independent OS thread to compress the old file using native gzip | ||
| thread::spawn(move || match Command::new("gzip").arg("-f").arg(&rotated_path).status() { |
There was a problem hiding this comment.
This is assuming they have gzip installed and we have permissions to run it. I would rather just have the rust code do this
There was a problem hiding this comment.
It doesn't really seem worth taking a gzip dependency just to do log rotation. We can just rotate and delete as-is and tell people to use the system log (which handles this properly) otherwise. Really we shouldn't be doing logging ourselves anyway - log should go to stdout/err and systemd or some other logic should figure out what to do with it.
There was a problem hiding this comment.
I'm happy to drop the compression so we do a rotate and delete. If that works for everyone, I'll update this to introduce a configurable max_rotated_files that will default to the last 5 uncompressed files. Does that work?
There was a problem hiding this comment.
I'm in favor of just doing deletion instead of compression but I would really rather keep the log file and not rely on just stdout/stderr. If we don't have an easy log file and rely on the user's systemd/docker/whatever to do and persist the logs, we will likely not have logs for lots of users and make it much harder to do support.
There was a problem hiding this comment.
I'm in favor of just doing deletion instead of compression but I would really rather keep the log file and not rely on just stdout/stderr. If we don't have an easy log file and rely on the user's systemd/docker/whatever to do and persist the logs, we will likely not have logs for lots of users and make it much harder to do support.
I'm also leaning towards just not logging to file. However I see your point that it might lead to nothing being logged at all. In that case we should however at the very least add the option to disable logging to file, and also update our docs and checked-in systemd ldk-server.service to use that mode, so that everybody who runs it that way will just use journald rather than our custom filesystem logger.
There was a problem hiding this comment.
Just added an option to disable logging to file by default and a configurable native rotate and delete here b54e0a5
| } | ||
|
|
||
| runtime.block_on(async { | ||
| // Register SIGHUP handler for log rotation |
There was a problem hiding this comment.
looks like you actually removed the SIGHUP handling even though in the docs you say we have it
There was a problem hiding this comment.
Ah, good catch. Thanks!
Update the ServerLogger to track file size and age internally, triggering rotation at 50MB or 24 hours. Old logs are now compressed in the background using native OS gzip via `std::thread::spawn`, eliminating the need for the user to configure `logrotate`. Disk writes are also now buffered for better runtime performance. Co-Authored-By: Gemini 3.0 Pro
|
Addressed review comment here 42cd66a and rebased to fix conflict. |
| [log] | ||
| level = "Debug" # Log level (Error, Warn, Info, Debug, Trace) | ||
| #file = "/tmp/ldk-server/ldk-server.log" # Log file path | ||
| log_to_file = true # Enable logging to a file (default: true, also logs to both stdout and stderr) |
There was a problem hiding this comment.
nit: Alignment of comments is off.
| > **Important:** LDK Server does not rotate or truncate its own log file. Without log rotation | ||
| > configured, the log file will grow indefinitely and can eventually fill your disk. A full | ||
| > disk can prevent the node from persisting channel state, risking fund loss. | ||
| By default, LDK Server logs to `stdout`/`stderr`. When running under `systemd` or Docker, |
There was a problem hiding this comment.
Hmm, here we say that by default we log to stdout/stderr, but above we say log_to_file defaults to true? Probably both somewhat true, but is a bit confusing. Might be good to clarify.
| } | ||
|
|
||
| fn cleanup_old_logs(log_file_path: &Path, max_files: usize) -> io::Result<()> { | ||
| let parent = log_file_path.parent().unwrap_or_else(|| Path::new(".")); |
There was a problem hiding this comment.
Hmm, why are we falling back to .? In general, maybe it would be better to just error out if something is unexpected instead of doing the unwrap_or fallbacks here and below, just to be sure we never end up removing some unrelated files?
There was a problem hiding this comment.
Codex has the same concern:
- P3 Retention cleanup matches every file whose name starts with the active log basename (ldk-server/src/util/logger.rs:227). That can delete unrelated files such as ldk-server.log.backup or config artifacts once the count exceeds max_files; it should match the exact rotation filename
pattern.
|
|
||
| If `log_to_file` is enabled, the server performs internal rotation and retention | ||
| based on `max_size_mb`, `rotation_interval_hours`, and `max_files`. The server will | ||
| also reopen the log file on `SIGHUP` for compatibility with external tools like `logrotate`. |
There was a problem hiding this comment.
Hmm, it seems we're now no longer compatible with logrotate, but rather rotate ourselves when log_to_file is configured? I guess that's fine, but we might want to update docs here and elsewhere?
There was a problem hiding this comment.
it seems we're now no longer compatible with
logrotate
We still are, I added that back in 42cd66a.
but rather rotate ourselves when log_to_file is configured?
Yes, we rotate ourselves when log_to_file is configured, but also have the SIGHUP signal handler for users relying on logrotate
There was a problem hiding this comment.
But how would the user disable our internal log rotation if they use logrotate themselves?
| } | ||
| } | ||
|
|
||
| fn flush(&self) { |
There was a problem hiding this comment.
Codex:
- P1 File logs are now buffered with BufWriter (ldk-server/src/util/logger.rs:83), but normal writes do not flush (ldk-server/src/util/logger.rs:184) and shutdown does not call log::logger().flush() after the final log line (ldk-server/src/main.rs:527). Since the logger is installed
globally, recent file logs from short runs or shutdown can remain in memory and never reach disk.
This updates the
ServerLoggerto track file size and age internally, triggering rotation at 50MB or 24 hours. Old logs are now compressed in the background using native OSgzipviastd::thread::spawn, eliminating the need for the user to configurelogrotate.Disk writes are also now buffered for better runtime performance.