日志
log
是 Rust 日志接口的事实标准。所有的日志消费者库都支持它。在它的主页也推荐了其他的日志消费者库,如env_logger
、 fern
和 flexi_logger
。下面是一个添加每日变化log文件的配置选项:
fn init_logger() {
use flexi_logger::{opt_format, FileSpec, Logger};
Logger::with(LevelFilter::Info)
.log_to_file(
FileSpec::default()
.directory("log")
.basename("price")
.suffix("log"),
)
.rotate(
flexi_logger::Criterion::Age(flexi_logger::Age::Day),
flexi_logger::Naming::TimestampsDirect,
flexi_logger::Cleanup::KeepLogFiles(7),
)
.format_for_files(opt_format)
.start()
.expect("Logger initialization failed");
}
Rust - tracing
tracing
是tokio团队维护的,更适合Rust异步程序使用的日志接口库。与之相配合的是tracing-subscriber
。
理解Tracing库,要理解两个概念:spans(范围), events(事件)。
一个 span
表示程序中的一个操作区间,它可以是一个函数调用、一个请求的处理过程,或者是任何需要被追踪的时间段。span
可以嵌套,允许你构造一个请求或任务的详细执行路径。在编程实践中,我们通常使用instrument
宏来修饰函数,创造span
。
event
是 tracing
中的一个点事件,相当于日志记录中的一条记录。它们用于表示在某个时间点发生的事情,通常用于记录错误、用户操作、状态变更等。event
通常在某个 span
的上下文中记录,从而可以知道每个事件发生在什么操作过程中。
对应上文提出的问题。对于a1, a2 事件,我们需要在a1开始之前创建span,a2结束之后终止span。
tracing-log
库允许捕获从log
发出的日志消息,并将它们作为tracing
事件处理。这样,你可以在使用tracing
的同时,保留那些还在使用log
接口的库或应用部分的日志记录。tracing_subscriber
使用了他并默认支持log
。
fn init_logger() -> tracing_appender::non_blocking::WorkerGuard {
use tracing_subscriber::{filter, fmt, layer::SubscriberExt, util::SubscriberInitExt, Layer};
let file_appender = tracing_appender::rolling::daily("log", "price.log");
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
let file_layer = fmt::layer()
.json()
.with_writer(non_blocking)
.with_file(true)
.with_line_number(true)
.with_ansi(false)
.with_span_events(fmt::format::FmtSpan::NEW | fmt::format::FmtSpan::CLOSE)
.with_filter(filter::LevelFilter::INFO);
let console_layer = fmt::layer()
.with_file(false)
.with_span_events(fmt::format::FmtSpan::NEW | fmt::format::FmtSpan::CLOSE)
.with_filter(filter::LevelFilter::INFO);
// 初始化 Subscriber
tracing_subscriber::registry()
.with(file_layer)
.with(console_layer)
.init();
tracing::info!("Logger initialized");
guard
}