zlsrs 0.1.0

Rust 标准库扩展工具集,提供更便捷的使用方式
Documentation
use std::fmt;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};

use super::color;

/// 日志等级
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Level {
    Debug,
    Info,
    Warn,
    Error,
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if !color::supports_color() {
            return write!(f, "{}", self.plain_text());
        }

        match self {
            Level::Debug => write!(f, "\x1b[36mDEBUG\x1b[0m"),
            Level::Info => write!(f, "\x1b[32mINFO\x1b[0m"),
            Level::Warn => write!(f, "\x1b[33mWARN\x1b[0m"),
            Level::Error => write!(f, "\x1b[31mERROR\x1b[0m"),
        }
    }
}

impl Level {
    /// 获取不带颜色的文本表示
    fn plain_text(&self) -> &'static str {
        match self {
            Level::Debug => "DEBUG",
            Level::Info => "INFO",
            Level::Warn => "WARN",
            Level::Error => "ERROR",
        }
    }
}

pub struct Logger {
    level: Level,
    file: Option<Mutex<File>>,
    supports_color: bool,
}

impl Logger {
    /// 创建新的日志记录器
    pub fn new(level: Level) -> Self {
        Logger {
            level,
            file: None,
            supports_color: color::supports_color(),
        }
    }

    /// 设置日志级别
    pub fn set_level(&mut self, level: Level) {
        self.level = level;
    }

    /// 设置日志文件
    pub fn set_file(&mut self, path: &str) -> std::io::Result<()> {
        let file = OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .open(path)?;
        self.file = Some(Mutex::new(file));
        Ok(())
    }

    /// 获取当前时间戳
    fn get_timestamp() -> String {
        let start = SystemTime::now();
        let since_epoch = start
            .duration_since(UNIX_EPOCH)
            .unwrap_or_else(|_| std::time::Duration::from_secs(0));

        let secs = since_epoch.as_secs();
        let nanos = since_epoch.subsec_nanos();

        format!("{}.{:09}", secs, nanos)
    }

    /// 记录日志
    fn log(&self, level: Level, message: &str) {
        if level as u8 >= self.level as u8 {
            let timestamp = Self::get_timestamp();

            // 控制台输出
            let console_message = if self.supports_color {
                format!("[{}] {} {}\n", timestamp, level, message)
            } else {
                format!("[{}] {} {}\n", timestamp, level.plain_text(), message)
            };
            print!("{}", console_message);

            // 文件输出(不带颜色)
            if let Some(file) = &self.file {
                if let Ok(mut file) = file.lock() {
                    let file_message = format!("[{}] {} {}\n", timestamp, level.plain_text(), message);
                    let _ = file.write_all(file_message.as_bytes());
                    let _ = file.flush();
                }
            }
        }
    }

    pub fn debug(&self, message: &str) {
        self.log(Level::Debug, message);
    }

    pub fn info(&self, message: &str) {
        self.log(Level::Info, message);
    }

    pub fn warn(&self, message: &str) {
        self.log(Level::Warn, message);
    }

    pub fn error(&self, message: &str) {
        self.log(Level::Error, message);
    }
}