Rust 日志库完全指南:从入门到精通

GitHub 仓库: https://github.com/zhouByte-hub/rust-study ⭐ 如果这个项目对您有帮助,请给我一个 star!

在 Rust 生态系统中,日志处理是一个至关重要的环节。无论是开发小型应用还是大型系统,良好的日志记录都能帮助我们追踪问题、监控应用状态以及优化性能。本文将深入探讨 Rust 中几种流行的日志库,从基础概念到实际应用,帮助您选择最适合自己项目的日志解决方案。

目录

  1. log:Rust 日志门面
  2. env_logger:环境变量配置的日志实现
  3. pretty_env_logger:美化的日志输出
  4. flexi_logger:灵活强大的日志解决方案
  5. simple-log:简单易用的日志库

1. log:Rust 日志门面

log crate 是 Rust 生态系统中日志记录的核心组件。它提供了一个统一的日志 API,但本身并不实现日志输出功能,而是作为一个门面(facade),允许开发者选择最适合其需求的日志实现。

基本用法

use log::{info, trace};#[test]
fn test_1() {log::info!("info"); // 没有输出log::trace!("trace"); // 没有输出
}

优点

  • 统一接口:为所有日志实现提供了一致的 API
  • 解耦设计:库可以使用 log crate 的 API,而应用程序可以选择具体的日志实现
  • 标准化:定义了标准的日志级别(trace、debug、info、warn、error)

缺点

  • 无输出实现:本身不提供日志输出功能,需要配合其他日志库使用
  • 配置复杂:需要额外配置才能看到日志输出

适用场景

  • 作为库的开发者,希望提供日志功能但不强制用户使用特定日志实现
  • 需要在不同环境中灵活切换日志实现的应用程序

兼容的日志实现

  • env_logger
  • pretty_env_logger
  • flexi_logger
  • simple-log

2. env_logger:环境变量配置的日志实现

env_logger 是一个通过环境变量配置的日志实现,是 Rust 中最常用的日志库之一。它与 log crate 完美配合,提供了灵活的配置选项。

基本用法

use log::{error, info};#[test]
fn env_test_1() {// env_logger::init() 的作用是把 env_logger 作为日志后端注册到 log crate 的全局系统中env_logger::init();info!("info"); // 不会输出error!("error"); // init()默认的日志级别是error
}#[test]
fn env_test_2() {// 初始化日志,设置日志级别env_logger::Builder::from_default_env().filter_level(log::LevelFilter::Info).init();info!("abc");
}#[test]
fn env_test_3() {env_logger::Builder::from_default_env().format(|buf, record| {writeln!(buf,"{} [{}] {}: {}","time",record.level(),record.target(),record.args())}).filter_level(log::LevelFilter::Info).init();info!("abc");
}

优点

  • 环境变量配置:可以通过环境变量灵活配置日志行为
  • 简单易用:基本用法非常简单,只需一行代码即可初始化
  • 灵活格式化:支持自定义日志格式
  • 模块级别过滤:可以为不同模块设置不同的日志级别

缺点

  • 默认只输出到控制台:不直接支持输出到文件
  • 配置复杂度:高级配置需要编写较多代码
  • 依赖环境变量:在某些环境中可能不方便设置环境变量

适用场景

  • 命令行工具和简单的应用程序
  • 开发和测试环境
  • 需要通过环境变量控制日志行为的场景

3. pretty_env_logger:美化的日志输出

pretty_env_loggerenv_logger 的一个美化版本,提供了更美观、更易读的日志输出格式,特别适合在开发和调试时使用。

基本用法

use log::{error, info, warn};
extern crate pretty_env_logger;#[test]
fn test_1() {pretty_env_logger::init(); // init默认的日志级别也是errorinfo!("such information"); // 不打印warn!("o_O"); // 不打印error!("much error"); // 打印
}#[test]
fn test_2() {pretty_env_logger::formatted_builder().filter_level(log::LevelFilter::Info) // 全局日志级别.filter_module("reqwest", log::LevelFilter::Debug) // 模块日志级别.init();info!("info");
}

