From 67d6b4f713baffaebb0afda0903c31e727b9460f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 10 Mar 2020 10:33:14 +1000 Subject: [PATCH] add basic log rotation --- rslib/src/backend.rs | 4 ++-- rslib/src/log.rs | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/rslib/src/backend.rs b/rslib/src/backend.rs index 842011101..8997ff71d 100644 --- a/rslib/src/backend.rs +++ b/rslib/src/backend.rs @@ -21,7 +21,7 @@ use crate::{backend_proto as pb, log}; use fluent::FluentValue; use prost::Message; use std::collections::{HashMap, HashSet}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use tokio::runtime::Runtime; pub type ProtoProgressCallback = Box) -> bool + Send>; @@ -108,7 +108,7 @@ pub fn init_backend(init_msg: &[u8]) -> std::result::Result { let log_path = match input.log_path.as_str() { "" => None, - path => Some(Path::new(path)), + path => Some(path), }; let logger = default_logger(log_path).map_err(|e| format!("Unable to open log file: {:?}", e))?; diff --git a/rslib/src/log.rs b/rslib/src/log.rs index 497608619..82c7a9a98 100644 --- a/rslib/src/log.rs +++ b/rslib/src/log.rs @@ -5,8 +5,9 @@ pub use slog::{debug, error, Logger}; use slog::{slog_o, Drain}; use slog_async::OverflowStrategy; use std::fs::OpenOptions; -use std::io; -use std::path::Path; +use std::{fs, io}; + +const LOG_ROTATE_BYTES: u64 = 50 * 1024 * 1024; pub(crate) fn terminal() -> Logger { let decorator = slog_term::TermDecorator::new().build(); @@ -20,7 +21,8 @@ pub(crate) fn terminal() -> Logger { Logger::root(drain, slog_o!()) } -fn file(path: &Path) -> io::Result { +fn file(path: &str) -> io::Result { + maybe_rotate_log(path)?; let file = OpenOptions::new().create(true).append(true).open(path)?; let decorator = slog_term::PlainSyncDecorator::new(file); @@ -34,8 +36,37 @@ fn file(path: &Path) -> io::Result { 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. -pub(crate) fn default_logger(path: Option<&Path>) -> io::Result { +pub(crate) fn default_logger(path: Option<&str>) -> io::Result { Ok(match path { Some(path) => file(path)?, None => terminal(),