use crate::utils::clonecell::CloneCell;
use log::Level;
use log::LevelFilter;
use log::Log;
use log::Metadata;
use log::Record;
use std::fmt::Write as FmtWrite;
use std::io::Write;
use std::rc::Rc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::time::SystemTime;
use uapi::Fd;
use uapi::OwnedFd;
static LEVEL: AtomicUsize = AtomicUsize::new(Level::Info as usize);
thread_local! {
static FILE: CloneCell<Option<Rc<OwnedFd>>> = const { CloneCell::new(None) };
}
pub fn install() {
let _ = log::set_logger(&Logger);
log::set_max_level(LevelFilter::Info);
}
pub fn set_level(level: Level) {
LEVEL.store(level as usize, Ordering::Relaxed);
log::set_max_level(level.to_level_filter());
}
pub fn set_file(file: Rc<OwnedFd>) {
FILE.with(|f| f.set(Some(file)));
}
pub fn unset_file() {
FILE.with(|f| f.set(None));
}
struct Logger;
impl Log for Logger {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.level() as usize <= LEVEL.load(Ordering::Relaxed)
}
fn log(&self, record: &Record<'_>) {
if record.level() as usize > LEVEL.load(Ordering::Relaxed) {
return;
}
let mut buf = String::new();
let now = SystemTime::now();
let _ = if let Some(mp) = record.module_path() {
writeln!(
buf,
"[{} {:5} {}] {}",
humantime::format_rfc3339_millis(now),
record.level(),
mp,
record.args(),
)
} else {
writeln!(
buf,
"[{} {:5}] {}",
humantime::format_rfc3339_millis(now),
record.level(),
record.args(),
)
};
let mut fd = match FILE.with(|f| f.get()) {
Some(f) => f.borrow(),
_ => Fd::new(2),
};
let _ = fd.write_all(buf.as_bytes());
}
fn flush(&self) {
}
}