calib_targets_core/
logger.rs1use std::io::Write;
7use std::sync::OnceLock;
8use std::time::Instant;
9
10use log::{LevelFilter, Log, Metadata, Record};
11
12#[cfg(feature = "tracing")]
13use tracing_subscriber::fmt::format::FmtSpan;
14#[cfg(feature = "tracing")]
15use tracing_subscriber::util::SubscriberInitExt;
16#[cfg(feature = "tracing")]
17use tracing_subscriber::{fmt, EnvFilter};
18
19struct SimpleLogger {
20 level: LevelFilter,
21 started: Instant,
22}
23
24impl Log for SimpleLogger {
25 fn enabled(&self, metadata: &Metadata) -> bool {
26 metadata.level() <= self.level
27 }
28
29 fn log(&self, record: &Record) {
30 if !self.enabled(record.metadata()) {
31 return;
32 }
33
34 let elapsed = self.started.elapsed().as_secs_f64();
35 let mut stderr = std::io::stderr();
36 let _ = writeln!(
37 stderr,
38 "[{:7.3}s {:>5}] {}",
39 elapsed,
40 record.level(),
41 record.args()
42 );
43 }
44
45 fn flush(&self) {}
46}
47
48static LOGGER: OnceLock<SimpleLogger> = OnceLock::new();
49
50pub fn init_with_level(level: LevelFilter) -> Result<(), log::SetLoggerError> {
55 if LOGGER.get().is_none() {
56 let logger = LOGGER.get_or_init(|| SimpleLogger {
57 level,
58 started: Instant::now(),
59 });
60 log::set_logger(logger)?;
61 log::set_max_level(level);
62 }
63 Ok(())
64}
65
66#[cfg(feature = "tracing")]
67pub fn init_tracing(json: bool) {
68 let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
69 if json {
70 let _ = fmt()
71 .with_env_filter(filter)
72 .with_span_events(FmtSpan::CLOSE)
73 .json()
74 .flatten_event(true)
75 .finish()
76 .try_init();
77 } else {
78 let _ = fmt()
79 .with_env_filter(filter)
80 .with_span_events(FmtSpan::CLOSE)
81 .with_timer(fmt::time::Uptime::default())
82 .finish()
83 .try_init();
84 }
85}