use crate::handler::HandlerRef;
use crate::level::LogLevel;
use std::fs;
use std::io;
use std::path::PathBuf;
use toml;
#[derive(Debug)]
pub struct LoggerConfig {
pub level: LogLevel,
pub handlers: Vec<HandlerRef>,
pub capture_source: bool,
pub use_colors: bool,
pub format: String,
}
impl Clone for LoggerConfig {
fn clone(&self) -> Self {
Self {
level: self.level,
handlers: self.handlers.clone(),
capture_source: self.capture_source,
use_colors: self.use_colors,
format: self.format.clone(),
}
}
}
impl Default for LoggerConfig {
fn default() -> Self {
Self {
level: LogLevel::Info,
handlers: Vec::new(),
capture_source: true,
use_colors: true,
format: "{time} {level} {message}".to_string(),
}
}
}
#[derive(Debug)]
pub struct LoggerConfigBuilder {
config: LoggerConfig,
}
impl Default for LoggerConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl LoggerConfigBuilder {
pub fn new() -> Self {
Self {
config: LoggerConfig::default(),
}
}
pub fn level(mut self, level: LogLevel) -> Self {
self.config.level = level;
self
}
pub fn add_handler(mut self, handler: HandlerRef) -> Self {
self.config.handlers.push(handler);
self
}
pub fn capture_source(mut self, capture: bool) -> Self {
self.config.capture_source = capture;
self
}
pub fn use_colors(mut self, use_colors: bool) -> Self {
self.config.use_colors = use_colors;
self
}
pub fn format(mut self, format: String) -> Self {
self.config.format = format;
self
}
pub fn with_env_overrides(mut self) -> Self {
use std::env;
if let Ok(level) = env::var("LOGURU_LEVEL") {
if let Ok(parsed) = level.parse::<LogLevel>() {
self.config.level = parsed;
} else {
let level_up = level.to_ascii_uppercase();
if let Ok(parsed) = level_up.parse::<LogLevel>() {
self.config.level = parsed;
}
}
}
if let Ok(capture_source) = env::var("LOGURU_CAPTURE_SOURCE") {
self.config.capture_source =
matches!(capture_source.as_str(), "1" | "true" | "TRUE" | "True");
}
if let Ok(use_colors) = env::var("LOGURU_USE_COLORS") {
self.config.use_colors = matches!(use_colors.as_str(), "1" | "true" | "TRUE" | "True");
}
if let Ok(format) = env::var("LOGURU_FORMAT") {
self.config.format = format;
}
self
}
pub fn build(self) -> LoggerConfig {
self.config
}
pub fn from_toml_str(mut self, toml_str: &str) -> Result<Self, toml::de::Error> {
let toml_cfg: LoggerConfigToml = toml::from_str(toml_str)?;
if let Some(level) = toml_cfg.level {
if let Ok(parsed) = level.parse::<LogLevel>() {
self.config.level = parsed;
}
}
if let Some(capture_source) = toml_cfg.capture_source {
self.config.capture_source = capture_source;
}
if let Some(use_colors) = toml_cfg.use_colors {
self.config.use_colors = use_colors;
}
if let Some(format) = toml_cfg.format {
self.config.format = format;
}
Ok(self)
}
pub fn from_toml_file<P: AsRef<std::path::Path>>(self, path: P) -> Result<Self, io::Error> {
let content = fs::read_to_string(path)?;
self.from_toml_str(&content)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
}
impl LoggerConfig {
pub fn basic_console() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.use_colors(true)
.build()
}
pub fn file_logging(_path: PathBuf) -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.use_colors(false)
.build()
}
pub fn development() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Debug)
.use_colors(true)
.capture_source(true)
.format("{time} {level} {file}:{line} {message}".to_string())
.build()
}
pub fn production() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.use_colors(false)
.capture_source(false)
.format("{time} {level} {message}".to_string())
.build()
}
}
#[derive(serde::Deserialize, Debug, Default)]
struct LoggerConfigToml {
level: Option<String>,
capture_source: Option<bool>,
use_colors: Option<bool>,
format: Option<String>,
}