Write output to a file and rotate the files when limits have been exceeded.
Defines a simple [std::io::Write] object that you can plug into your writers as middleware.
Rotating by Lines
We can rotate log files by using the amount of lines as a limit.
use file_rotate::{FileRotate, RotationMode};
use std::{fs, io::Write};
fs::create_dir("target/my-log-directory-lines");
let mut log = FileRotate::new("target/my-log-directory-lines/my-log-file", RotationMode::Lines(3), 2);
writeln!(log, "Line 1: Hello World!");
for idx in 2..11 {
writeln!(log, "Line {}", idx);
}
assert_eq!("Line 10\n", fs::read_to_string("target/my-log-directory-lines/my-log-file").unwrap());
assert_eq!("Line 1: Hello World!\nLine 2\nLine 3\n", fs::read_to_string("target/my-log-directory-lines/my-log-file.0").unwrap());
assert_eq!("Line 4\nLine 5\nLine 6\n", fs::read_to_string("target/my-log-directory-lines/my-log-file.1").unwrap());
assert_eq!("Line 7\nLine 8\nLine 9\n", fs::read_to_string("target/my-log-directory-lines/my-log-file.2").unwrap());
fs::remove_dir_all("target/my-log-directory-lines");
Rotating by Bytes
Another method of rotation is by bytes instead of lines.
use file_rotate::{FileRotate, RotationMode};
use std::{fs, io::Write};
fs::create_dir("target/my-log-directory-bytes");
let mut log = FileRotate::new("target/my-log-directory-bytes/my-log-file", RotationMode::Bytes(5), 2);
writeln!(log, "Test file");
assert_eq!("Test ", fs::read_to_string("target/my-log-directory-bytes/my-log-file.0").unwrap());
assert_eq!("file\n", fs::read_to_string("target/my-log-directory-bytes/my-log-file").unwrap());
fs::remove_dir_all("target/my-log-directory-bytes");
Rotation Method
The rotation method used is to always write to the base path, and then move the file to a new
location when the limit is exceeded. The moving occurs in the sequence 0, 1, 2, n, 0, 1, 2...
Here's an example with 1 byte limits:
use file_rotate::{FileRotate, RotationMode};
use std::{fs, io::Write};
fs::create_dir("target/my-log-directory-small");
let mut log = FileRotate::new("target/my-log-directory-small/my-log-file", RotationMode::Bytes(1), 3);
write!(log, "A");
assert_eq!("A", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
write!(log, "B");
assert_eq!("A", fs::read_to_string("target/my-log-directory-small/my-log-file.0").unwrap());
assert_eq!("B", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
write!(log, "C");
assert_eq!("A", fs::read_to_string("target/my-log-directory-small/my-log-file.0").unwrap());
assert_eq!("B", fs::read_to_string("target/my-log-directory-small/my-log-file.1").unwrap());
assert_eq!("C", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
write!(log, "D");
assert_eq!("A", fs::read_to_string("target/my-log-directory-small/my-log-file.0").unwrap());
assert_eq!("B", fs::read_to_string("target/my-log-directory-small/my-log-file.1").unwrap());
assert_eq!("C", fs::read_to_string("target/my-log-directory-small/my-log-file.2").unwrap());
assert_eq!("D", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
write!(log, "E");
assert_eq!("A", fs::read_to_string("target/my-log-directory-small/my-log-file.0").unwrap());
assert_eq!("B", fs::read_to_string("target/my-log-directory-small/my-log-file.1").unwrap());
assert_eq!("C", fs::read_to_string("target/my-log-directory-small/my-log-file.2").unwrap());
assert_eq!("D", fs::read_to_string("target/my-log-directory-small/my-log-file.3").unwrap());
assert_eq!("E", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
write!(log, "F");
assert_eq!("E", fs::read_to_string("target/my-log-directory-small/my-log-file.0").unwrap());
assert_eq!("B", fs::read_to_string("target/my-log-directory-small/my-log-file.1").unwrap());
assert_eq!("C", fs::read_to_string("target/my-log-directory-small/my-log-file.2").unwrap());
assert_eq!("D", fs::read_to_string("target/my-log-directory-small/my-log-file.3").unwrap());
assert_eq!("F", fs::read_to_string("target/my-log-directory-small/my-log-file").unwrap());
fs::remove_dir_all("target/my-log-directory-small");
Filesystem Errors
If the directory containing the logs is deleted or somehow made inaccessible then the rotator
will simply continue operating without fault. When a rotation occurs, it attempts to open a
file in the directory. If it can, it will just continue logging. If it can't then the written
date is sent to the void.
This logger never panics.