rust-flexi_logger

flexi_logger 是字节开源的rust日志库。目前有log4rs、env_log 等库,综合比较下来,还是flexi_logger简单容易上手,而且自定义很方便,以及在效率方面感觉也会高,下篇文章我们来测试下。
下面来看下怎么使用
关注 vx golang技术实验室,获取更多好文

一、启动日志的三种方式

引入包

flexi_logger = { version = "0.25.3", features = ["specfile", "compress"] }

通过选择三个选项之一来指定您想要查看的日志输出进行初始化,并start()立即调用:

  • 在环境变量中提供日志规范RUST_LOG

    Logger::try_with_env()?.start()?;
    
  • 以编程方式提供日志规范:

    Logger::try_with_str("info")?.start()?;
    
  • 结合两个选项:

    Logger::try_with_env_or_str("info")?.start()?;
    

之后,您只需使用日志箱中的日志宏即可。然后,那些与日志规范匹配的日志行将被写入默认输出通道 (stderr)。

二、日志输出通道

2.1 写入到文件

assert_eq!(FileSpec::default().directory("/a/b/c")//输出的目录.basename("foo")//输出的文件名.suppress_timestamp()//是否添加时间.suffix("bar"),//添加的后缀.discriminant("Sample4711A") .//使用FileSpec::discriminant 您可以向日志文件名添加有区别的中缀。FileSpec::try_from("/a/b/c/foo.bar").unwrap()//
);
$ ll log_files
total 16
-rw-r--r--  1 xxx  staff  70 Oct 27 16:47 foo.bar //使用suppress_timestamp
-rw-r--r--  1 xxx  staff  70 Oct 27 16:47 foo_2023-10-27_16-47-53.bar
-rw-r--r--  1 xxx  staff  70 Oct 27 17:01 foo_Sample4711A_2023-10-27_17-01-11.bar

如果给定路径的基本名称没有文件名,则会发生恐慌

三、写入模式

默认情况下,每个日志行都直接写入输出,而不进行缓冲。这允许实时查看新的日志行。

您有Logger::write_mode 一些选择来改变这种行为,例如

-

pub enum WriteMode {Direct,SupportCapture,BufferAndFlush,BufferAndFlushWith(usize, Duration),BufferDontFlush,BufferDontFlushWith(usize),Async,AsyncWith {pool_capa: usize,message_capa: usize,flush_interval: Duration,},
}
  • Direct

    不缓冲(默认)。

    每个日志行都直接写入输出,无需缓冲。这允许实时查看新的日志行,并且不需要额外的线程。

  • SupportCapture

​ 不缓冲和支持cargo test捕获。

​ 很像Direct,只是慢一点,并且允许 cargo test捕获日志输出并仅在失败的测试时打印它。

  • BufferAndFlush

BufferAndFlushWith与默认容量 ( DEFAULT_BUFFER_CAPACITY) 和默认间隔 ( )相同DEFAULT_FLUSH_INTERVAL

pub const DEFAULT_BUFFER_CAPACITY: usize = _; // 8_192usize 8k
pub const DEFAULT_FLUSH_INTERVAL: Duration;//1s
  • BufferAndFlushWith(usize, Duration)
元组字段
0: usize
缓冲能力。1: Duration
冲洗间隔。以给定的缓冲区容量和刷新间隔进行缓冲和刷新。
和上面的一样,是指指定size和刷新时间
  • BufferDontFlush

BufferDontFlushWith与默认容量相同( DEFAULT_BUFFER_CAPACITY)。达到8k刷新

  • BufferDontFlushWith(usize)

​ 元组字段

0: usize

​ 缓冲能力。

​ 具有给定缓冲区容量的缓冲区,但不刷新。

​ 如果您想最大程度地减少 I/O 工作量并且不想创建额外的线程用于刷新并且不关心日志行是否出现延迟,这可能会很方便。

  • Async

与 相同AsyncWith,所有参数均使用默认值。

  • AsyncWith
Fields
pool_capa: usize
消息缓冲区池的容量。message_capa: usize
单个消息缓冲区的容量。flush_interval: Duration
刷新输出的时间间隔。随着Duration::ZERO冲洗被抑制。

日志行通过无界通道发送到输出线程,该线程执行 I/O,如果log_to_file()选择的话,还执行轮换和清理。

