use file_rotate::{
ContentLimit, FileRotate,
compression::Compression,
suffix::{AppendTimestamp, FileLimit},
};
use std::{
env,
ffi::OsStr,
fmt::Debug,
io,
io::Write,
path::{Path, PathBuf},
};
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
pub(super) fn file_rotater(
dir: &PathBuf,
max_bytes: usize,
uncompressed_files: usize,
max_files: usize,
) -> (NonBlocking, WorkerGuard) {
let binary_name = env::current_exe()
.map(|path| {
path.file_stem()
.unwrap_or(OsStr::new("autonomi"))
.to_string_lossy()
.into_owned()
})
.unwrap_or_else(|_| "autonomi".to_string());
let file_appender = FileRotateAppender::make_rotate_appender(
dir,
format!("{binary_name}.log"),
AppendTimestamp::default(FileLimit::MaxFiles(max_files)),
ContentLimit::BytesSurpassed(max_bytes),
Compression::OnRotate(uncompressed_files),
);
let non_blocking_builder = tracing_appender::non_blocking::NonBlockingBuilder::default();
non_blocking_builder
.lossy(false)
.finish(file_appender)
}
pub(super) struct FileRotateAppender {
writer: FileRotate<AppendTimestamp>,
}
impl FileRotateAppender {
pub(super) fn make_rotate_appender(
directory: impl AsRef<Path>,
file_name_prefix: impl AsRef<Path>,
file_limit: AppendTimestamp,
max_log_size: ContentLimit,
compression: Compression,
) -> Self {
let log_directory = directory.as_ref();
let log_filename_prefix = file_name_prefix.as_ref();
let path = Path::new(&log_directory).join(log_filename_prefix);
let writer = FileRotate::new(
Path::new(&path),
file_limit,
max_log_size,
compression,
#[cfg(unix)]
None,
);
Self { writer }
}
}
impl Write for FileRotateAppender {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.writer.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
use std::fmt;
impl Debug for FileRotateAppender {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FileRotateAppender").finish()
}
}