proxy_sdk/
logger.rs

1use log::{Level, LevelFilter};
2
3use crate::hostcalls::{self, LogLevel};
4use std::borrow::Cow;
5use std::panic;
6use std::sync::atomic::{AtomicBool, Ordering};
7
8struct Logger;
9
10static LOGGER: Logger = Logger;
11static INITIALIZED: AtomicBool = AtomicBool::new(false);
12
13impl From<Level> for LogLevel {
14    fn from(val: Level) -> Self {
15        match val {
16            Level::Error => LogLevel::Error,
17            Level::Warn => LogLevel::Warn,
18            Level::Info => LogLevel::Info,
19            Level::Debug => LogLevel::Debug,
20            Level::Trace => LogLevel::Trace,
21        }
22    }
23}
24
25impl From<LogLevel> for LevelFilter {
26    fn from(val: LogLevel) -> Self {
27        match val {
28            LogLevel::Trace => LevelFilter::Trace,
29            LogLevel::Debug => LevelFilter::Debug,
30            LogLevel::Info => LevelFilter::Info,
31            LogLevel::Warn => LevelFilter::Warn,
32            LogLevel::Error => LevelFilter::Error,
33            LogLevel::Critical => LevelFilter::Off,
34        }
35    }
36}
37
38/// Sets the log level filter and installs a panic hook to log out panics.
39pub fn set_log_level(level: Level) {
40    if !INITIALIZED.load(Ordering::Relaxed) {
41        log::set_logger(&LOGGER).unwrap();
42        panic::set_hook(Box::new(|panic_info| {
43            hostcalls::log(LogLevel::Critical, &panic_info.to_string()).unwrap();
44        }));
45        INITIALIZED.store(true, Ordering::Relaxed);
46    }
47    LOGGER.set_log_level(level.into());
48}
49
50impl Logger {
51    pub fn set_log_level(&self, level: LogLevel) {
52        log::set_max_level(level.into());
53    }
54}
55
56impl log::Log for Logger {
57    fn enabled(&self, metadata: &log::Metadata) -> bool {
58        metadata.level() <= log::max_level()
59    }
60
61    fn log(&self, record: &log::Record) {
62        if self.enabled(record.metadata()) {
63            let args = record.args();
64            let message = match args.as_str() {
65                Some(v) => Cow::Borrowed(v),
66                None => Cow::Owned(args.to_string()),
67            };
68            hostcalls::log(record.level().into(), &message).unwrap();
69        }
70    }
71
72    fn flush(&self) {}
73}