1use crate::handler::HandlerRef;
2use crate::level::LogLevel;
3use std::fs;
4use std::io;
5use std::path::PathBuf;
6use toml;
7
8#[derive(Debug)]
10pub struct LoggerConfig {
11 pub level: LogLevel,
13 pub handlers: Vec<HandlerRef>,
15 pub capture_source: bool,
17 pub use_colors: bool,
19 pub format: String,
21}
22
23impl Clone for LoggerConfig {
24 fn clone(&self) -> Self {
25 Self {
26 level: self.level,
27 handlers: self.handlers.clone(),
28 capture_source: self.capture_source,
29 use_colors: self.use_colors,
30 format: self.format.clone(),
31 }
32 }
33}
34
35impl Default for LoggerConfig {
36 fn default() -> Self {
37 Self {
38 level: LogLevel::Info,
39 handlers: Vec::new(),
40 capture_source: true,
41 use_colors: true,
42 format: "{time} {level} {message}".to_string(),
43 }
44 }
45}
46
47#[derive(Debug)]
49pub struct LoggerConfigBuilder {
50 config: LoggerConfig,
51}
52
53impl Default for LoggerConfigBuilder {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl LoggerConfigBuilder {
60 pub fn new() -> Self {
62 Self {
63 config: LoggerConfig::default(),
64 }
65 }
66
67 pub fn level(mut self, level: LogLevel) -> Self {
69 self.config.level = level;
70 self
71 }
72
73 pub fn add_handler(mut self, handler: HandlerRef) -> Self {
75 self.config.handlers.push(handler);
76 self
77 }
78
79 pub fn capture_source(mut self, capture: bool) -> Self {
81 self.config.capture_source = capture;
82 self
83 }
84
85 pub fn use_colors(mut self, use_colors: bool) -> Self {
87 self.config.use_colors = use_colors;
88 self
89 }
90
91 pub fn format(mut self, format: String) -> Self {
93 self.config.format = format;
94 self
95 }
96
97 pub fn with_env_overrides(mut self) -> Self {
105 use std::env;
106 if let Ok(level) = env::var("LOGURU_LEVEL") {
107 if let Ok(parsed) = level.parse::<LogLevel>() {
108 self.config.level = parsed;
109 } else {
110 let level_up = level.to_ascii_uppercase();
112 if let Ok(parsed) = level_up.parse::<LogLevel>() {
113 self.config.level = parsed;
114 }
115 }
116 }
117 if let Ok(capture_source) = env::var("LOGURU_CAPTURE_SOURCE") {
118 self.config.capture_source =
119 matches!(capture_source.as_str(), "1" | "true" | "TRUE" | "True");
120 }
121 if let Ok(use_colors) = env::var("LOGURU_USE_COLORS") {
122 self.config.use_colors = matches!(use_colors.as_str(), "1" | "true" | "TRUE" | "True");
123 }
124 if let Ok(format) = env::var("LOGURU_FORMAT") {
125 self.config.format = format;
126 }
127 self
128 }
129
130 pub fn build(self) -> LoggerConfig {
132 self.config
133 }
134
135 pub fn from_toml_str(mut self, toml_str: &str) -> Result<Self, toml::de::Error> {
143 let toml_cfg: LoggerConfigToml = toml::from_str(toml_str)?;
144 if let Some(level) = toml_cfg.level {
145 if let Ok(parsed) = level.parse::<LogLevel>() {
146 self.config.level = parsed;
147 }
148 }
149 if let Some(capture_source) = toml_cfg.capture_source {
150 self.config.capture_source = capture_source;
151 }
152 if let Some(use_colors) = toml_cfg.use_colors {
153 self.config.use_colors = use_colors;
154 }
155 if let Some(format) = toml_cfg.format {
156 self.config.format = format;
157 }
158 Ok(self)
159 }
160
161 pub fn from_toml_file<P: AsRef<std::path::Path>>(self, path: P) -> Result<Self, io::Error> {
163 let content = fs::read_to_string(path)?;
164 self.from_toml_str(&content)
166 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
167 }
168}
169
170impl LoggerConfig {
172 pub fn basic_console() -> LoggerConfig {
174 LoggerConfigBuilder::new()
175 .level(LogLevel::Info)
176 .use_colors(true)
177 .build()
178 }
179
180 pub fn file_logging(_path: PathBuf) -> LoggerConfig {
182 LoggerConfigBuilder::new()
183 .level(LogLevel::Info)
184 .use_colors(false)
185 .build()
186 }
187
188 pub fn development() -> LoggerConfig {
190 LoggerConfigBuilder::new()
191 .level(LogLevel::Debug)
192 .use_colors(true)
193 .capture_source(true)
194 .format("{time} {level} {file}:{line} {message}".to_string())
195 .build()
196 }
197
198 pub fn production() -> LoggerConfig {
200 LoggerConfigBuilder::new()
201 .level(LogLevel::Info)
202 .use_colors(false)
203 .capture_source(false)
204 .format("{time} {level} {message}".to_string())
205 .build()
206 }
207}
208
209#[derive(serde::Deserialize, Debug, Default)]
210struct LoggerConfigToml {
211 level: Option<String>,
212 capture_source: Option<bool>,
213 use_colors: Option<bool>,
214 format: Option<String>,
215}