Search code examples
rustrust-tracing

How to add a layer to tracing_subscriber's Registry based on a condition?


I need to add a layer to the registry in the below code based on a condition.

As you can see I'm trying two ways: both of them fail.

What can I use?

REPL: https://www.rustexplorer.com/b/n16o51

use tracing_subscriber::{fmt::Layer, prelude::*, EnvFilter, Registry};

#[tokio::main]
async fn main() {
    let mut registry = Registry::default()
        .with(EnvFilter::from("INFO"))
        .with(Layer::default().json().boxed());

    // This doesn't work because of: use of moved value: `registry`
    // if (1 == 1) {
    //     registry.with(Layer::default().pretty().with_file(false).boxed());
    // }

    // This doesn't work because of very strange `mismatched types`
    // if (2 == 2) {
    //     registry = registry.with(Layer::default().pretty().with_file(false).boxed());
    // }

    tracing::subscriber::set_global_default(registry).unwrap();
}

Solution

  • Option<Layer> implements Layer, so the correct way is to use Option:

    let registry = Registry::default()
        .with(EnvFilter::from("INFO"))
        .with(Layer::default().json())
        .with(if 2 == 2 {
            Some(Layer::default().pretty().with_file(false))
        } else {
            None
        });
    

    Or:

    let registry = Registry::default()
        .with(EnvFilter::from("INFO"))
        .with(Layer::default().json())
        .with((2 == 2).then(|| Layer::default().pretty().with_file(false)));
    

    The assignment doesn't work because each with() wraps the type with Layered, creating a different type.