How to Filter Logs by Level and Module in Rust

You can filter logs by level and module in Rust by configuring the `tracing` or `env_logger` crate with a specific filter string passed via the `RUST_LOG` environment variable or programmatically.

You can filter logs by level and module in Rust by configuring the tracing or env_logger crate with a specific filter string passed via the RUST_LOG environment variable or programmatically. This string uses a syntax like module_name=level to enable or disable specific log streams, allowing you to isolate output for debugging without changing code.

For the standard tracing ecosystem, set the RUST_LOG environment variable before running your binary. The syntax supports glob patterns and specific module paths. For example, to see only ERROR logs globally but DEBUG logs for a specific module named my_app::auth, use:

RUST_LOG="error,my_app::auth=debug" cargo run

If you need to configure this programmatically within your application (e.g., to switch levels based on a config file), use tracing_subscriber to build a custom filter:

use tracing_subscriber::{fmt, EnvFilter};

fn main() {
    let filter = EnvFilter::try_from_default_env()
        .unwrap_or_else(|_| EnvFilter::new("info,my_app::auth=debug"));

    tracing_subscriber::fmt()
        .with_env_filter(filter)
        .init();

    tracing::info!("Global info message");
    tracing::debug!("Global debug message (hidden)");

    // Simulate a log from the specific module
    // In real code, this would be inside the my_app::auth module
    tracing::debug!("Auth debug message (visible)");
}

If you are using the older log crate with env_logger, the approach is similar but uses the env_logger::Builder. You can set the filter string directly or parse it from the environment:

use log::{info, debug, LevelFilter};
use env_logger;

fn main() {
    // "error,my_app::auth=debug" enables error globally and debug for auth
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("error,my_app::auth=debug"))
        .init();

    info!("Global info (hidden)");
    debug!("Global debug (hidden)");
    
    // Assuming this code is inside the `my_app::auth` module
    debug!("Auth debug (visible)");
}

Key syntax rules for the filter string:

  • module=level targets a specific path (e.g., my_crate::utils=trace).
  • level alone sets the global default (e.g., info).
  • Use = to assign a level to a module; omitting it implies the default.
  • You can combine multiple rules with commas (e.g., error,my_crate=debug,other_crate=warn).
  • Use off to explicitly disable logging for a specific module.

This approach is dynamic; you can change the RUST_LOG variable at runtime without recompiling, making it ideal for production debugging where you need to toggle verbosity for specific components.