Add pruning behaviour

This commit is contained in:
Floris Bruynooghe
2019-11-22 00:42:26 +01:00
parent 124f684036
commit 4312c03a0b

View File

@@ -1,8 +1,8 @@
//! # Logging support //! # Logging support
use std::io;
use std::fmt; use std::fmt;
use std::fs; use std::fs;
use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@@ -51,7 +51,7 @@ impl Logger {
pub fn new(logdir: PathBuf) -> Result<Logger, io::Error> { pub fn new(logdir: PathBuf) -> Result<Logger, io::Error> {
let (fname, file) = Self::open(&logdir)?; let (fname, file) = Self::open(&logdir)?;
let max_files = 5; let max_files = 5;
Self::prune(&logdir, max_files); Self::prune(&logdir, max_files)?;
Ok(Logger { Ok(Logger {
logdir, logdir,
logfile: fname, logfile: fname,
@@ -94,8 +94,21 @@ impl Logger {
} }
/// Cleans up old logfiles. /// Cleans up old logfiles.
fn prune(logdir: &Path, max_files: u32) { fn prune(logdir: &Path, max_files: u32) -> Result<(), io::Error> {
// TODO let mut names: Vec<std::ffi::OsString> = Vec::new();
for dirent in fs::read_dir(logdir)? {
names.push(dirent?.file_name());
}
// Sorting like this sorts: 23.log, 24.1.log, 24.2.log,
// 24.log, 25.log. That is 24.log is out of sequence. Oh well.
names.sort();
names.reverse();
while names.len() > max_files as usize {
if let Some(name) = names.pop() {
fs::remove_file(logdir.join(name))?;
}
}
Ok(())
} }
pub fn log( pub fn log(
@@ -105,10 +118,11 @@ impl Logger {
msg: &str, msg: &str,
) -> Result<(), std::io::Error> { ) -> Result<(), std::io::Error> {
if self.bytes_written > self.max_filesize { if self.bytes_written > self.max_filesize {
self.flush()?;
let (fname, handle) = Self::open(&self.logdir)?; let (fname, handle) = Self::open(&self.logdir)?;
self.logfile = fname; self.logfile = fname;
self.file_handle = handle; self.file_handle = handle;
Self::prune(&self.logdir, self.max_files); Self::prune(&self.logdir, self.max_files)?;
} }
let msg = format!("{} [{}]: {}\n", level, callsite, msg); let msg = format!("{} [{}]: {}\n", level, callsite, msg);
self.file_handle.write_all(msg.as_bytes())?; self.file_handle.write_all(msg.as_bytes())?;
@@ -225,17 +239,20 @@ mod tests {
assert!(log0.contains("more than 5 bytes are written")); assert!(log0.contains("more than 5 bytes are written"));
let log1 = fs::read_to_string(logger.logdir.join(&fname1)).unwrap(); let log1 = fs::read_to_string(logger.logdir.join(&fname1)).unwrap();
assert!(log1.contains("2nd msg")); assert!(log1.contains("2nd msg"));
}
let mut count = 0; #[test]
loop { fn test_prune() {
if count > 40 { let tmp = tempfile::tempdir().unwrap();
assert!(false, "Failed to find error"); let dir = tmp.path();
} Logger::new(dir.to_path_buf()).unwrap();
count += 1; Logger::new(dir.to_path_buf()).unwrap();
match logger.log(LogLevel::Info, callsite!(), "more reopens please") { Logger::new(dir.to_path_buf()).unwrap();
Ok(_) => continue, Logger::new(dir.to_path_buf()).unwrap();
Err(_) => break, let dirents0: Vec<fs::DirEntry> = fs::read_dir(&dir).unwrap().map(|r| r.unwrap()).collect();
} assert_eq!(dirents0.len(), 4);
} Logger::prune(&dir, 3).unwrap();
let dirents1: Vec<fs::DirEntry> = fs::read_dir(&dir).unwrap().map(|r| r.unwrap()).collect();
assert_eq!(dirents1.len(), 3);
} }
} }