使用缓冲输出来减少开销,并使用有界消息池来减少分配。日志输出按照给定的时间间隔定期刷新。

  • 使用WriteMode::BufferAndFlush、 或WriteMode::BufferAndFlushWith,您可以减少程序的 I/O 开销,从而提高整体性能,如果大量使用日志记录,这可能是相关的。此外,为了在日志行在输出通道中可见之前保持较短的最大等待时间,会创建一个额外的线程来定期刷新缓冲区。

    fn main() -> Result<(), Box<dyn std::error::Error>> {let _logger = Logger::try_with_str("info")?.log_to_file(FileSpec::default()).write_mode(WriteMode::BufferAndFlush).start()?;// ... do all your work ...Ok(())
    }
    
  • 使用WriteMode::Async 或 时WriteMode::AsyncWith,日志通过无界通道从应用程序线程发送到输出线程,该输出线程执行输出(以及轮换和清理,如果适用)。此外,输出被缓冲,并且使用有界消息池来减少分配,并使用刷新来避免长时间延迟。如果使用复制,则消息将同步写入stdoutstderr

    fn main() -> Result<(), Box<dyn std::error::Error>> {let _logger = Logger::try_with_str("info")?.log_to_file(FileSpec::default()).write_mode(WriteMode::Async).start()?;// ... do all your work ...Ok(())
    }
    

四、日志格式

4.1 自定义输出格式

