How to Configure Log Levels Using Environment Variables with `set_env_filter_from_env` in tui-logger
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 at lines 111-122, where the function signature is defined as:
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:
- Creates two
env_filter::Builderinstances. Thetui-loggerarchitecture maintains separate filters for the hot-select circular buffer (used for real-time widget display) and the main logger (used for file logging). - Reads the environment variable. Passing
Nonedefaults to readingRUST_LOG; passingSome("VAR_NAME")reads your custom variable instead. - Parses the filter string. The syntax follows standard
env-filterconventions, such asmycrate=info,othercrate::module=debug,hyper=error. - Installs the filters. The built filter objects populate
TUI_LOGGER.hot_selectandTUI_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:
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:
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:
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:
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:
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:
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:
RUST_LOG="tui_logger=info" cargo run --example demo --features crossterm
Summary
set_env_filter_from_envparses environment variables using standardenv-filtersyntax and applies directives to both the hot-select and main logger instances.- Default behavior reads from
RUST_LOGwhen passedNone; custom variable names requireSome("VAR_NAME"). - Implementation location is
src/logger/api.rslines 111-122, where the function builds and installs filters intoTUI_LOGGER.hot_selectandTUI_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, demonstrating the parsing logic (usingset_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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →