1#[cfg(feature = "color")]
37mod color;
38#[cfg(feature = "panic")]
39mod panic;
40mod config;
41
42pub use config::Config;
43pub use log::LevelFilter;
44pub use log::{error, warn, info, debug, trace};
45
46pub fn init(config: Config) -> Result<(), log::SetLoggerError> {
48 let level = config.level;
49
50 let logger = Box::new(Logger { config });
51
52 log::set_boxed_logger(logger).map(|()| {
53 log::set_max_level(level);
54 #[cfg(feature = "panic")]
55 panic::install_panic_hook();
56 })
57}
58
59pub fn init_with_level(level: log::LevelFilter) -> Result<(), log::SetLoggerError> {
61 init(Config { level, .. Default::default() })
62}
63
64pub fn init_with_default() -> Result<(), log::SetLoggerError> {
66 init(Default::default())
67}
68
69struct Logger {
70 config: Config
71}
72
73impl log::Log for Logger {
74 #[inline]
75 fn enabled(&self, metadata: &log::Metadata) -> bool {
76 self.config.level >= metadata.level()
77 }
78
79 fn log(&self, record: &log::Record) {
80 if !self.enabled(record.metadata()) {
81 return;
82 }
83
84 #[cfg(feature = "chrono")]
85 let time = chrono::Local::now().format(&self.config.datetime_format);
86
87 #[cfg(not(feature = "chrono"))]
88 let time = "";
89
90 #[cfg(feature = "color")]
91 let (sgr_in, sgr_out) = if color::color_enabled(&self.config) {
92 color::get_colors(record.level())
93 } else {
94 ("", "")
95 };
96
97 #[cfg(not(feature = "color"))]
98 let (sgr_in, sgr_out) = ("", "");
99
100 println!("{}[{}{:5}{}] {}", time, sgr_in, record.level(), sgr_out, record.args());
101 }
102
103 #[inline]
104 fn flush(&self) {
105 use std::io::Write;
106
107 std::io::stdout().flush().unwrap()
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use log::*;
114 use super::*;
115
116 #[test]
117 fn it_works() {
118 init_with_level(log::LevelFilter::max()).unwrap();
119
120 error!("Error!");
121 warn!("Warn!");
122 info!("Info!");
123 debug!("Debug!");
124 trace!("Trace!");
125 }
126}