Difference Between CAPTURE and SHOW Filters in tui-logger Smart Widget
The SHOW filter controls which log entries appear in the terminal interface, while the CAPTURE filter determines which log levels are actually recorded by the underlying logger into the circular buffer.
The gin66/tui-logger crate provides Rust applications with a terminal user interface for log management. Its Smart Widget implements dual-layer filtering where SHOW and CAPTURE operate independently—enabling you to record verbose debug logs while displaying only error levels, or vice versa.
What the SHOW Filter Controls
The SHOW filter is a view-only configuration stored in the widget's private LevelConfig (state.config). According to the implementation in src/widget/target.rs, this filter determines which log entries appear in the UI for each target without affecting the global logger configuration.
Key characteristics of the SHOW filter:
- Storage: Resides in
state.configper target via thesetmethod defined insrc/config/level_config.rs - Key bindings: ← decreases and → increases the shown level (handled by
LeftKeyandRightKeyinsrc/widget/inner.rs) - State variables: Uses
opt_selected_visibility_lessandopt_selected_visibility_moreto track pending changes - Effect: Only changes what is currently rendered; past entries remain in the buffer unchanged
- Visibility: Targets set to
LevelFilter::Offare hidden whenhide_targetis toggled via theSPACEkey
What the CAPTURE Filter Controls
The CAPTURE filter determines which log events are actually recorded by the logger. Unlike SHOW, this affects the global logger state stored in TUI_LOGGER.inner and impacts future log events.
Key characteristics of the CAPTURE filter:
- Storage: Lives in the global logger and updated via
set_level_for_targetcalls - Key bindings: - decreases and + increases the captured level (handled by
MinusKeyandPlusKeyinsrc/widget/inner.rs) - State variables: Uses
opt_selected_recording_lessandopt_selected_recording_more - Effect: Only messages meeting the captured level threshold are stored in the circular buffer
- Persistence: Setting to
LevelFilter::Offstops new events from recording, but existing buffered entries may still appear in the UI
Implementation Details in Source Code
The separation of concerns is enforced across multiple source files in the gin66/tui-logger repository:
src/widget/target.rs calculates available filter levels using advance_levelfilter:
// SHOW filter preparation
let (more, less) = if let Some(levelfilter) = state.config.get(t) {
advance_levelfilter(levelfilter)
} else {
(None, None)
};
state.opt_selected_visibility_less = less;
state.opt_selected_visibility_more = more;
src/widget/inner.rs contains the TuiWidgetInnerState::transition method that processes key events:
SHOW filter adjustments update the widget configuration:
LeftKey => {
if let Some(selected_target) = self.opt_selected_target.take() {
if let Some(selected_visibility_less) = self.opt_selected_visibility_less.take() {
self.config.set(&selected_target, selected_visibility_less);
}
}
}
RightKey => {
if let Some(selected_target) = self.opt_selected_target.take() {
if let Some(selected_visibility_more) = self.opt_selected_visibility_more.take() {
self.config.set(&selected_target, selected_visibility_more);
}
}
}
CAPTURE filter adjustments modify the global logger:
MinusKey => {
if let Some(selected_target) = self.opt_selected_target.take() {
if let Some(selected_recording_less) = self.opt_selected_recording_less.take() {
set_level_for_target(&selected_target, selected_recording_less);
}
}
}
PlusKey => {
if let Some(selected_target) = self.opt_selected_target.take() {
if let Some(selected_recording_more) = self.opt_selected_recording_more.take() {
set_level_for_target(&selected_target, selected_recording_more);
}
}
}
Key Differences Between SHOW and CAPTURE
Storage Location
- SHOW: Stored in
state.config(widget-only) withinLevelConfig - CAPTURE: Stored in
TUI_LOGGER.inner(global logger state)
Key Bindings
- SHOW: Adjusted with ← and → keys
- CAPTURE: Adjusted with - and + keys
Effect on Log History
- SHOW: Changes current display only; buffered entries persist unchanged
- CAPTURE: Affects future log recording; determines what enters the circular buffer
Target Visibility
- SHOW: Controls immediate visibility in the UI; hidden targets can be toggled with
SPACE - CAPTURE: Controls data collection; OFF stops recording but existing data may remain visible
Programmatic Filter Configuration
To adjust filters programmatically rather than through key bindings, use TuiWidgetState and TuiWidgetEvent:
use tui_logger::{TuiWidgetState, TuiWidgetEvent};
let state = TuiWidgetState::new()
.set_default_display_level(log::LevelFilter::Trace);
// Decrease shown level (SHOW filter)
state.transition(TuiWidgetEvent::LeftKey);
// Decrease captured level (CAPTURE filter)
state.transition(TuiWidgetEvent::MinusKey);
For direct CAPTURE filter manipulation without the widget state machine:
// Set capture level for specific target
set_level_for_target("my_target", log::LevelFilter::Debug);
Documentation for these key commands appears in src/lib.rs (lines 71-84) with references to CAPTURED and SHOWN filters.
Summary
- SHOW filters control UI visibility and live in
state.config, modified by ←/→ keys viaopt_selected_visibility_less/more - CAPTURE filters control log recording and live in the global logger, modified by -/+ keys via
opt_selected_recording_less/more - Implementation spans
src/widget/target.rs,src/widget/inner.rs, andsrc/config/level_config.rs - Both filters can be adjusted programmatically via
TuiWidgetState::transitionorset_level_for_target
Frequently Asked Questions
Can I set different levels for CAPTURE and SHOW on the same target?
Yes. The filters operate independently. You can set CAPTURE to Trace to record everything while setting SHOW to Error to display only critical messages, enabling detailed debugging without UI clutter.
Why do I still see logs from a target after setting CAPTURE to OFF?
Setting CAPTURE to LevelFilter::Off stops new events from being recorded, but existing entries in the circular buffer remain visible until cleared. The SHOW filter controls visibility of buffered entries, so you must also set SHOW to Off or clear the buffer to hide existing logs.
How do I persist filter settings between application restarts?
The tui-logger crate does not persist filter settings automatically. You must serialize state.config for SHOW filters and replay set_level_for_target calls for CAPTURE filters during application startup, or store these values in your application's configuration file.
Where are the key bindings documented in the source code?
Key bindings are documented in src/lib.rs (lines 71-84) with explicit references to CAPTURED and SHOWN filters, and implemented in src/widget/inner.rs within the TuiWidgetInnerState::transition method that handles LeftKey, RightKey, MinusKey, and PlusKey events.
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 →