add basic log rotation

This commit is contained in:
Damien Elmes 2020-03-10 10:33:14 +10:00
parent 6e30572e6d
commit 67d6b4f713
2 changed files with 37 additions and 6 deletions

View file

@ -21,7 +21,7 @@ use crate::{backend_proto as pb, log};
use fluent::FluentValue; use fluent::FluentValue;
use prost::Message; use prost::Message;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
pub type ProtoProgressCallback = Box<dyn Fn(Vec<u8>) -> bool + Send>; pub type ProtoProgressCallback = Box<dyn Fn(Vec<u8>) -> bool + Send>;
@ -108,7 +108,7 @@ pub fn init_backend(init_msg: &[u8]) -> std::result::Result<Backend, String> {
let log_path = match input.log_path.as_str() { let log_path = match input.log_path.as_str() {
"" => None, "" => None,
path => Some(Path::new(path)), path => Some(path),
}; };
let logger = let logger =
default_logger(log_path).map_err(|e| format!("Unable to open log file: {:?}", e))?; default_logger(log_path).map_err(|e| format!("Unable to open log file: {:?}", e))?;

View file

@ -5,8 +5,9 @@ pub use slog::{debug, error, Logger};
use slog::{slog_o, Drain}; use slog::{slog_o, Drain};
use slog_async::OverflowStrategy; use slog_async::OverflowStrategy;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io; use std::{fs, io};
use std::path::Path;
const LOG_ROTATE_BYTES: u64 = 50 * 1024 * 1024;
pub(crate) fn terminal() -> Logger { pub(crate) fn terminal() -> Logger {
let decorator = slog_term::TermDecorator::new().build(); let decorator = slog_term::TermDecorator::new().build();
@ -20,7 +21,8 @@ pub(crate) fn terminal() -> Logger {
Logger::root(drain, slog_o!()) Logger::root(drain, slog_o!())
} }
fn file(path: &Path) -> io::Result<Logger> { fn file(path: &str) -> io::Result<Logger> {
maybe_rotate_log(path)?;
let file = OpenOptions::new().create(true).append(true).open(path)?; let file = OpenOptions::new().create(true).append(true).open(path)?;
let decorator = slog_term::PlainSyncDecorator::new(file); let decorator = slog_term::PlainSyncDecorator::new(file);
@ -34,8 +36,37 @@ fn file(path: &Path) -> io::Result<Logger> {
Ok(Logger::root(drain, slog_o!())) Ok(Logger::root(drain, slog_o!()))
} }
fn maybe_rotate_log(path: &str) -> io::Result<()> {
let current_bytes = match fs::metadata(path) {
Ok(meta) => meta.len(),
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
0
} else {
return Err(e);
}
}
};
if current_bytes < LOG_ROTATE_BYTES {
return Ok(());
}
let path2 = format!("{}.1", path);
let path3 = format!("{}.2", path);
// if a rotated file already exists, rename it
if let Err(e) = fs::rename(&path2, &path3) {
if e.kind() != io::ErrorKind::NotFound {
return Err(e);
}
}
// and rotate the primary log
fs::rename(path, path2)
}
/// Get a logger, logging to a file if a path was provided, otherwise terminal. /// Get a logger, logging to a file if a path was provided, otherwise terminal.
pub(crate) fn default_logger(path: Option<&Path>) -> io::Result<Logger> { pub(crate) fn default_logger(path: Option<&str>) -> io::Result<Logger> {
Ok(match path { Ok(match path {
Some(path) => file(path)?, Some(path) => file(path)?,
None => terminal(), None => terminal(),