跳转至

日志

log 是 Rust 日志接口的事实标准。所有的日志消费者库都支持它。在它的主页也推荐了其他的日志消费者库,如env_loggerfernflexi_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

eventtracing 中的一个点事件,相当于日志记录中的一条记录。它们用于表示在某个时间点发生的事情,通常用于记录错误、用户操作、状态变更等。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
}