logs-wheel 0.3.1

Rolling log files with compression
Documentation
use logs_wheel::LogFileInitializer;
use std::{
    fs::{remove_dir_all, rename, File},
    io::{self, Write},
    path::Path,
};
use time::{Duration, OffsetDateTime};

fn filename_from_date(date: OffsetDateTime) -> String {
    let (year, month, day) = date.to_calendar_date();
    format!("test-{year:04}{:02}{day:02}.gz", month as u8)
}

#[test]
fn main() -> io::Result<()> {
    // Some tests might fail at 00:00 UTC when the date is incremented between tests.

    let directory = Path::new("integration_tests_logs");

    // Start with a new directory.
    if directory.exists() {
        remove_dir_all(directory)?;
    }

    let assert_dir = |filenames: &[&str]| {
        assert!(directory
            .read_dir()
            .unwrap()
            .zip(filenames)
            .all(|(entry, expected)| entry.unwrap().file_name().to_str().unwrap() == *expected))
    };

    let init = || {
        LogFileInitializer {
            directory,
            filename: "test",
            max_n_old_files: 2,
            preferred_max_file_size_mib: 1,
        }
        .init()
    };

    let mib = 1_u64 << 20;
    let mib_usize = 1_usize << 20;
    let buf_half_mib = vec![0; mib_usize / 2];

    // Fresh start.
    {
        let mut file = init()?;
        file.write_all(&buf_half_mib)?;
        assert_dir(&["test"]);
        assert_eq!(file.metadata().unwrap().len(), mib / 2);
    }

    // No rolling since the preferred maximum file size is not reached yet.
    {
        let mut file = init()?;
        file.write_all(&buf_half_mib)?;
        assert_dir(&["test"]);
        assert_eq!(file.metadata().unwrap().len(), mib);
    }

    let write_1_mib = |file: &mut File| {
        file.write_all(&buf_half_mib)?;
        file.write_all(&buf_half_mib)
    };

    // Rolling.
    let today = time::OffsetDateTime::now_utc();
    let today_filename = filename_from_date(today);
    {
        let mut file = init()?;
        write_1_mib(&mut file)?;
        assert_dir(&["test", &today_filename]);
        assert_eq!(file.metadata().unwrap().len(), mib);
    }

    // No rolling twice a day.
    {
        let mut file = init()?;
        write_1_mib(&mut file)?;
        assert_dir(&["test", &today_filename]);
        assert_eq!(file.metadata().unwrap().len(), 2 * mib);
    }

    // Simulate next day.
    let yesterday = today - Duration::days(1);
    let yesterday_filename = filename_from_date(yesterday);
    rename(
        directory.join(&today_filename),
        directory.join(&yesterday_filename),
    )?;

    // Rolling on a later day.
    {
        let mut file = init()?;
        write_1_mib(&mut file)?;
        assert_dir(&["test", &yesterday_filename, &today_filename]);
        assert_eq!(file.metadata().unwrap().len(), mib);
    }

    // Simulate next day.
    let day_before_yesterday = today - Duration::days(1);
    let day_before_yesterday_filename = filename_from_date(day_before_yesterday);
    rename(
        directory.join(&today_filename),
        directory.join(day_before_yesterday_filename),
    )?;

    // Deleting the oldest file after reaching the maximum number of old files.
    {
        let file = init()?;
        assert_dir(&["test", &yesterday_filename, &today_filename]);
        assert_eq!(file.metadata().unwrap().len(), 0);
    }

    // Clean up.
    remove_dir_all(directory)
}