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

一、启动日志三种方式

引入

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

通过选择三个选项之一来指定您想要查看日志输出进行初始化,并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,
    },
}

​ 不缓冲和支持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
元组字段
0: usize
缓冲能力。

1: Duration
冲洗间隔。

以给定缓冲区容量和刷新间隔进行缓冲和刷新。
和上面的一样,是指指定size和刷新时间
  • BufferDontFlush

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

元组字段

0: usize

​ 缓冲能力。

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

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

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

  • AsyncWith
Fields
pool_capa: usize
消息缓冲区池的容量。

message_capa: usize
单个消息缓冲区的容量。

flush_interval: Duration
刷新输出的时间间隔。

随着Duration::ZERO冲洗被抑制。

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

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

四、日志格式

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 采用三个定义行为枚举参数

案例

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 day
        Naming::Timestamps,       // - let the rotated files have a timestamp in their name
        Cleanup::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 day
                                      Naming::Timestamps,       // - let the rotated files have a timestamp in their name
                                      Cleanup::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.

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

原文地址:https://blog.csdn.net/qq_39787367/article/details/134664048

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_6735.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注