use std::sync::Once;
#[derive(Debug, Clone)]
pub struct LoggerConfig {
pub enabled: bool,
pub level: LogLevel,
pub show_timestamp: bool,
pub show_module: bool,
pub show_line_number: bool,
pub use_colors: bool,
pub custom_format: Option<String>,
pub target: LogTarget,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LogLevel {
Error,
Warn,
Info,
Debug,
Trace,
}
#[derive(Debug, Clone)]
pub enum LogTarget {
Stdout,
Stderr,
File(String),
None,
}
impl Default for LoggerConfig {
fn default() -> Self {
Self {
enabled: true,
level: LogLevel::Info,
show_timestamp: true,
show_module: true,
show_line_number: false,
use_colors: true,
custom_format: None,
target: LogTarget::Stdout,
}
}
}
static LOGGER_INIT: Once = Once::new();
#[derive(Debug)]
pub struct Logger {
config: LoggerConfig,
}
impl Logger {
pub fn new(config: LoggerConfig) -> Self {
Self { config }
}
pub fn init(&self) -> Result<(), Box<dyn std::error::Error>> {
if !self.config.enabled {
return Ok(());
}
println!("Logger initialized with config: {:?}", self.config);
Ok(())
}
pub fn config(&self) -> &LoggerConfig {
&self.config
}
pub fn update_config(&mut self, config: LoggerConfig) {
self.config = config;
}
pub fn is_enabled(&self, level: &LogLevel) -> bool {
self.config.enabled && level >= &self.config.level
}
}
impl Default for Logger {
fn default() -> Self {
Self::new(LoggerConfig::default())
}
}
static mut GLOBAL_LOGGER: Option<Logger> = None;
static GLOBAL_LOGGER_INIT: Once = Once::new();
pub fn init_logger(config: LoggerConfig) -> Result<(), Box<dyn std::error::Error>> {
GLOBAL_LOGGER_INIT.call_once(|| {
let logger = Logger::new(config);
if let Err(e) = logger.init() {
eprintln!("Failed to initialize global logger: {}", e);
return;
}
unsafe {
GLOBAL_LOGGER = Some(logger);
}
});
Ok(())
}
pub fn get_logger() -> Option<&'static Logger> {
unsafe { GLOBAL_LOGGER.as_ref() }
}
#[macro_export]
macro_rules! psi_error {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Error) {
rat_logger::error!($($arg)*);
}
}
};
}
#[macro_export]
macro_rules! psi_warn {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Warn) {
rat_logger::warn!($($arg)*);
}
}
};
}
#[macro_export]
macro_rules! psi_info {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Info) {
rat_logger::info!($($arg)*);
}
}
};
}
#[macro_export]
macro_rules! psi_debug {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Debug) {
rat_logger::debug!($($arg)*);
}
}
};
}
#[macro_export]
macro_rules! psi_trace {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Trace) {
rat_logger::trace!($($arg)*);
}
}
};
}
#[derive(Debug)]
pub struct LoggerConfigBuilder {
config: LoggerConfig,
}
impl LoggerConfigBuilder {
pub fn new() -> Self {
Self {
config: LoggerConfig::default(),
}
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.config.enabled = enabled;
self
}
pub fn level(mut self, level: LogLevel) -> Self {
self.config.level = level;
self
}
pub fn show_timestamp(mut self, show: bool) -> Self {
self.config.show_timestamp = show;
self
}
pub fn show_module(mut self, show: bool) -> Self {
self.config.show_module = show;
self
}
pub fn show_line_number(mut self, show: bool) -> Self {
self.config.show_line_number = show;
self
}
pub fn use_colors(mut self, use_colors: bool) -> Self {
self.config.use_colors = use_colors;
self
}
pub fn custom_format<S: Into<String>>(mut self, format: S) -> Self {
self.config.custom_format = Some(format.into());
self
}
pub fn target(mut self, target: LogTarget) -> Self {
self.config.target = target;
self
}
pub fn build(self) -> LoggerConfig {
self.config
}
pub fn init(self) -> Result<(), Box<dyn std::error::Error>> {
init_logger(self.config)
}
}
impl Default for LoggerConfigBuilder {
fn default() -> Self {
Self::new()
}
}
pub fn disabled_config() -> LoggerConfig {
LoggerConfig {
enabled: false,
..Default::default()
}
}
pub fn dev_config() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Debug)
.show_timestamp(true)
.show_module(true)
.show_line_number(true)
.use_colors(true)
.target(LogTarget::Stdout)
.build()
}
pub fn prod_config() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.show_timestamp(true)
.show_module(false)
.show_line_number(false)
.use_colors(false)
.target(LogTarget::Stdout)
.build()
}
pub fn file_config<P: Into<String>>(path: P) -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.show_timestamp(true)
.show_module(true)
.show_line_number(true)
.use_colors(false)
.target(LogTarget::File(path.into()))
.build()
}
pub fn yuri_psychic_config() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Info)
.show_timestamp(true)
.show_module(true)
.show_line_number(false)
.use_colors(true)
.custom_format("🧠 {timestamp} | {level} | {module} | {message}")
.target(LogTarget::Stdout)
.build()
}
pub fn psi_detector_config() -> LoggerConfig {
LoggerConfigBuilder::new()
.level(LogLevel::Debug)
.show_timestamp(true)
.show_module(true)
.show_line_number(true)
.use_colors(true)
.custom_format("🔍 PSI | {timestamp} | {level} | {module}:{line} | {message}")
.target(LogTarget::Stdout)
.build()
}
#[macro_export]
macro_rules! psi_detect {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Info) {
rat_logger::info!("🔍 DETECT: {}", format!($($arg)*));
}
}
};
}
#[macro_export]
macro_rules! psi_upgrade {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Info) {
rat_logger::info!("⬆️ UPGRADE: {}", format!($($arg)*));
}
}
};
}
#[macro_export]
macro_rules! psi_mind_control {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Debug) {
rat_logger::debug!("🧠 MIND_CONTROL: {}", format!($($arg)*));
}
}
};
}
#[macro_export]
macro_rules! psi_scan {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Trace) {
rat_logger::trace!("📡 SCAN: {}", format!($($arg)*));
}
}
};
}
#[macro_export]
macro_rules! psi_perf {
($($arg:tt)*) => {
if let Some(logger) = $crate::utils::logger::get_logger() {
if logger.is_enabled(&$crate::utils::logger::LogLevel::Debug) {
rat_logger::debug!("⚡ PERF: {}", format!($($arg)*));
}
}
};
}