use alloc::sync::Arc;
use std::fs;
use std::io::Write as _;
use std::path::Path;
use std::sync::Mutex;
use env_logger::Logger as EnvLogger;
use log::{LevelFilter, Log, Metadata, Record};
struct ArcsecLogger {
stderr: Option<EnvLogger>,
file: Option<Arc<Mutex<fs::File>>>,
}
impl Log for ArcsecLogger {
fn enabled(&self, m: &Metadata<'_>) -> bool {
self.stderr
.as_ref()
.map_or_else(|| self.file.is_some(), |l| l.enabled(m))
}
fn log(&self, r: &Record<'_>) {
if let Some(l) = &self.stderr {
l.log(r);
}
if let Some(f) = &self.file {
let line = format!("{} {}", hms_now(), r.args());
if let Ok(mut g) = f.lock() {
let _ = writeln!(g, "{line}");
}
}
}
fn flush(&self) {
if let Some(l) = &self.stderr {
l.flush();
}
}
}
pub fn install(progress: bool, log_path: Option<&Path>) {
let file = log_path.and_then(|lp| match fs::File::create(lp) {
Ok(f) => Some(Arc::new(Mutex::new(f))),
Err(e) => {
eprintln!("Warning: cannot create {}: {e}", lp.display());
None
}
});
let stderr = progress.then(|| {
let mut b = env_logger::Builder::new();
b.filter_level(LevelFilter::Info);
b.format(|buf, r| writeln!(buf, "{} {}", hms_now(), r.args()));
b.build()
});
log::set_boxed_logger(Box::new(ArcsecLogger { stderr, file })).ok();
log::set_max_level(if progress || log_path.is_some() {
LevelFilter::Info
} else {
LevelFilter::Off
});
}
fn hms_now() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let s = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| d.as_secs())
% 86400;
format!("{:02}:{:02}:{:02}", s / 3600, (s % 3600) / 60, s % 60)
}