1#[cfg(feature = "termcolor")]
2use log::Level;
3use log::LevelFilter;
45pub use chrono::offset::{FixedOffset, Local, Offset, TimeZone, Utc};
6use std::borrow::Cow;
7#[cfg(feature = "termcolor")]
8use termcolor::Color;
910#[derive(Debug, Clone, Copy)]
11/// Padding to be used for logging the level
12pub enum LevelPadding {
13/// Add spaces on the left side
14Left,
15/// Add spaces on the right side
16Right,
17/// Do not pad the level
18Off,
19}
2021#[derive(Debug, Clone, Copy)]
22/// Padding to be used for logging the thread id/name
23pub enum ThreadPadding {
24/// Add spaces on the left side, up to usize many
25Left(usize),
26/// Add spaces on the right side, up to usize many
27Right(usize),
28/// Do not pad the thread id/name
29Off,
30}
3132#[derive(Debug, Clone, Copy, PartialEq)]
33/// Mode for logging the thread name or id or both.
34pub enum ThreadLogMode {
35/// Log thread ids only
36IDs,
37/// Log the thread names only
38Names,
39/// If this thread is named, log the name. Otherwise, log the thread id.
40Both,
41}
4243/// Configuration for the Loggers
44///
45/// All loggers print the message in the following form:
46/// `00:00:00 [LEVEL] crate::module: [lib.rs::100] your_message`
47/// Every space delimited part except the actual message is optional.
48///
49/// Pass this struct to your logger to change when these information shall
50/// be logged.
51///
52/// Construct using `Default` or using `ConfigBuilder`
53#[derive(Debug, Clone)]
54pub struct Config {
55pub(crate) time: LevelFilter,
56pub(crate) level: LevelFilter,
57pub(crate) level_padding: LevelPadding,
58pub(crate) thread: LevelFilter,
59pub(crate) thread_log_mode: ThreadLogMode,
60pub(crate) thread_padding: ThreadPadding,
61pub(crate) target: LevelFilter,
62pub(crate) location: LevelFilter,
63pub(crate) time_format: Cow<'static, str>,
64pub(crate) time_offset: FixedOffset,
65pub(crate) time_local: bool,
66pub(crate) filter_allow: Cow<'static, [Cow<'static, str>]>,
67pub(crate) filter_ignore: Cow<'static, [Cow<'static, str>]>,
68#[cfg(feature = "termcolor")]
69pub(crate) level_color: [Option<Color>; 6],
70}
7172/// Builder for the Logger Configurations (`Config`)
73///
74/// All loggers print the message in the following form:
75/// `00:00:00 [LEVEL] crate::module: [lib.rs::100] your_message`
76/// Every space delimited part except the actual message is optional.
77///
78/// Use this struct to create a custom `Config` changing when these information shall
79/// be logged. Every part can be enabled for a specific Level and is then
80/// automatically enable for all lower levels as well.
81///
82/// The Result is that the logging gets more detailed the more verbose it gets.
83/// E.g. to have one part shown always use `Level::Error`. But if you
84/// want to show the source line only on `Trace` use that.
85#[derive(Debug, Clone)]
86#[non_exhaustive]
87pub struct ConfigBuilder(Config);
8889impl ConfigBuilder {
90/// Create a new default ConfigBuilder
91pub fn new() -> ConfigBuilder {
92 ConfigBuilder(Config::default())
93 }
9495/// Set at which level and above (more verbose) the level itself shall be logged (default is Error)
96pub fn set_max_level(&mut self, level: LevelFilter) -> &mut ConfigBuilder {
97self.0.level = level;
98self
99}
100101/// Set at which level and above (more verbose) the current time shall be logged (default is Error)
102pub fn set_time_level(&mut self, time: LevelFilter) -> &mut ConfigBuilder {
103self.0.time = time;
104self
105}
106107/// Set at which level and above (more verbose) the thread id shall be logged. (default is Debug)
108pub fn set_thread_level(&mut self, thread: LevelFilter) -> &mut ConfigBuilder {
109self.0.thread = thread;
110self
111}
112113/// Set at which level and above (more verbose) the target shall be logged. (default is Debug)
114pub fn set_target_level(&mut self, target: LevelFilter) -> &mut ConfigBuilder {
115self.0.target = target;
116self
117}
118119/// Set at which level and above (more verbose) a source code reference shall be logged (default is Trace)
120pub fn set_location_level(&mut self, location: LevelFilter) -> &mut ConfigBuilder {
121self.0.location = location;
122self
123}
124125/// Set how the levels should be padded, when logging (default is Off)
126pub fn set_level_padding(&mut self, padding: LevelPadding) -> &mut ConfigBuilder {
127self.0.level_padding = padding;
128self
129}
130131/// Set how the thread should be padded
132pub fn set_thread_padding(&mut self, padding: ThreadPadding) -> &mut ConfigBuilder {
133self.0.thread_padding = padding;
134self
135}
136137/// Set the mode for logging the thread
138pub fn set_thread_mode(&mut self, mode: ThreadLogMode) -> &mut ConfigBuilder {
139self.0.thread_log_mode = mode;
140self
141}
142143/// Set the color used for printing the level (if the logger supports it),
144 /// or None to use the default foreground color
145#[cfg(feature = "termcolor")]
146pub fn set_level_color(&mut self, level: Level, color: Option<Color>) -> &mut ConfigBuilder {
147self.0.level_color[level as usize] = color;
148self
149}
150151/// Set time chrono [strftime] format string.
152 ///
153 /// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers
154pub fn set_time_format_str(&mut self, time_format: &'static str) -> &mut ConfigBuilder {
155self.0.time_format = Cow::Borrowed(time_format);
156self
157}
158159/// Set time chrono [strftime] format string.
160 ///
161 /// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers
162pub fn set_time_format(&mut self, time_format: String) -> &mut ConfigBuilder {
163self.0.time_format = Cow::Owned(time_format);
164self
165}
166167/// Set offset used for logging time (default is 0)
168pub fn set_time_offset(&mut self, time_offset: FixedOffset) -> &mut ConfigBuilder {
169self.0.time_offset = time_offset;
170self
171}
172173/// set if you log in local timezone or UTC (default is UTC)
174pub fn set_time_to_local(&mut self, local: bool) -> &mut ConfigBuilder {
175self.0.time_local = local;
176self
177}
178179/// Add allowed module filters.
180 /// If any are specified, only records from modules starting with one of these entries will be printed
181 ///
182 /// For example, `add_filter_allow_str("tokio::uds")` would allow only logging from the `tokio` crates `uds` module.
183pub fn add_filter_allow_str(&mut self, filter_allow: &'static str) -> &mut ConfigBuilder {
184let mut list = Vec::from(&*self.0.filter_allow);
185 list.push(Cow::Borrowed(filter_allow));
186self.0.filter_allow = Cow::Owned(list);
187self
188}
189190/// Add allowed module filters.
191 /// If any are specified, only records from modules starting with one of these entries will be printed
192 ///
193 /// For example, `add_filter_allow(format!("{}{}","tokio", "uds"))` would allow only logging from the `tokio` crates `uds` module.
194pub fn add_filter_allow(&mut self, filter_allow: String) -> &mut ConfigBuilder {
195let mut list = Vec::from(&*self.0.filter_allow);
196 list.push(Cow::Owned(filter_allow));
197self.0.filter_allow = Cow::Owned(list);
198self
199}
200201/// Clear allowed module filters.
202 /// If none are specified, nothing is filtered out
203pub fn clear_filter_allow(&mut self) -> &mut ConfigBuilder {
204self.0.filter_allow = Cow::Borrowed(&[]);
205self
206}
207208/// Add denied module filters.
209 /// If any are specified, records from modules starting with one of these entries will be ignored
210 ///
211 /// For example, `add_filter_ignore_str("tokio::uds")` would deny logging from the `tokio` crates `uds` module.
212pub fn add_filter_ignore_str(&mut self, filter_ignore: &'static str) -> &mut ConfigBuilder {
213let mut list = Vec::from(&*self.0.filter_ignore);
214 list.push(Cow::Borrowed(filter_ignore));
215self.0.filter_ignore = Cow::Owned(list);
216self
217}
218219/// Add denied module filters.
220 /// If any are specified, records from modules starting with one of these entries will be ignored
221 ///
222 /// For example, `add_filter_ignore(format!("{}{}","tokio", "uds"))` would deny logging from the `tokio` crates `uds` module.
223pub fn add_filter_ignore(&mut self, filter_ignore: String) -> &mut ConfigBuilder {
224let mut list = Vec::from(&*self.0.filter_ignore);
225 list.push(Cow::Owned(filter_ignore));
226self.0.filter_ignore = Cow::Owned(list);
227self
228}
229230/// Clear ignore module filters.
231 /// If none are specified, nothing is filtered
232pub fn clear_filter_ignore(&mut self) -> &mut ConfigBuilder {
233self.0.filter_ignore = Cow::Borrowed(&[]);
234self
235}
236237/// Build new `Config`
238pub fn build(&mut self) -> Config {
239self.0.clone()
240 }
241}
242243impl Default for ConfigBuilder {
244fn default() -> Self {
245 ConfigBuilder::new()
246 }
247}
248249impl Default for Config {
250fn default() -> Config {
251 Config {
252 time: LevelFilter::Error,
253 level: LevelFilter::Error,
254 level_padding: LevelPadding::Off,
255 thread: LevelFilter::Debug,
256 thread_log_mode: ThreadLogMode::IDs,
257 thread_padding: ThreadPadding::Off,
258 target: LevelFilter::Debug,
259 location: LevelFilter::Trace,
260 time_format: Cow::Borrowed("%H:%M:%S"),
261 time_offset: FixedOffset::east(0),
262 time_local: false,
263 filter_allow: Cow::Borrowed(&[]),
264 filter_ignore: Cow::Borrowed(&[]),
265266#[cfg(feature = "termcolor")]
267level_color: [
268None, // Default foreground
269Some(Color::Red), // Error
270Some(Color::Yellow), // Warn
271Some(Color::Blue), // Info
272Some(Color::Cyan), // Debug
273Some(Color::White), // Trace
274],
275 }
276 }
277}