use core::fmt::{self, Write}; use alloc::string::ToString; use log::{info, Level, Log}; use super::lib_ui::textui::{textui_putstr, FontColor}; use crate::{ driver::tty::{tty_driver::TtyOperation, virtual_terminal::vc_manager}, filesystem::procfs::{ kmsg::KMSG, log::{LogLevel, LogMessage}, }, time::PosixTimeSpec, }; #[macro_export] macro_rules! print { ($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*))); } #[macro_export] macro_rules! println { () => { $crate::print!("\n"); }; ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } pub struct PrintkWriter; impl PrintkWriter { #[inline] pub fn __write_fmt(&mut self, args: fmt::Arguments) { self.write_fmt(args).ok(); } /// 并输出白底黑字 /// @param str: 要写入的字符 pub fn __write_string(&mut self, s: &str) { if let Some(current_vc) = vc_manager().current_vc() { // tty已经初始化了之后才输出到屏幕 let port = current_vc.port(); let tty = port.port_data().internal_tty(); if let Some(tty) = tty { let _ = tty.write(tty.core(), s.as_bytes(), s.len()); } else { let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK); } } else { let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK); } } } /// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出 impl fmt::Write for PrintkWriter { fn write_str(&mut self, s: &str) -> fmt::Result { self.__write_string(s); Ok(()) } } #[doc(hidden)] pub fn __printk(args: fmt::Arguments) { PrintkWriter.write_fmt(args).unwrap(); } pub struct Logger; impl Logger { pub fn log(&self, log_level: usize, message: fmt::Arguments) { if unsafe { KMSG.is_some() } { let timestamp: PosixTimeSpec = PosixTimeSpec::now_cpu_time(); let log_level = LogLevel::from(log_level); let log_message = LogMessage::new(timestamp, log_level, message.to_string()); unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) }; } } } /// 内核自定义日志器 /// /// todo: https://github.com/DragonOS-Community/DragonOS/issues/762 struct KernelLogger; impl Log for KernelLogger { fn enabled(&self, _metadata: &log::Metadata) -> bool { // 这里可以自定义日志过滤规则 true } fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { // todo: 接入kmsg Self::kernel_log(record); Self::iodisplay(record) } } fn flush(&self) { // 如果需要的话,可以在这里实现缓冲区刷新逻辑 } } impl KernelLogger { fn iodisplay(record: &log::Record) { match record.level() { Level::Debug | Level::Info | Level::Trace => { write!(PrintkWriter, "[ {} ] ", record.level(),) } Level::Error => { write!(PrintkWriter, "\x1B[41m[ ERROR ] \x1B[0m",) } Level::Warn => { write!(PrintkWriter, "\x1B[1;33m[ WARN ] \x1B[0m",) } } .unwrap(); writeln!( PrintkWriter, "({}:{})\t {}", record.file().unwrap_or(""), record.line().unwrap_or(0), record.args() ) .unwrap(); } fn kernel_log(record: &log::Record) { match record.level() { Level::Debug => Logger.log( 7, format_args!( "({}:{})\t {}\n", record.file().unwrap_or(""), record.line().unwrap_or(0), record.args() ), ), Level::Error => Logger.log( 3, format_args!( "({}:{})\t {}\n", record.file().unwrap_or(""), record.line().unwrap_or(0), record.args() ), ), Level::Info => Logger.log( 6, format_args!( "({}:{})\t {}\n", record.file().unwrap_or(""), record.line().unwrap_or(0), record.args() ), ), Level::Warn => Logger.log( 4, format_args!( "({}:{})\t {}\n", record.file().unwrap_or(""), record.line().unwrap_or(0), record.args() ), ), Level::Trace => { todo!() } } } } pub fn early_init_logging() { log::set_logger(&KernelLogger).unwrap(); log::set_max_level(log::LevelFilter::Debug); info!("Logging initialized"); }