rust【日志库】

可以设置输出级别,颜色,时间戳,输出行数等

rust 复制代码
// logger.rs
use chrono::Local;
use std::fmt;
use std::io::{self, Write};
use std::sync::Mutex;
use std::sync::OnceLock;

/// 日志级别
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum LogLevel {
    Error = 0,
    Warning = 1,
    Notice = 2,
    Info = 3,
    Debug = 4,
}

impl fmt::Display for LogLevel {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            LogLevel::Notice => "NOTICE",
            LogLevel::Debug => "DEBUG",
            LogLevel::Info => "INFO",
            LogLevel::Warning => "WARN",
            LogLevel::Error => "ERROR",
        };
        write!(f, "{}", s)
    }
}

/// ANSI 颜色代码
#[allow(dead_code)]
mod ansi_colors {
    pub const RESET: &str = "\x1b[0m";
    pub const BLACK: &str = "\x1b[30m";
    pub const RED: &str = "\x1b[31m";
    pub const GREEN: &str = "\x1b[32m";
    pub const YELLOW: &str = "\x1b[33m";
    pub const BLUE: &str = "\x1b[34m";
    pub const MAGENTA: &str = "\x1b[35m";
    pub const CYAN: &str = "\x1b[36m";
    pub const WHITE: &str = "\x1b[37m";

    // 亮色
    pub const BRIGHT_BLACK: &str = "\x1b[90m";
    pub const BRIGHT_RED: &str = "\x1b[91m";
    pub const BRIGHT_GREEN: &str = "\x1b[92m";
    pub const BRIGHT_YELLOW: &str = "\x1b[93m";
    pub const BRIGHT_BLUE: &str = "\x1b[94m";
    pub const BRIGHT_MAGENTA: &str = "\x1b[95m";
    pub const BRIGHT_CYAN: &str = "\x1b[96m";
    pub const BRIGHT_WHITE: &str = "\x1b[97m";
}

/// 日志级别颜色映射
struct LevelColors {
    notice: &'static str,
    debug: &'static str,
    info: &'static str,
    warning: &'static str,
    error: &'static str,
}

impl Default for LevelColors {
    fn default() -> Self {
        Self {
            notice: ansi_colors::WHITE,
            debug: ansi_colors::CYAN,
            info: ansi_colors::GREEN,
            warning: ansi_colors::YELLOW,
            error: ansi_colors::RED,
        }
    }
}

impl LevelColors {
    fn get(&self, level: LogLevel) -> &'static str {
        match level {
            LogLevel::Notice => self.notice,
            LogLevel::Debug => self.debug,
            LogLevel::Info => self.info,
            LogLevel::Warning => self.warning,
            LogLevel::Error => self.error,
        }
    }
}
/// 日志配置
pub struct LogConfig {
    pub level: LogLevel,
    pub use_colors: bool,
    pub use_timestamps: bool,
}

impl Default for LogConfig {
    fn default() -> Self {
        Self {
            level: LogLevel::Info,
            use_colors: true,
            use_timestamps: false,
        }
    }
}

/// 内部日志器
struct Logger {
    config: Mutex<LogConfig>,
    colors: LevelColors, // 颜色配置
}

impl Logger {
    fn new(level: LogLevel) -> Self {
        Self {
            config: Mutex::new(LogConfig {
                level,
                use_colors: true,
                use_timestamps: false,
            }),
            colors: LevelColors::default(),
        }
    }

    fn set_config(&self, config: LogConfig) {
        let mut cfg = self.config.lock().unwrap();
        *cfg = config;
    }

    fn get_level(&self) -> LogLevel {
        self.config.lock().unwrap().level
    }

    fn color_enabled(&self) -> bool {
        self.config.lock().unwrap().use_colors
    }

    fn timestamps_enabled(&self) -> bool {
        self.config.lock().unwrap().use_timestamps
    }

    fn log(&self, level: LogLevel, message: fmt::Arguments) {
        if level > self.get_level() {
            return;
        }

        let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
        // 需要输出行号,取消下面注释
        // let (file, line) = get_caller_location();

        // let output = format!("{} {:<5} [{}:{}] {}", timestamp, level, file, line, message);
        // 改变输出格式,调整output变量即可
        let output = if self.timestamps_enabled() {
            format!("{} {}", timestamp,   message)
        } else {
            format!("{}",  message)
        };
        if self.color_enabled() {
            let color = self.colors.get(level);
            let colored = format!("{}{}{}", color, output, ansi_colors::RESET);

            let _ = match level {
                LogLevel::Error => writeln!(io::stderr(), "{}", colored),
                _ => writeln!(io::stdout(), "{}", colored),
            };
        } else {
            let _ = match level {
                LogLevel::Error => writeln!(io::stderr(), "{}", output),
                _ => writeln!(io::stdout(), "{}", output),
            };
        }
    }
}

