How to use `tracing-subscriber` Rust crate to build a mult-writer, global filter subscriber

huangapple go评论91阅读模式
英文:

How to use `tracing-subscriber` Rust crate to build a mult-writer, global filter subscriber

问题

我正在尝试使用tracingtracing-subscriber构建日志记录设置。然而,我发现tracing生态系统非常抽象且难以使用。

我正在尝试创建具有以下特性的订阅器:

  • 基于目标的顶级过滤器。例如,为module_a记录错误级别,为module_b记录信息级别。
  • 两个具有各自层级过滤器的写入器。

但是,我无法使用现有的实现RegistryFmtSubscriber创建最终的订阅器。

问题在于Registry不允许添加env_filter或顶级过滤器。而FmtSubscriber不允许添加写入器层。而且对我来说不清楚为什么在它们都实现了Subscriber特性的情况下这两者都不可能。

总的来说,我发现很难理解tracing中各个组件是如何配合的。任何解释其工作原理的博客或教程都会有所帮助。

参考链接 1
参考链接 2

英文:

I'm trying to build a logging setup using the tracing and tracing-subscriber. However I'm finding the tracing ecosystem incredibly abstract and hard to work with.

I'm trying to create Subscriber that has -

  • A top level filter based on the target. For e.g. a filter that logs error level for module_a and info level for module_b.^1
  • Two writers^2 each with their own layer level filter.

But I'm unable to create the final subscriber with the existing implementations Registry and FmtSubscriber.

The problem is that Registry does not allow adding an env_filter or a top level filter. While the FmtSubscriber does not allow adding the writer layers. And it's not clear to me why either of this is not possible when both of them implement the Subscriber trait.

use tracing::{instrument::WithSubscriber, metadata::LevelFilter, subscriber, Level, Subscriber};
use tracing_appender::{
    non_blocking::WorkerGuard,
    rolling::{RollingFileAppender, Rotation},
};
use tracing_subscriber::{
    filter::filter_fn, fmt, layer::Filter, prelude::*, registry::LookupSpan, Registry,
};

fn main() {
    // layer 1 is the file writer
    let rolling_log = RollingFileAppender::new(Rotation::NEVER, "hey", "cool.og");
    let (non_blocking, _) = tracing_appender::non_blocking(rolling_log);
    let layer1 = fmt::Layer::default()
        .with_writer(non_blocking)
        .with_filter(LevelFilter::from(Level::INFO));

    // layer 2 is the stdout writer
    let (non_blocking, _) = tracing_appender::non_blocking(std::io::stdout());
    let layer2 = fmt::Layer::default()
        .with_writer(non_blocking)
        .with_filter(LevelFilter::from(Level::ERROR));

    let top_level_filter: String = "module_a=info,module_b=error".to_string();
    // can't add env_filter/top level filter
    Registry::default().with(layer1).with(layer2).init();
    // can't add multiple writer layers
    fmt().with_env_filter(top_level_filter).init();
}

Overall I've found it hard to understand how the the various components in tracing fit together. Any blogs or tutorials explaining how it works will also help.

答案1

得分: -1

EnvFilter 实现了各种级别的过滤,并可以使用 Subscriber::with 添加到订阅者中,以充当全局过滤器。

use tracing_subscriber::filter::EnvFilter;

let layer1 = ...;
let layer2 = ...;

let global_filter: EnvFilter = "module_a=info,module_b=error".parse()?;
Registry::default().with(layer1).with(layer2).with(global_filter).init();
英文:

Answered by gusrut in this reddit comment.

EnvFilter implements various levels of filtering and can be added to the subscriber using Subscriber::with to act as a global filter.

use tracing_subscriber::filter::EnvFilter;

let layer1 = ...;
let layer2 = ...;

let global_filter: EnvFilter = "module_a=info,module_b=error".parse()?;
Registry::default().with(layer1).with(layer2).with(global_filter).init();

huangapple
  • 本文由 发表于 2023年8月4日 21:55:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定