mod rotating;
use std::path::PathBuf;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
pub use rotating::SizeRotatingWriter;
pub struct LogConfig {
pub log_dir: PathBuf,
pub file_name: String,
pub default_filter: String,
pub max_file_size: u64,
pub max_files: usize,
pub foreground: bool,
}
impl Default for LogConfig {
fn default() -> Self {
Self {
log_dir: PathBuf::from("."),
file_name: "app.log".to_string(),
default_filter: "info".to_string(),
max_file_size: 10 * 1024 * 1024,
max_files: 5,
foreground: false,
}
}
}
pub struct LogGuard {
_file_guard: WorkerGuard,
}
impl LogGuard {
pub fn flush(self) {
drop(self);
}
}
pub fn init(config: LogConfig) -> LogGuard {
std::fs::create_dir_all(&config.log_dir).expect("failed to create log directory");
let rotating_writer = SizeRotatingWriter::new(
config.log_dir.join(&config.file_name),
config.max_file_size,
config.max_files,
);
let (non_blocking, file_guard) = tracing_appender::non_blocking(rotating_writer);
let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| config.default_filter.into());
let file_layer = tracing_subscriber::fmt::layer()
.json()
.with_target(true)
.with_writer(non_blocking);
let stderr_layer = config.foreground.then(|| {
tracing_subscriber::fmt::layer()
.with_target(false)
.with_writer(std::io::stderr)
});
tracing_subscriber::registry()
.with(env_filter)
.with(file_layer)
.with(stderr_layer)
.init();
LogGuard {
_file_guard: file_guard,
}
}
#[cfg(feature = "sentry")]
pub fn init_with_sentry(config: LogConfig) -> LogGuard {
std::fs::create_dir_all(&config.log_dir).expect("failed to create log directory");
let rotating_writer = SizeRotatingWriter::new(
config.log_dir.join(&config.file_name),
config.max_file_size,
config.max_files,
);
let (non_blocking, file_guard) = tracing_appender::non_blocking(rotating_writer);
let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| config.default_filter.into());
let file_layer = tracing_subscriber::fmt::layer()
.json()
.with_target(true)
.with_writer(non_blocking);
let stderr_layer = config.foreground.then(|| {
tracing_subscriber::fmt::layer()
.with_target(false)
.with_writer(std::io::stderr)
});
let sentry_layer = sentry::integrations::tracing::layer();
tracing_subscriber::registry()
.with(env_filter)
.with(file_layer)
.with(stderr_layer)
.with(sentry_layer)
.init();
LogGuard {
_file_guard: file_guard,
}
}