# How to Configure Log Levels Using Environment Variables with `set_env_filter_from_env` in tui-logger

> Easily configure tui-logger log levels using environment variables. Call set_env_filter_from_env to parse RUST_LOG and apply filter directives for your Rust application.

- Repository: [gin66/tui-logger](https://github.com/gin66/tui-logger)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Call `set_env_filter_from_env(None)` after initializing the logger to parse the `RUST_LOG` environment variable and apply standard filter directives to both the circular buffer and the TUI widget.**

The `tui-logger` crate provides a direct path to configure log levels using environment variables with `set_env_filter_from_env`. This function, found in the `gin66/tui-logger` repository, integrates with the `env-filter` crate to parse standard logging directives and apply them instantly to your terminal user interface.

## How `set_env_filter_from_env` Works Internally

The implementation resides in [`src/logger/api.rs`](https://github.com/gin66/tui-logger/blob/main/src/logger/api.rs) at lines 111-122, where the function signature is defined as:

```rust
pub fn set_env_filter_from_env(env_name: Option<&str>)

```

### The Filter Installation Process

When invoked, the function executes four distinct operations to configure the filtering mechanism:

1. **Creates two `env_filter::Builder` instances.** The `tui-logger` architecture maintains separate filters for the *hot-select* circular buffer (used for real-time widget display) and the *main* logger (used for file logging).
2. **Reads the environment variable.** Passing `None` defaults to reading `RUST_LOG`; passing `Some("VAR_NAME")` reads your custom variable instead.
3. **Parses the filter string.** The syntax follows standard `env-filter` conventions, such as `mycrate=info,othercrate::module=debug,hyper=error`.
4. **Installs the filters.** The built filter objects populate `TUI_LOGGER.hot_select` and `TUI_LOGGER.inner`, immediately affecting which log events appear in the widget.

You can call this function multiple times during runtime to reconfigure filters without restarting the application.

## Configuring Log Levels from Environment Variables

### Using the Default `RUST_LOG` Variable

The standard approach uses the conventional `RUST_LOG` environment variable recognized across the Rust ecosystem:

```rust
use tui_logger::{init_logger, set_default_level, set_env_filter_from_env};
use log::LevelFilter;

fn main() {
    // Initialize the logger with maximum verbosity
    init_logger(LevelFilter::Trace).unwrap();
    
    // Set fallback level for targets not specified in the filter
    set_default_level(LevelFilter::Trace);
    
    // Parse RUST_LOG and apply filters
    set_env_filter_from_env(None);
}

```

Run your application with specific directives:

```bash
RUST_LOG="mycrate=debug,othercrate::mod=info" cargo run

```

The logger will display `debug` messages from `mycrate` and `info` messages from `othercrate::mod`, while respecting the default `Trace` level for all other targets.

### Specifying a Custom Environment Variable

For applications requiring specific variable names (such as avoiding conflicts with other log configurations), pass the identifier directly:

```rust
use tui_logger::{init_logger, set_default_level, set_env_filter_from_env};
use log::LevelFilter;

fn main() {
    init_logger(LevelFilter::Trace).unwrap();
    set_default_level(LevelFilter::Trace);
    
    // Use LOG_FILTER instead of RUST_LOG
    set_env_filter_from_env(Some("LOG_FILTER"));
}

```

Execute with your custom variable:

```bash
LOG_FILTER="tui_logger=warn,example=trace" cargo run

```

## Updating Filters at Runtime

The function supports dynamic reconfiguration without application restarts. This pattern allows you to adjust verbosity during debugging sessions:

```rust
use tui_logger::{init_logger, set_default_level, set_env_filter_from_env, move_events};
use log::LevelFilter;

fn main() {
    init_logger(LevelFilter::Trace).unwrap();
    set_default_level(LevelFilter::Trace);
    
    // Initial configuration from environment
    set_env_filter_from_env(None);
    
    // Process events with initial filter...
    move_events();
    
    // Change environment variable programmatically
    std::env::set_var("RUST_LOG", "mycrate=error");
    
    // Re-apply the new configuration
    set_env_filter_from_env(None);
    
    // Subsequent logs now obey the error-only filter
}

```

Note that `move_events()` ensures any buffered events are processed before the filter change takes effect.

## Integration with the Logger Widget

Complete integration with `TuiLoggerWidget` follows this pattern, as demonstrated in the crate examples:

```rust
use tui_logger::*;
use ratatui::{backend::CrosstermBackend, Terminal, widgets::Block};
use std::io::stdout;
use log::LevelFilter;

fn main() -> std::io::Result<()> {
    // Initialize logger infrastructure
    init_logger(LevelFilter::Trace).unwrap();
    set_default_level(LevelFilter::Trace);
    
    // Apply environment-based filtering
    set_env_filter_from_env(None);

    // Setup terminal backend
    let backend = CrosstermBackend::new(stdout());
    let mut terminal = Terminal::new(backend)?;

    // Render the logger widget
    terminal.draw(|f| {
        let widget = TuiLoggerWidget::default()
            .block(Block::default().title("Demo Logger"));
        f.render_widget(widget, f.size());
    })?;

    Ok(())
}

```

Test the filtering with:

```bash
RUST_LOG="tui_logger=info" cargo run --example demo --features crossterm

```

## Summary

- **`set_env_filter_from_env`** parses environment variables using standard `env-filter` syntax and applies directives to both the hot-select and main logger instances.
- **Default behavior** reads from `RUST_LOG` when passed `None`; custom variable names require `Some("VAR_NAME")`.
- **Implementation location** is [`src/logger/api.rs`](https://github.com/gin66/tui-logger/blob/main/src/logger/api.rs) lines 111-122, where the function builds and installs filters into `TUI_LOGGER.hot_select` and `TUI_LOGGER.inner`.
- **Runtime updates** are supported—call the function again after modifying environment variables to apply new filter configurations without restarting.
- **Test coverage** exists in [`tests/envfilter.rs`](https://github.com/gin66/tui-logger/blob/main/tests/envfilter.rs), demonstrating the parsing logic (using `set_env_filter_from_string`, which follows identical parsing rules).

## Frequently Asked Questions

### What filter syntax does the environment variable use?

The function uses standard `env-filter` syntax as implemented in the `env-filter` crate. You specify comma-separated directives in the format `target=level`, where level can be `trace`, `debug`, `info`, `warn`, or `error`. For example: `myapp=debug,hyper::client=info,warn` sets `myapp` to debug, `hyper::client` to info, and everything else to warn.

### Can I change log levels without restarting my application?

Yes. After modifying the environment variable with `std::env::set_var()`, call `set_env_filter_from_env` again with the same arguments. The function rebuilds the filter and immediately updates `TUI_LOGGER.hot_select` and `TUI_LOGGER.inner`, applying new levels to subsequent log events dynamically.

### Why does `set_env_filter_from_env` create two filter builders?

The `tui-logger` architecture maintains two separate filter states: one for the **hot-select** circular buffer (used for the widget display) and one for the **main** logger (used for file output and other sinks). Both must be updated simultaneously to ensure consistent filtering behavior across all logging destinations.

### How does this function interact with `set_default_level`?

`set_default_level` establishes a baseline level filter that applies when no specific directive matches a target. When you call `set_env_filter_from_env`, it overrides specific targets mentioned in the environment variable while leaving others at the default level. The default level acts as a catch-all for unspecified modules, whereas the env filter provides granular control.