如何通过跟踪有条件地将日志写入多个目的地?

The*_*Nik 4 rust rust-tracing

我尝试使用跟踪箱实现一些集中式日志记录。我可以使用跟踪附加程序箱写入滚动文件,或使用以下代码写入 Graylog 应用程序:

let mut guards = Vec::new();
if let Some(log) = config.logs {
    if let Some(file) = log.file {
        let file_appender = tracing_appender::rolling::hourly(file.directory, file.filename);
        let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
        guards.push(guard);
        let file_logger = tracing_subscriber::fmt()
            .with_writer(non_blocking)
            .init();
    }

    if let Some(graylog) = log.graylog {
        let address: SocketAddr = graylog.host.parse().expect("Unable to parse graylog host address");
        let bg_task = Logger::builder()
            .additional_field("module_id", graylog.module_id)
            .init_tcp(address)
            .unwrap();

        tokio::spawn(bg_task);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果日志配置仅包含.file.graylog定义之一,则它可以工作,但如果我同时定义这两个应用程序,则应用程序会在启动时崩溃。

我认为存在冲突,因为两者都试图设置默认收集器。有什么方法可以定义两者来接受每个跨度和事件?

Net*_*ave 9

您可以Option<Layer>with组合图层时使用:

let mut guards = Vec::new();
if let Some(log) = config.logs {
    let file_log = if let Some(file) = log.file {
        let file_appender = tracing_appender::rolling::hourly(file.directory, file.filename);
        let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
        guards.push(guard);
        Some(fmt::Layer::new().with_writer(non_blocking))
    } else {
        None
    };

    let grey_log = if let Some(graylog) = log.graylog {
        let address: SocketAddr = graylog
            .host
            .parse()
            .expect("Unable to parse graylog host address");
        let (layer, task) = tracing_gelf::Logger::builder().connect_tcp(address)?;
        tokio::spawn(task);
        Some(layer)
    } else {
        None
    };

    let mut subscriber = tracing_subscriber::registry()
        .with(EnvFilter::...)
        .with(file_log)
        .with(grey_log);
}
Run Code Online (Sandbox Code Playgroud)