use flexi_logger::{ DeferredNow, Record};fn custom_format(w: &mut dyn std::io::Write,now: &mut DeferredNow,record: &Record,
) -> Result<(), std::io::Error> {write!(w,"[{}] [{}] {}: {}",now.now().format("%Y-%m-%d %H:%M:%S"),record.level(),record.module_path().unwrap_or("<unnamed>"),record.args())
}let _logger = Logger::try_with_str("debug, my::critical::module=trace").unwrap().log_to_file(FileSpec::default().directory("./log_files").basename("foo").// suppress_timestamp().suffix("bar").discriminant("Sample4711A")).duplicate_to_stderr(Duplicate::Debug)// print warnings and errors also to the console.write_mode(WriteMode::BufferAndFlush).format(custom_format)//定义的输出格式.start().unwrap();[2023-10-27 17:32:08] [DEBUG] my_test: s
[2023-10-27 17:32:08] [INFO] my_test: s
[2023-10-27 17:32:08] [WARN] my_test: s
[2023-10-27 17:32:08] [ERROR] my_test: s

4. 2 使用默认的日志格式

## opt_format
[2023-10-27 17:34:23.438382 +08:00] DEBUG [src/main.rs:50] s
[2023-10-27 17:34:23.439057 +08:00] INFO [src/main.rs:51] s
[2023-10-27 17:34:23.439078 +08:00] WARN [src/main.rs:52] s
[2023-10-27 17:34:23.439091 +08:00] ERROR [src/main.rs:53] s## default_format
DEBUG [my_test] s
INFO [my_test] s
WARN [my_test] s
ERROR [my_test] s## detailed_format
[2023-10-27 17:36:12.719699 +08:00] DEBUG [my_test] src/main.rs:50: s
[2023-10-27 17:36:12.719948 +08:00] INFO [my_test] src/main.rs:51: s
[2023-10-27 17:36:12.719964 +08:00] WARN [my_test] src/main.rs:52: s
[2023-10-27 17:36:12.719978 +08:00] ERROR [my_test] src/main.rs:53: s## with_thread
[2023-10-27 17:36:41.542709 +08:00] T[main] DEBUG [src/main.rs:50] s
[2023-10-27 17:36:41.542968 +08:00] T[main] INFO [src/main.rs:51] s
[2023-10-27 17:36:41.542984 +08:00] T[main] WARN [src/main.rs:52] s
[2023-10-27 17:36:41.542997 +08:00] T[main] ERROR [src/main.rs:53] s

4.2 默认的彩色输出

## colored_default_format

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

## colored_detailed_format

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

## colored_opt_format

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

和上面的是一一对应的

4.4 日志文件截取

无论Logger::log_to_file是否进行轮换, flexi_logger默认情况下都会使用名称中带有时间戳的文件,例如 foo_2020-11-16_08-37-44.log(对于名为 的程序foo),这些文件对于每个程序启动来说都是非常唯一的。

这样FileSpec::suppress_timestamp 您就可以获得一个简单的固定文件名,例如foo.log.

在这种情况下,重新启动程序将截断现有日志文件。

另外使用Logger::append 将每次新运行的日志附加到现有文件中。

Logger::try_with_str("info")? // Write all error, warn, and info messages// use a simple filename without a timestamp.log_to_file(FileSpec::default().suppress_timestamp())// do not truncate the log file when the program is restarted.append().start()?;

通过轮换,日志始终会写入带有中缀的文件中rCURRENT,例如foo_rCURRENT.log

Logger::rotate 采用三个定义其行为的枚举参数:

  • Criterion

    • Criterion::Age当时钟切换到新的一天、小时、分钟或秒时,就会发生旋转
    • Criterion::Size当当前日志文件超过指定限制时发生轮转
    • Criterion::AgeOrSize当达到两个限制中的任何一个时,就会发生旋转
  • Naming
    然后将当前文件重命名

    • Naming::Timestamps类似的东西foo_r2020-11-16_08-56-52.log
    • Naming::Numbers类似的东西foo_r00000.log

    rCURRENT创建一个新文件。

  • Cleanup定义是否以及如何避免无限期累积日志文件:

    • 您指定Cleanup::KeepLogFiles应保留的日志文件的数量;如果有更多,较旧的将被删除
    • 您指定Cleanup::KeepCompressedFiles应保留的日志文件的数量,并且这些文件将被额外压缩
    • 您可以Cleanup::KeepLogAndCompressedFiles 指定应按原样保留的日志文件数量以及正在压缩的附加数量
    • 如果Cleanup::Never不进行清理,所有文件都会保留。

案例

Logger::try_with_str("info")?      // Write all error, warn, and info messages.log_to_file(FileSpec::default()).rotate(                      // If the program runs long enough,Criterion::Age(Age::Day), // - create a new file every dayNaming::Timestamps,       // - let the rotated files have a timestamp in their nameCleanup::KeepLogFiles(7), // - keep at most 7 log files).start()?;-rw-r--r--  1 xxx  staff  1508 Oct 27 18:46 foo_Sample4711A_rCURRENT.bar

五、代码方式启动

5.1 程序中设置

    let _logger = Logger::try_with_str("debug, my::critical::module=trace").unwrap().log_to_file(FileSpec::default().directory("./log_files").basename("foo").suppress_timestamp().suffix("bar").discriminant("Sample4711A")).duplicate_to_stderr(Duplicate::Debug)// print warnings and errors also to the console.write_mode(WriteMode::BufferAndFlush).format(colored_opt_format).append().rotate(                      // If the program runs long enough,Criterion::AgeOrSize(Age::Day,10000000000000), // - create a new file every dayNaming::Timestamps,       // - let the rotated files have a timestamp in their nameCleanup::KeepLogFiles(7), // - keep at most 7 log files).start().unwrap();

这里我们使用了配置字符串 "debug, my::critical::module=trace",表示全局默认日志级别为 debug,而模块路径为 my::critical::module 的日志级别为 trace

5.2 文件设置

Logger::try_with_str("info").unwrap()// ... logger configuration ....start_with_specfile("./server/config/logspec.toml").unwrap();

将创建包含以下内容的文件logspecification.toml(如果尚不存在):

### Optional: Default log level
global_level = 'info'
### Optional: specify a regular expression to suppress all messages that don't match
#global_pattern = 'foo'### Specific log levels per module are optionally defined in this section
[modules]
#'mod1' = 'warn'
#'mod2' = 'debug'
#'mod2::mod3' = 'trace'

随后,您可以根据需要编辑和修改该文件,在程序运行时,它将立即考虑您的更改。

目前仅支持 toml 文件,因此文件后缀必须是.toml.

如果无法读取文件,则初始规范仍然有效。

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

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

相关文章

jq+canvas:实现图片上传+裁剪+保存等功能

效果图 上传图片之前&#xff1a; 上传图片之后&#xff0c;点击放大/缩小后的效果&#xff1a; 裁剪之后的效果&#xff1a; 代码实现如下&#xff1a; 1.html部分 <input type"file" id"fileInput" accept"image/png, image/gif, image/j…

Python提取PDF表格(基于AUTOSAR_SWS_CANDriver.pdf)

个人学习笔记&#xff0c;仅供参考。 需求&#xff1a;提取AUTOSAR SWS中所有的API接口信息&#xff0c;用于生成C代码。 此处以AUTOSAR_SWS_CANDriver.pdf为例&#xff0c;若需要提取多个SWS文件&#xff0c;遍历各个文件即可。 1.Python包 pdfplumber是一款完全用python开…

【FMC139】青翼科技基于VITA57.1标准的4路500MSPS/1GSPS/1.25GSPS采样率14位AD采集FMC子卡模块

板卡概述 FMC139是一款基于VITA57.1标准规范的JESD204B接口FMC子卡模块&#xff0c;该模块可以实现4路14-bit、500MSPS/1GSPS ADC采集功能。该板卡ADC器件采用ADI公司的AD9680芯片,全功率-3dB模拟输入带宽可达2GHz。该ADC与FPGA的主机接口通过8通道的高速串行GTX收发器进行互联…

SpringCloud-高级篇(五)

一&#xff1a;分布式事务理论基础 原子性&#xff08;Atomicity&#xff09; 原子性是指事务是一个不可分割的工作单位&#xff0c;事务中的操作要么都发生&#xff0c;要么都不发生。 一致性&#xff08;Consistency&#xff09; 事务前后数据的完整性必须保持一致。 隔离性&…

计算机服务器中了mallox勒索病毒如何处理,mallox勒索病毒解密文件恢复

科技技术的发展推动了企业的生产运营&#xff0c;网络技术的不断应用&#xff0c;极大地方便了企业日常生产生活&#xff0c;但网络毕竟是一把双刃剑&#xff0c;网络安全威胁一直存在&#xff0c;近期&#xff0c;云天数据恢复中心接到很多企业的求助&#xff0c;企业的计算机…

【离散数学】——期末刷题题库(命题逻辑)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

使用opencv的matchTemplate进行银行卡卡号识别

![字体文件](https://img-blog.csdnimg.cn/3a16c87cf4d34aceb0778c4b20ddadb2.png#pic_center import cv2 import numpy as npdef show_img(img, name"temp"):img cv2.resize(img, (0, 0), fx3, fy3)cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()de…

神奇的世界(高斯核是唯一可以产生多尺度空间的线性核研究总结,两个高斯公式的联系,和推导)

放大缩小其实在现实世界中不存在。 也就是说尺度是不存在的。 比如树的长大&#xff0c;人的长大&#xff0c;从来就不是放大能解释的。 但你发现&#xff0c;这种事情存在于人的眼睛当中&#xff0c;光线真是神奇的东西。 但现实的东西是不存在放大缩小的&#xff0c;只有…

DjiTello + YoloV5的无人机的抽烟检测

一、效果展示 注&#xff1a;此项目纯作者自己原创&#xff0c;创作不易&#xff0c;不经同意不给予搬运权限&#xff0c;转发前请联系我&#xff0c;源码较大需要者评论获取&#xff0c;谢谢配合&#xff01; 1、未启动飞行模型无人机的目标检测。 DjiTello YOLOV5抽烟检测 …

【深入剖析K8s】容器技术基础(三):深入理解容器镜像 文件角度

容器里的进程‘看到’’的文件系统 可能你立刻就能想到,这应该是一个关于MountNamespace的问题:容器里的应用进程理应‘看到”一套完全独立的文件系统这样它就可以在自己的容器目录&#xff08;比如 /tmp&#xff09;下进行操作’而完全不会受宿主机以及其他容器的影响。 容器…

94.STM32外部中断

目录 1.什么是 NVIC&#xff1f; 2.NVIC寄存器 3.中断优先级 4.NVIC的配置 设置中断分组​编辑 配置某一个中断的优先级 5.什么是EXTI 6.EXTI和NVIC之间的关系 7.SYSCFG 的介绍 1.什么是 NVIC&#xff1f; NVIC是一种中断控制器&#xff0c;主要用于处理 ARM Cort…

美国高防云服务器的优劣势分析(相比普通云服务器)

在当前数字化时代&#xff0c;云服务器已经成为企业和个人进行在线业务的重要基础设施。而在选择云服务器时&#xff0c;很多人会面临一个问题&#xff1a;是选择普通云服务器还是高防云服务器?本文将从多个方面来分析美国高防云服务器相比普通云服务器的优势和劣势。 我们来看…