jam_tooling/
log.rs

1use colored::Colorize;
2use env_logger::{
3	fmt::{Color, Formatter},
4	Builder as LogBuilder,
5};
6use log::LevelFilter;
7use std::io::{IsTerminal, Write};
8
9#[derive(Debug, PartialEq, Clone)]
10pub struct Config {
11	pub mode: Option<String>,
12	pub color: bool,
13	pub file: Option<String>,
14}
15
16impl Default for Config {
17	fn default() -> Self {
18		Config { mode: None, color: !cfg!(windows), file: None }
19	}
20}
21
22pub static LOG_ENABLED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(true);
23
24pub fn setup_log(config: &Config) {
25	let mut levels = String::new();
26	let mut builder = LogBuilder::new();
27
28	builder.filter(None, LevelFilter::Info);
29
30	if let Ok(lvl) = std::env::var("RUST_LOG") {
31		levels.push_str(&lvl);
32		levels.push(',');
33		builder.parse_filters(&lvl);
34	}
35
36	if let Some(ref s) = config.mode {
37		levels.push_str(s);
38		builder.parse_filters(s);
39	}
40
41	let isatty = std::io::stderr().is_terminal();
42	let enable_color = config.color && isatty;
43
44	let format = move |buf: &mut Formatter, record: &log::Record| {
45		let mut bold = buf.style();
46		bold.set_bold(true);
47		let mut blue_bold = buf.style();
48		blue_bold.set_color(Color::Blue).set_bold(true);
49
50		let dt = chrono::Local::now();
51		let timestamp = dt.format("%Y-%m-%d %H:%M:%S");
52
53		let with_color = if enable_color && log::max_level() <= LevelFilter::Info {
54			format!("{} {}", bold.value(timestamp), record.args(),)
55		} else {
56			let name = std::thread::current()
57				.name()
58				.map_or_else(Default::default, |x| format!("{}", blue_bold.value(x)));
59			format!(
60				"{} {} {} {}  {}",
61				bold.value(timestamp),
62				name,
63				record.level(),
64				record.target(),
65				record.args()
66			)
67		};
68
69		if !isatty && record.level() <= log::Level::Info && std::io::stdout().is_terminal() {
70			// duplicate INFO/WARN output to console
71			println!("{}", with_color);
72		}
73
74		if LOG_ENABLED.load(std::sync::atomic::Ordering::Relaxed) {
75			writeln!(buf, "{}", with_color.dimmed())?;
76		}
77		Ok(())
78	};
79
80	builder.format(format);
81	let _ = builder.try_init();
82}