优点

  • 美观输出:提供了比标准 env_logger 更美观的日志格式
  • 颜色支持:支持彩色输出,使日志更易读
  • 模块级别过滤:可以为不同模块设置不同的日志级别
  • 易于调试:在开发环境中特别有用

缺点

  • 性能开销:格式化和颜色处理会带来一些性能开销
  • 不适合生产环境:美观的格式在生产环境中可能不是最佳选择
  • 功能有限:相比其他日志库,功能相对简单

适用场景

  • 开发和调试阶段
  • 命令行工具和交互式应用
  • 需要美观日志输出的演示程序

4. flexi_logger:灵活强大的日志解决方案

flexi_logger 是一个功能强大且高度可配置的日志库,支持将日志写入标准错误输出、文件或其他输出流,并允许在程序运行时进行动态配置。

基本用法

use flexi_logger::{DeferredNow, FileSpec, LogSpecification, Logger, WriteMode};
use log::{Record, info};#[test]
fn test_1() {// 初始化,日志级别是infoflexi_logger::init();log::info!("info");log::debug!("debug"); // 不会输出log::trace!("trace"); // 不会输出
}#[test]
fn test_2() {// 初始化,设置全局的Log Level为debugflexi_logger::Logger::try_with_str("debug").unwrap().start().unwrap();log::info!("info");log::trace!("trace"); // 不会输出log::debug!("debug");
}// 输出到文件
#[test]
fn log_to_file() {/*  WriteMode可以取值:1、Direct: 每条日志直接写入输出目标,无缓冲,实时输出,频繁IO操作。2、Buffer:使用缓冲区,默认8KB,缓冲区满后自动刷新,减少了IO操作,程序崩溃会丢失日志。3、BufferAndFlush:使用缓冲区,每次日志写入后都尝试刷新,比Direct性能好,比Buffer可靠。4、Never:从不主动刷新缓冲区,依赖操作系统自动刷新5、Auto:自动选择最佳模式*/let log_handle = Logger::try_with_str("info").unwrap().log_to_file(FileSpec::default().directory("src/logs").basename("app").suffix("log"),).write_mode(WriteMode::Direct).start().unwrap();info!("info");log_handle.flush(); //当WriteMode取值为BufferAndFlush时需要手动flush
}// 输出到控制台
#[test]
fn log_to_console() {Logger::try_with_str("info").unwrap().log_to_stdout().write_mode(WriteMode::Direct).start().unwrap();info!("info");
}// 同时将日志输出到文件和控制台
#[test]
fn log_to_file_and_console() {Logger::try_with_str("info").unwrap().log_to_file(FileSpec::default().directory("src/logs") // 日志文件所在的目录.discriminant("abc") // 日志文件名中包含的标识符,会拼接在baseName后面.basename("app") // 日志文件名前缀.suffix("log") // 日志文件名后缀.suppress_timestamp(), // 日志名不包含日期).duplicate_to_stdout(flexi_logger::Duplicate::All).write_mode(WriteMode::Direct).start().unwrap();info!("abc");
}// 设置日志格式进行输出
#[test]
fn format_log_to_console() {Logger::try_with_str("info").unwrap().log_to_stdout().write_mode(WriteMode::Direct).format(file_log_format).start().unwrap();log::info!("info");
}fn file_log_format(w: &mut dyn std::io::Write,now: &mut DeferredNow,record: &Record,
) -> std::io::Result<()> {write!(w,"[{}][{}][{}][{}:{}] - {}",now.now().format("%Y-%m-%d %H:%M:%S%.3f"), // 时间戳record.level(),                            // 日志级别record.module_path().unwrap_or("<unkonwn>"), // 模块路径record.file().unwrap_or("<unkonw>"),       // 文件名record.line().unwrap_or(0),                // 行号&record.args()                             // 日志内容)
}// 输出到文件中的日志和控制台中的日志格式不同
#[test]
fn file_format_and_console_format() {let log_specification = LogSpecification::builder().default(log::LevelFilter::Info).build();Logger::with(log_specification).format_for_files(file_log_format).format_for_stdout(console_log_format).log_to_file(FileSpec::default().directory("src/logs")).duplicate_to_stdout(flexi_logger::Duplicate::All).start().unwrap();info!("This is a test log message.");
}fn console_log_format(w: &mut dyn std::io::Write,_now: &mut DeferredNow,record: &Record,
) -> std::io::Result<()> {write!(w, "{}", &record.args())
}

优点

  • 高度可配置:提供了丰富的配置选项,几乎可以满足所有日志需求
  • 多种输出目标:支持同时输出到文件、控制台等多个目标
  • 灵活的写入模式:提供了多种写入模式(Direct、Buffer、BufferAndFlush等)
  • 自定义格式:可以为不同的输出目标设置不同的日志格式
  • 运行时配置:支持在程序运行时动态修改日志配置

缺点

  • API 复杂:功能丰富导致 API 相对复杂,学习曲线较陡
  • 依赖较多:相比简单的日志库,依赖更多
  • 配置繁琐:高级功能需要编写较多配置代码

适用场景

  • 需要复杂日志功能的大型应用程序
  • 需要将日志输出到多个目标的应用
  • 需要在运行时动态调整日志配置的系统
  • 对日志格式有特殊要求的应用

5. simple-log:简单易用的日志库

simple-log 是一个设计简洁、易于使用的日志库,支持本地文件或标准输出写入,适合那些不需要复杂配置的简单应用。

基本用法

use simple_log::{LogConfigBuilder, debug, info};#[test]
fn test_1() {simple_log::quick!("info");info!("abc");
}#[test]
fn test_2() {let log_config = LogConfigBuilder::builder().path("src/logs/simple.log").size(10).roll_count(8).time_format("%Y-%m-%d %H:%M:%S.%f").level("debug").unwrap().output_console().output_file().build();simple_log::new(log_config).unwrap();info!("abc");debug!("debug");
}

优点

  • 简单易用:API 设计简洁,上手快
  • 快速配置:提供了 quick! 宏进行快速初始化
  • 文件滚动:支持日志文件滚动,避免单个日志文件过大
  • 多输出支持:支持同时输出到控制台和文件

缺点

  • 功能有限:相比 flexi_logger 等库,功能较为基础
  • 自定义性差:日志格式和行为的自定义选项较少
  • 社区支持:社区和生态系统相对较小

适用场景

  • 小型应用程序和工具
  • 不需要复杂日志功能的简单项目
  • 快速原型开发
  • 日志需求相对固定的应用

总结

Rust 生态系统提供了多种日志库,每种都有其独特的优势和适用场景。选择合适的日志库应该基于您的具体需求:

  • 如果您正在开发一个库,应该使用 log crate 作为日志门面,让用户选择具体的实现。
  • 对于简单的命令行工具,env_loggerpretty_env_logger 是不错的选择。
  • 如果您需要将日志写入文件或需要更复杂的配置,flexi_logger 提供了丰富的功能。
  • 对于追求简单易用的项目,simple-log 可能是最合适的选择。

希望这篇指南能帮助您更好地理解和使用 Rust 中的日志库。如果您想了解更多关于 Rust 日志处理的实践和技巧,请查看我们的 https://github.com/zhouByte-hub/rust-study 并给个 star!您的支持是我们持续改进的动力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921599.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【科研绘图系列】R语言绘制论文合集图

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍 数据准备与过滤 统计分析 可视化绘图 抗药性分析 系统发育分析 加载R包 数据下载 Supp figure 1 Fig 1a Fig 1c Fig 1d Fig 1e Fig 1f Supp figure 3 Supp figure 4 Supp figure 5…

【c++】从三个类的设计看软件架构的哲学思考

从三个类的设计看软件架构的哲学思考 文章目录从三个类的设计看软件架构的哲学思考前言一、OP类&#xff1a;系统工程的安全守护者设计特点设计哲学适用场景现实类比二、VarReviser类&#xff1a;版本控制的严谨管理者设计特点设计哲学适用场景现实类比三、Model类&#xff1a;…

人工智能优化SEO关键词的实战策略

本文聚焦智能技术如何革新关键词优化实践&#xff0c;系统解析提升网站排名的核心路径。重点探讨语义分析如何精准匹配用户意图、长尾词智能挖掘怎样解锁高潜力流量&#xff0c;并详解工具筛选高转化关键词的五大实用策略。通过实战案例说明技术如何突破流量增长瓶颈&#xff0…

【c++】c++第一课:命名空间

文章目录1.C的第⼀个程序2.命名空间2.1 namespace的价值2.2 namespace的定义2.3 命名空间使⽤最新的c标准&#xff08;建议收藏&#xff09; 1.C的第⼀个程序 C兼容C语⾔绝⼤多数的语法&#xff0c;所以C语⾔实现的helloworld依旧可以运⾏&#xff0c;C中需要把定义⽂件代码后…

版本发布流程手册:Release分支规范与Bug分级标准全解析

在软件交付日益高频、用户需求快速迭代的今天&#xff0c;版本发布流程的规范性直接决定了团队的交付效率、产品质量和用户满意度。然而&#xff0c;许多团队仍面临以下痛点&#xff1a; 发布混乱&#xff1a;分支管理随意&#xff0c;代码冲突频发&#xff1b;质量失控&#…

什么是CA根证书

CA 根证书&#xff08;Certificate Authority Root Certificate&#xff09;是 数字证书体系&#xff08;PKI&#xff0c;Public Key Infrastructure&#xff09; 中的核心证书。它有几个关键点&#xff1a;1. 定义 CA&#xff08;Certificate Authority&#xff09;&#xff1…

git push -u origin main 这个-u起什么作用

git push -u origin main 里的 -u 等价于 --set-upstream&#xff0c;它的作用是&#xff1a;&#x1f449; 把本地分支 main 和远程分支 origin/main 绑定&#xff08;建立追踪关系&#xff09;。&#x1f539; 具体效果第一次推送分支时&#xff0c;如果加了 -u&#xff1a;本…

【Unity基础】两个关于UGUI中Text对非英文字体支持的问题

问题1&#xff1a;Unity中为什么UGUI中的Text(Textmeshpro&#xff09;默认不支持非英文字体&#xff0c;而legacy中的text却可以呢&#xff1f; 在Unity中&#xff0c;TextMeshPro&#xff08;TMP&#xff09;默认不支持非英文字体&#xff0c;而Legacy Text支持&#xff0c;主…

碎片时间干活的好手(requestIdleCallback)

&#x1f7e2; What —— 它是什么&#xff1f; requestIdleCallback(callback[, options]) 是浏览器提供的一个 API&#xff0c;用来在主线程空闲时执行一些优先级不高的任务。 它的特点&#xff1a; 异步执行&#xff1a;不会打断关键的渲染、交互、动画。节省性能&#xff1…

第三方网站测评:【WEB应用文件包含漏洞(LFI/RFI)的测试步骤】

文件包含漏洞分为本地文件包含(LFI)和远程文件包含(RFI)两类。LFI允许读取服务器本地文件,RFI可执行远程服务器上的恶意代码。PHP应用中include()、require()等函数未正确过滤用户输入时易产生此类漏洞。 检测URL中可能包含文件的参数,常见特征如下: 参数名包含file、pa…

网络爬虫(web crawler)

文章目录一、什么是网络爬虫二、爬虫工作流程详解第1步&#xff1a;起始点 - URL种子库&#xff08;Seed URLs&#xff09;第2步&#xff1a;大脑 - 调度器&#xff08;Scheduler&#xff09;第3步&#xff1a;双手 - 网页下载器&#xff08;Downloader&#xff09;第4步&#…

redis的高可用(哨兵)

Redis 的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时大量的客户端需要被通知切换到新的主节点上&#xff0c;对于上了一定规模的应用来说&#xff0c;这种方案是无法接受的&#xff0c;于是Redis从2.8开始提供…

安徽某能源企业积极推进运维智能化转型,引入高压配电房机器人巡检系统

在工业自动化与智能化深度融合的当下&#xff0c;机器人技术已成为能源行业提质增效的关键支撑。特别是在配电房这类高压电力核心区域的运维工作中&#xff0c;传统人工巡检不仅面临效率低下、巡检周期长的困境&#xff0c;更因人员直接接触高压设备而存在极高的安全风险。此&a…

数据结构_二叉平衡树

#include <stdio.h> #include <stdlib.h> #define max(a,b) ((a > b)? (a):(b))//平衡二叉树的节点结构 typedef struct AVL_TreeNode{int data; //数据域struct AVL_TreeNode* l;struct AVL_TreeNode* r;int h;//记录树的高度&#xff0c;用于计算平衡因子 }…

扫描件、PDF、图片都能比对!让文档差异无所遁形

智能文档比对系统可精准识别文档差异&#xff0c;解决金融、法律等多方协作场景下的版本混乱、审核低效和合规风险问题&#xff0c;将一份百页文档的人工核对从数小时缩短至3分钟以内。 文档差异比对常见场景有哪些&#xff1f; 每一次文档的修改都可能带来潜在风险&#xff0c…

excel里面店铺这一列的数据结构是2C【uniteasone17】这种,我想只保留前面的2C部分,后面的【uniteasone17】不要

这个结构是&#xff1a; 2C【uniteasone17】只要取前面的 2C 部分&#xff0c;可以用 Excel 的 公式 或者 文本函数 来实现。 方法 1&#xff1a;使用公式提取 假设店铺数据在 A2 单元格&#xff1a; LEFT(A2,FIND("【",A2)-1)&#x1f449; 解释&#xff1a; FIND(“…

四、神经网络的学习(中)

4.3 数值微分梯度法使用梯度的信息决定前进的方向。本节将介绍梯度是什么、有什么性质等内容。4.3.1 导数假如你是全程马拉松选手&#xff0c;在开始的10分钟内跑了2千米。如果要计算此时的奔跑速度&#xff0c;则为2/10 0.2&#xff3b;千米/分&#xff3d;。也就是说&#x…

Jenkins 监控方案:Prometheus + Grafana 实践

这两天在运维群里面看到有人说 Jenkins 节点也可以监控&#xff0c;以前没想过搞这个&#xff0c;现在就对公司 Jenkins 搞搞顺便记录下呗。 一、使用 Jenkins Prometheus 插件&#xff08;推荐方式&#xff09; 1. 安装插件 在 Jenkins 插件管理里搜索并安装 Prometheus Me…

用博图FB类比c#中sdk的api

我有一个大胆的想法我准备自己做个简单的视觉软件来锻炼自己的c#编程能力&#xff0c;我准备用到海康工业机器人官网下载的mvs软件的sdk,听说sdk的主要作用就是api提供了开放的接口给第三方免费调用。按照我的理解&#xff0c;api接口就像西门子博图的FB块&#xff0c;所谓api接…

【Leetcode】高频SQL基础题--1164.指定日期的产品价格

【Leetcode】高频SQL基础题–1164.指定日期的产品价格 要求&#xff1a;一开始&#xff0c;所有产品价格都为 10。编写一个解决方案&#xff0c;找出在 2019-08-16 所有产品的价格。 以 任意顺序 返回结果表。解题思路&#xff1a; 找到 2019-08-16 前所有有改动的产品及其最新…