x_log/
lib.rs

1#![allow(dead_code, unused_imports)]
2
3mod utils;
4
5use utils::{format_path};
6use log::{Level, Log, Metadata, Record, SetLoggerError};
7
8pub use utils::{Timezone};
9pub use log::{LevelFilter};
10
11
12cfg_if::cfg_if! {
13    if #[cfg(target_arch = "wasm32")]
14    {
15        use web_sys::console;
16        use wasm_bindgen::{JsValue};
17    } else {
18        use utils::{format_time};
19        use ansi_term::Color;
20    }
21}
22
23#[cfg(not(target_arch = "wasm32"))]
24static LOG_LEVEL_NAMES: [&str; 6] = ["N/A", "E", "W", "I", "D", "T"];
25
26#[cfg(not(target_arch = "wasm32"))]
27fn level_to_str(l: &Level) -> &'static str {
28    LOG_LEVEL_NAMES[*l as usize]
29}
30
31
32#[derive(Clone)]
33pub struct Options {
34    pub level: LevelFilter,
35    pub print_level: bool,
36    pub timezone: Timezone,
37    pub colored: bool,
38    pub mods: Vec<String>,
39}
40
41impl Default for Options {
42    fn default() -> Self {
43        Self {
44            level: LevelFilter::Trace,
45            print_level: true,
46            timezone: Timezone::Local,
47            colored: true,
48            mods: vec![],
49        }
50    }
51}
52
53pub struct XLog {
54    level: LevelFilter,
55    print_level: bool,
56    timezone: Timezone,
57    colored: bool,
58    mods: Vec<String>,
59}
60
61impl XLog {
62    #[must_use = "You must call init() to begin logging"]
63    pub fn new(opts: Options) -> XLog {
64        let Options {
65            level, print_level, timezone, colored, mods
66        } = opts;
67        XLog {
68            level,
69            print_level,
70            timezone,
71            colored,
72            mods,
73        }
74    }
75
76    pub fn init(self) -> Result<(), SetLoggerError> {
77        log::set_max_level(log::STATIC_MAX_LEVEL);
78        log::set_boxed_logger(Box::new(self))?;
79        Ok(())
80    }
81}
82
83impl Default for XLog {
84    fn default() -> Self {
85        XLog::new(Options::default())
86    }
87}
88
89impl Log for XLog {
90    fn enabled(&self, metadata: &Metadata) -> bool {
91        let target = metadata.target().to_string();
92        let mods: Vec<&str> = target.split("::").collect();
93
94        if self.mods.is_empty() == false {
95            let finds: Vec<&String> = self.mods.iter().filter_map(|x| {
96                if *x == mods[0].to_string() {
97                    Some(x)
98                } else {
99                    None
100                }
101            }).collect();
102            if finds.is_empty() {
103                return false;
104            }
105        }
106
107        metadata.level().to_level_filter() <= self.level
108    }
109
110    fn log(&self, record: &Record) {
111        if self.enabled(record.metadata()) {
112            let pathname = format_path(record.file().unwrap_or("???"),
113                                       record.line().unwrap_or(0));
114
115
116            #[cfg(target_arch = "wasm32")]
117            {
118                let level = match self.print_level {
119                    true => format!("{}", &record.level().as_str()),
120                    false => "".to_string()
121                };
122                let msg = format!("{}", record.args());
123                let level_pre = match record.level() {
124                    Level::Trace => "color: white; background: #747474",
125                    Level::Debug => "color: white; background: #2330da",
126                    Level::Info => "color: white; background: #00831c",
127                    Level::Warn => "color: white; background: #e17400",
128                    Level::Error => "color: white; background: #b90008",
129                };
130                let console_log = match record.level() {
131                    Level::Trace => console::debug_4,
132                    Level::Debug => console::log_4,
133                    Level::Info => console::info_4,
134                    Level::Warn => console::warn_4,
135                    Level::Error => console::error_4,
136                };
137                // let msg_pre = match record.level() {
138                //     Level::Trace => "color: #inherit",
139                //     Level::Debug => "color: #inherit",
140                //     Level::Info => "color: #inherit",
141                //     Level::Warn => "color: #e17400",
142                //     Level::Error => "color: #b90008",
143                // };
144                let msg_pre = "color: inherit";
145
146                console_log(
147                    &JsValue::from(format!("%c{}%c {} %c{}",
148                                           level, pathname, msg
149                    )),
150                    &JsValue::from(level_pre),
151                    &JsValue::from("color: inherit"),
152                    &JsValue::from(msg_pre),
153                );
154            }
155
156            #[cfg(not(target_arch = "wasm32"))]
157            {
158                let timestamp = format_time(&self.timezone);
159
160                let level = match self.print_level {
161                    true => format!("[{}] ", level_to_str(&record.level())),
162                    false => "".to_string()
163                };
164
165                let mut msg = format!("{}{}", level, record.args());
166
167                let mut pathname = pathname;
168                if self.colored {
169                    // timestamp = Color::Fixed(250).paint(timestamp).to_string();
170                    // let mut pathname =p pathname;
171                    pathname = Color::Blue.paint(pathname.as_str()).to_string();
172
173                    msg = match record.level() {
174                        Level::Trace => Color::White.paint(msg).to_string(),
175                        Level::Debug => Color::Blue.paint(msg).to_string(),
176                        Level::Info => Color::Green.paint(msg).to_string(),
177                        Level::Warn => Color::Yellow.paint(msg).to_string(),
178                        Level::Error => Color::Red.paint(msg).to_string(),
179                    };
180                }
181
182                let message = format!("{}{} {}", timestamp, pathname, msg);
183
184                #[cfg(not(feature = "stderr"))]
185                println!("{}", message);
186            }
187
188
189            #[cfg(feature = "stderr")]
190            eprintln!("{}", message);
191        }
192    }
193
194    fn flush(&self) {}
195}
196
197use std::sync::Once;
198
199static INIT: Once = Once::new();
200
201pub fn init_once(opts: Option<Options>) {
202    INIT.call_once(|| {
203        let opts = opts.unwrap_or_default();
204        XLog::new(opts).init().unwrap();
205        // log::log!
206    });
207}
208
209pub extern crate log;
210
211// pub use log::{trace, debug, info, warn, error};
212
213#[macro_export]
214macro_rules! trace {
215    // (target: $target:expr, $($arg:tt)+) => ({
216    //     log::log!(target: $target, log::Level::Trace, $($arg)+)
217    // });
218    ($($arg:tt)*) => ({
219        x_log::init_once(None);
220        $crate::log::log!(log::Level::Trace, $($arg)+);
221    });
222}
223
224#[macro_export]
225macro_rules! debug {
226    ($($arg:tt)*) => ({
227        x_log::init_once(None);
228        $crate::log::log!(log::Level::Debug, $($arg)+);
229    });
230}
231
232#[macro_export]
233macro_rules! info {
234    ($($arg:tt)*) => ({
235        x_log::init_once(None);
236        $crate::log::log!(log::Level::Info, $($arg)+);
237    });
238}
239
240#[macro_export]
241macro_rules! warn {
242    ($($arg:tt)*) => ({
243        x_log::init_once(None);
244        $crate::log::log!(log::Level::Warn, $($arg)+);
245    });
246}
247
248#[macro_export]
249macro_rules! error {
250    ($($arg:tt)*) => ({
251        x_log::init_once(None);
252        $crate::log::log!(log::Level::Error, $($arg)+);
253    });
254}
255////////////////////////////////////////////////////////////////////////////////
256#[doc(hidden)]
257pub use utils::__print_val;
258
259#[macro_export]
260macro_rules! __val {
261    ($fmt:expr, $($arg:tt)+) => (
262        x_log::__print_val(file!(), line!(), format_args!($fmt, $($arg)+));
263    )
264}
265
266/// value each line
267#[macro_export]
268macro_rules! val {
269    ($v:expr) => {
270        __val!("\n{}︎︎︎︎⏤►{:?}", stringify!($v), $v);
271    };
272    ($v:expr, $v2:expr) => {
273        __val!("\n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2,);
274    };
275    ($v:expr, $v2:expr, $v3:expr) => {
276        __val!("\n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3);
277    };
278    ($v:expr, $v2:expr, $v3:expr, $v4:expr) => {
279        __val!("\n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4);
280    };
281    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr) => {
282        __val!("\n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5);
283    };
284    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr, $v6:expr) => {
285        __val!("\n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?} \n{}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5, stringify!($v6), $v6);
286    };
287}
288
289/// pretty format
290#[macro_export]
291macro_rules! valf {
292    ($v:expr) => {
293        __val!("\n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v);
294    };
295    ($v:expr, $v2:expr) => {
296        __val!("\n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v, stringify!($v2), $v2,);
297    };
298    ($v:expr, $v2:expr, $v3:expr) => {
299        __val!("\n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3);
300    };
301    ($v:expr, $v2:expr, $v3:expr, $v4:expr) => {
302        __val!("\n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4);
303    };
304    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr) => {
305        __val!("\n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5);
306    };
307    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr, $v6:expr) => {
308        __val!("\n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?} \n{}︎︎︎︎⏤►{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5, stringify!($v6), $v6);
309    };
310}
311// macro_rules! valf {
312//     ($v:expr) => {
313//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v);
314//     };
315//     ($v:expr, $v2:expr) => {
316//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v, stringify!($v2), $v2,);
317//     };
318//     ($v:expr, $v2:expr, $v3:expr) => {
319//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3);
320//     };
321//     ($v:expr, $v2:expr, $v3:expr, $v4:expr) => {
322//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4);
323//     };
324//     ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr) => {
325//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5);
326//     };
327//     ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr, $v6:expr) => {
328//         __val!("\n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?} \n⏤⏤ {}︎︎︎︎ ⏤⏤\n{:#?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5, stringify!($v6), $v6);
329//     };
330// }
331
332/// all in one line
333#[macro_export]
334macro_rules! valn {
335    ($v:expr) => {
336        __val!("{}︎︎︎︎⏤►{:?}", stringify!($v), $v);
337    };
338    ($v:expr, $v2:expr) => {
339        __val!("{}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2,);
340    };
341    ($v:expr, $v2:expr, $v3:expr) => {
342        __val!("{}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3);
343    };
344    ($v:expr, $v2:expr, $v3:expr, $v4:expr) => {
345        __val!("{}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4);
346    };
347    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr) => {
348        __val!("{}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5);
349    };
350    ($v:expr, $v2:expr, $v3:expr, $v4:expr, $v5:expr, $v6:expr) => {
351        __val!("{}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}, {}︎︎︎︎⏤►{:?}", stringify!($v), $v, stringify!($v2), $v2, stringify!($v3), $v3, stringify!($v4), $v4, stringify!($v5), $v5, stringify!($v6), $v6);
352    };
353}