/// 需要输出行号,取消注释,获取调用位置(文件名和行号)
// fn get_caller_location() -> (&'static str, u32) {
//     let location = std::panic::Location::caller();
//     (location.file(), location.line())
// }

// 全局静态日志器
static LOGGER: OnceLock<Logger> = OnceLock::new();

// 设置 v的级别,通过
fn get_logger() -> &'static Logger {
    LOGGER.get_or_init(|| Logger::new(LogLevel::Notice))
}

/// 初始化日志系统
pub fn init_logger(config: LogConfig) {
    get_logger().set_config(config);
}

/// 设置日志级别
pub fn set_log_level(level: u8) {
    let level = match level + 3 {
            0 => LogLevel::Error,
            1 => LogLevel::Warning,
            2 => LogLevel::Notice,
            3 => LogLevel::Info,
            4 => LogLevel::Debug,
            _ => LogLevel::Debug,
        };
    let mut config = get_logger().config.lock().unwrap();
    config.level = level;
}

/// 启用/禁用颜色输出
pub fn set_color_enabled(enabled: bool) {
    let mut config = get_logger().config.lock().unwrap();
    config.use_colors = enabled;
}

// 内部函数,供宏调用
#[doc(hidden)]
pub fn _log(level: LogLevel, args: fmt::Arguments) {
    get_logger().log(level, args);
}

// 宏定义:方便在任何地方调用
#[macro_export]
macro_rules! log_trace {
    ($($arg:tt)*) => {
        $crate::logger::_log($crate::logger::LogLevel::Notice, format_args!($($arg)*))
    };
}

#[macro_export]
macro_rules! log_debug {
    ($($arg:tt)*) => {
        $crate::logger::_log($crate::logger::LogLevel::Debug, format_args!($($arg)*))
    };
}

#[macro_export]
macro_rules! log_info {
    ($($arg:tt)*) => {
        $crate::logger::_log($crate::logger::LogLevel::Info, format_args!($($arg)*))
    };
}

#[macro_export]
macro_rules! log_warn {
    ($($arg:tt)*) => {
        $crate::logger::_log($crate::logger::LogLevel::Warning, format_args!($($arg)*))
    };
}

#[macro_export]
macro_rules! log_error {
    ($($arg:tt)*) => {
        $crate::logger::_log($crate::logger::LogLevel::Error, format_args!($($arg)*))
    };
}

注意: set_log_level函数需要稍微修改下,以适应不同方式的日志级别设置

使用方式

rust 复制代码
mod logger;

use logger::{LogConfig, LogLevel, init_logger, set_color_enabled, set_log_level};
// use logger::{log_trace, log_debug, log_info, log_warn, log_error};

fn main() {
    // 初始化(可选,不调用则使用默认配置:Info级别,彩色输出)
    init_logger(LogConfig {
        level: LogLevel::Debug,
        use_colors: true,
        use_timestamps: false,
    });

    println!("=== 日志示例 ===");
    example_function();

    println!("\n=== 修改为只显示 WARN 及以上级别 ===");
    set_log_level(1); // 0 + 3 = 3 -> LogLevel::Warning
    example_function();

    println!("\n=== 关闭颜色输出 ===");
    set_color_enabled(false);
    example_function();
}

fn example_function() {
    log_trace!("这是追踪信息(TRACE)");
    log_debug!("调试值: x = {}", 42);
    log_info!("服务启动成功");
    log_warn!("磁盘使用率 {}%", 85);
    log_error!("连接失败: {}", "timeout");
}
相关推荐
橙子家8 小时前
浏览器缓存之【基础键值存储】:Local storage 和 Session storage
前端
星星在线11 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒12 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x12 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
京东云开发者13 小时前
京东市民服务又“上新”!这次是黑龙江“龙易办”
前端
袋鱼不重13 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
Fireworks14 小时前
深入vue3源码解读 -- 1、响应式的基础概念
前端
程序员黑豆14 小时前
JDK 下载安装与配置详细教程
java·前端·ai编程
hunterandroid14 小时前
文件存储:内部存储与外部存储
前端
NorBugs14 小时前
飞机大战 Low 版 (Made in AI)
前端