/* * Copyright (c) 2022, Able * * SPDX-License-Identifier: MPL-2.0 */ use crate::{kmain::KERNEL_CONF, time::fetch_time}; use lliw::Fg; use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; static LOGGER: SimpleLogger = SimpleLogger; // TODO: Rebuild this to take advantage of sockets // DETAIL: Log to a socket instead of the screen // So that we can log in the kernel and display it in userland struct SimpleLogger; impl log::Log for SimpleLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= Level::Trace } fn log(&self, record: &Record) { x86_64::instructions::interrupts::without_interrupts(|| { if self.enabled(record.metadata()) { let time_float = fetch_time(); use Fg::*; let color = match record.level() { log::Level::Error => (Fg::Red, "\0RED\0"), log::Level::Warn => (Fg::LightYellow, "\0LIGHTYELLOW\0"), log::Level::Info => (Fg::LightWhite, "\0LIGHTGREY\0"), log::Level::Debug => (Fg::Blue, "\0BLUE\0"), log::Level::Trace => (Fg::Yellow, "\0YELLOW\0"), }; let mod_path = match record.module_path() { Some(p) => { if KERNEL_CONF.logging.filter.contains(&p.to_string()) { return; } p } None => "unknown", }; let line = match record.line() { Some(line_number) => line_number, None => 0, }; if KERNEL_CONF.logging.log_to_vterm { let msg = format!( // "[{}{}$RESET$][$GREEN${}$RESET$]{}\n", "[{}{:05}\0RESET\0][\0GREEN\0{}\0RESET\0][\0BLUE\0{}@{}\0RESET\0] {}", color.1, record.level(), time_float, mod_path, line, record.args(), ); println!("{msg}"); } if KERNEL_CONF.logging.log_to_serial { serial_println!( "[{}{:05}{}][{}{}{}][{}{}@{}{}] {}", color.0, record.level(), Reset, Green, time_float, Reset, Blue, mod_path, line, Reset, record.args() ); } } }); } /// Clear the log buffer fn flush(&self) {} } pub fn init() -> Result<(), SetLoggerError> { log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Trace)) // ?; // trace!("Logger started"); // Ok(()) }