157 lines
3.9 KiB
Rust
157 lines
3.9 KiB
Rust
// Copyright (c) 2025 shibedrill
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
use crate::constants::LOG_DEFAULT_LEVEL;
|
|
use crate::format;
|
|
use crate::memory::alloc::boxed::Box;
|
|
use crate::memory::alloc::string::String;
|
|
use crate::memory::alloc::vec::Vec;
|
|
use lazy_static::lazy_static;
|
|
use spin::Mutex;
|
|
|
|
pub type LogDevice = dyn Fn(&str) + Send + Sync;
|
|
|
|
pub struct Logger {
|
|
pub level: LogLevel,
|
|
devices: Vec<Box<LogDevice>>,
|
|
}
|
|
|
|
lazy_static! {
|
|
pub static ref LOGGER: Mutex<Logger> = Mutex::new(Logger::new());
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_info {
|
|
($($arg:tt)*) => {
|
|
LOGGER.lock().log(LogLevel::Info, &format!($($arg)*), file!(), line!(), column!())
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_trace {
|
|
($($arg:tt)*) => {
|
|
LOGGER.lock().log(LogLevel::Trace, &format!($($arg)*), file!(), line!(), column!())
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_warning {
|
|
($($arg:tt)*) => {
|
|
LOGGER.lock().log(LogLevel::Warning, &format!($($arg)*), file!(), line!(), column!())
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_error {
|
|
($($arg:tt)*) => {
|
|
LOGGER.lock().log(LogLevel::Error, &format!($($arg)*), file!(), line!(), column!())
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_critical {
|
|
($($arg:tt)*) => {
|
|
LOGGER.lock().log(LogLevel::Critical, &format!($($arg)*), file!(), line!(), column!())
|
|
};
|
|
}
|
|
|
|
impl Logger {
|
|
pub fn new() -> Self {
|
|
Logger {
|
|
level: LOG_DEFAULT_LEVEL,
|
|
devices: Vec::new(),
|
|
}
|
|
}
|
|
pub fn log(
|
|
&mut self,
|
|
level: LogLevel,
|
|
message: &str,
|
|
file: &'static str,
|
|
line: u32,
|
|
column: u32,
|
|
) {
|
|
for dev in &self.devices {
|
|
let message = format!(
|
|
"{} {}:{},{}- {}",
|
|
level.normalized_string(),
|
|
file,
|
|
line,
|
|
column,
|
|
message
|
|
);
|
|
dev(&message)
|
|
}
|
|
}
|
|
pub fn add_device(&mut self, device: Box<dyn Fn(&str) + Send + Sync>) {
|
|
self.devices.push(device);
|
|
}
|
|
}
|
|
pub struct EnumParseError {}
|
|
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
|
pub enum LogLevel {
|
|
Disabled = 0,
|
|
Critical = 1,
|
|
Error = 2,
|
|
Warning = 3,
|
|
Info = 4,
|
|
Trace = 5,
|
|
}
|
|
|
|
impl TryFrom<u8> for LogLevel {
|
|
type Error = EnumParseError;
|
|
fn try_from(from: u8) -> Result<Self, <crate::log::LogLevel as TryFrom<u8>>::Error> {
|
|
match from {
|
|
0 => Ok(Self::Disabled),
|
|
1 => Ok(Self::Critical),
|
|
2 => Ok(Self::Error),
|
|
3 => Ok(Self::Warning),
|
|
4 => Ok(Self::Info),
|
|
5 => Ok(Self::Trace),
|
|
_ => Err(EnumParseError {}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&str> for LogLevel {
|
|
type Error = EnumParseError;
|
|
fn try_from(from: &str) -> Result<Self, <crate::log::LogLevel as TryFrom<u8>>::Error> {
|
|
match from.to_ascii_lowercase().as_ref() {
|
|
"disabled" => Ok(Self::Disabled),
|
|
"critical" => Ok(Self::Critical),
|
|
"error" => Ok(Self::Error),
|
|
"warning" => Ok(Self::Warning),
|
|
"info" => Ok(Self::Info),
|
|
"trace" => Ok(Self::Trace),
|
|
_ => Err(EnumParseError {}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<LogLevel> for String {
|
|
fn from(from: LogLevel) -> String {
|
|
match from {
|
|
LogLevel::Disabled => "Disabled",
|
|
LogLevel::Critical => "CRIT ",
|
|
LogLevel::Error => "ERROR",
|
|
LogLevel::Warning => "WARN ",
|
|
LogLevel::Info => "INFO ",
|
|
LogLevel::Trace => "TRACE",
|
|
}
|
|
.into()
|
|
}
|
|
}
|
|
|
|
impl LogLevel {
|
|
fn normalized_string(&self) -> &str {
|
|
match self {
|
|
LogLevel::Critical => "[CRIT ]",
|
|
LogLevel::Error => "[ERROR]",
|
|
LogLevel::Info => "[INFO ]",
|
|
LogLevel::Trace => "[TRACE]",
|
|
LogLevel::Warning => "[WARN ]",
|
|
LogLevel::Disabled => "[DSBLD]",
|
|
}
|
|
}
|
|
}
|