学校网站维护怎么做,博白建设局网站,鲜花网站的网络营销与策划书,淘宝店铺怎么运营起来flexi_logger 是字节开源的rust日志库。目前有log4rs、env_log 等库#xff0c;综合比较下来#xff0c;还是flexi_logger简单容易上手#xff0c;而且自定义很方便#xff0c;以及在效率方面感觉也会高#xff0c;下篇文章我们来测试下。 下面来看下怎么使用 关注 vx gol…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)。
二、日志输出通道 log_to_stderr 日志写入标准输入 Logger::log_to_stdout 日志写入标准输出。 Logger::log_to_file 日志写入文件。 FileSpec有关文件名模式的详细信息请参阅。 您可以复制到 stdout 和 stderr并且可以添加其他编写器。 Logger::log_to_writer 日志写入到提供的写入器。 您可以复制到 stdout 和 stderr并且可以添加其他编写器。 Logger::log_to_file_and_writer 日志被写入文件与 一样Logger::log_to_file并且写入替代 LogWriter实现。 您可以复制到 stdout 和 stderr并且可以添加其他编写器。 或者Logger::do_not_log 日志被处理包括重复但不写入任何目的地。 这非常有用例如对于在所有日志级别都处于活动状态的情况下运行应用程序测试并且仍然避免大量日志文件等。此类测试可确保通常不活动的日志调用在激活时不会导致不需要的副作用请注意日志调用宏可能会阻止评估非活动日志调用的参数。 或者如果您希望将日志同时发送到 stdout 和 stderr但不发送到其他地方则使用此选项并将其与 Logger::duplicate_to_stdoutand结合使用Logger::duplicate_to_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;//1sBufferAndFlushWith(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(), Boxdyn 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日志通过无界通道从应用程序线程发送到输出线程该输出线程执行输出以及轮换和清理如果适用。此外输出被缓冲并且使用有界消息池来减少分配并使用刷新来避免长时间延迟。如果使用复制则消息将同步写入stdout或stderr。 fn main() - Result(), Boxdyn 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::moduletrace).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] s4.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::moduletrace).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::moduletrace表示全局默认日志级别为 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 dont 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.
如果无法读取文件则初始规范仍然有效。