1use env_logger::fmt::Formatter;
6use log::{Level, Record};
7#[cfg(feature = "log_with_time")]
10use std::sync::atomic::AtomicU8;
11use std::{
12 io,
13 io::Write,
14 sync::atomic::{AtomicBool, AtomicUsize, Ordering},
15};
16
17static MAX_MODULE_LEN: AtomicUsize = AtomicUsize::new(0);
18static SHOW_MODULE: AtomicBool = AtomicBool::new(true);
19static SHOW_EMOJIS: AtomicBool = AtomicBool::new(true);
20#[cfg(feature = "log_with_time")]
21static SHOW_TIME: AtomicU8 = AtomicU8::new(env_logger::TimestampPrecision::Seconds as u8);
22pub use env_logger;
27
28pub fn get_set_max_module_len(len: usize) -> usize {
34 let module_len = MAX_MODULE_LEN.load(Ordering::Relaxed);
35 if module_len < len {
36 MAX_MODULE_LEN.store(len, Ordering::Relaxed);
37 }
38 module_len
39}
40
41#[allow(clippy::missing_errors_doc)]
45pub fn format(buf: &mut Formatter, record: &Record<'_>) -> io::Result<()> {
46 let mut bold = buf.style();
47 bold.set_bold(true);
48 let mut dimmed = buf.style();
49 dimmed.set_dimmed(true);
50
51 #[cfg(feature = "log_with_time")]
52 {
53 let show_time = SHOW_TIME.load(Ordering::Relaxed);
54 match unsafe { std::mem::transmute::<u8, env_logger::TimestampPrecision>(show_time) } {
57 env_logger::TimestampPrecision::Seconds => {
58 write!(buf, "{} ", dimmed.value(buf.timestamp_seconds()))
59 }
60 env_logger::TimestampPrecision::Millis => {
61 write!(buf, "{} ", dimmed.value(buf.timestamp_millis()))
62 }
63 env_logger::TimestampPrecision::Micros => {
64 write!(buf, "{} ", dimmed.value(buf.timestamp_micros()))
65 }
66 env_logger::TimestampPrecision::Nanos => {
67 write!(buf, "{} ", dimmed.value(buf.timestamp_nanos()))
68 }
69 }?;
70 }
71
72 let level_style = buf.default_level_style(record.level());
73 let level_symbol = if SHOW_EMOJIS.load(Ordering::Relaxed) {
74 match record.level() {
75 Level::Trace => "🔬",
77 Level::Debug => " ⚙️",
78 Level::Info => " ℹ",
79 Level::Warn => " ⚠",
80 Level::Error => "💥",
81 }
82 } else {
83 ""
84 };
85 write!(buf, "{level_symbol} {:5} ", level_style.value(record.level()))?;
86
87 if SHOW_MODULE.load(Ordering::Relaxed) {
88 let module = record.module_path().unwrap_or_default();
89 let module_with_line_nr = module.to_owned() + "::" + &record.line().unwrap_or(0).to_string();
90 let module_len = get_set_max_module_len(module_with_line_nr.len() + 2); write!(buf, "{:module_len$} {} ", dimmed.value(module_with_line_nr), bold.value('>'))?;
92 }
93
94 writeln!(buf, "{}", record.args())
99}