use core::fmt;
use anstyle::AnsiColor;
use log::{Level, LevelFilter, Metadata, Record};
struct KernelLogger;
impl log::Log for KernelLogger {
fn enabled(&self, _: &Metadata<'_>) -> bool {
true
}
fn flush(&self) {
}
fn log(&self, record: &Record<'_>) {
if self.enabled(record.metadata()) {
println!(
"[{}][{}] {}",
crate::arch::core_local::core_id(),
ColorLevel(record.level()),
record.args()
);
}
}
}
struct ColorLevel(Level);
impl fmt::Display for ColorLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let level = self.0;
if no_color() {
write!(f, "{level}")
} else {
let color = match level {
Level::Trace => AnsiColor::Magenta,
Level::Debug => AnsiColor::Blue,
Level::Info => AnsiColor::Green,
Level::Warn => AnsiColor::Yellow,
Level::Error => AnsiColor::Red,
};
let style = anstyle::Style::new().fg_color(Some(color.into()));
write!(f, "{style}{level}{style:#}")
}
}
}
fn no_color() -> bool {
option_env!("NO_COLOR").is_some_and(|val| !val.is_empty())
}
pub unsafe fn init() {
log::set_logger(&KernelLogger).expect("Can't initialize logger");
let log_level: Option<&'static str> = option_env!("HERMIT_LOG_LEVEL_FILTER");
let mut max_level = LevelFilter::Info;
if let Some(log_level) = log_level {
max_level = if log_level.eq_ignore_ascii_case("off") {
LevelFilter::Off
} else if log_level.eq_ignore_ascii_case("error") {
LevelFilter::Error
} else if log_level.eq_ignore_ascii_case("warn") {
LevelFilter::Warn
} else if log_level.eq_ignore_ascii_case("info") {
LevelFilter::Info
} else if log_level.eq_ignore_ascii_case("debug") {
LevelFilter::Debug
} else if log_level.eq_ignore_ascii_case("trace") {
LevelFilter::Trace
} else {
error!("Could not parse HERMIT_LOG_LEVEL_FILTER, falling back to `info`.");
LevelFilter::Info
};
}
log::set_max_level(max_level);
}
#[cfg(any(not(target_arch = "riscv64"), feature = "pci", feature = "tcp"))]
macro_rules! infoheader {
($str:expr) => {{
::log::info!("");
::log::info!("{:=^70}", $str);
}};
}
#[cfg_attr(target_arch = "riscv64", allow(unused))]
macro_rules! infoentry {
($str:expr, $rhs:expr) => (infoentry!($str, "{}", $rhs));
($str:expr, $($arg:tt)+) => (::log::info!("{:25}{}", concat!($str, ":"), format_args!($($arg)+)));
}
#[cfg(any(not(target_arch = "riscv64"), feature = "pci", feature = "tcp"))]
macro_rules! infofooter {
() => {{
::log::info!("{:=^70}", '=');
::log::info!("");
}};
}