# Difference Between CAPTURE and SHOW Filters in tui-logger Smart Widget

> Understand the crucial difference between CAPTURE and SHOW filters in tui-logger. Learn how to control displayed logs and recorded log levels for efficient debugging.

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

---

**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`](https://github.com/gin66/tui-logger/blob/main/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.config` per target via the `set` method defined in [`src/config/level_config.rs`](https://github.com/gin66/tui-logger/blob/main/src/config/level_config.rs)
- **Key bindings**: **←** decreases and **→** increases the shown level (handled by `LeftKey` and `RightKey` in [`src/widget/inner.rs`](https://github.com/gin66/tui-logger/blob/main/src/widget/inner.rs))
- **State variables**: Uses `opt_selected_visibility_less` and `opt_selected_visibility_more` to track pending changes
- **Effect**: Only changes what is currently rendered; past entries remain in the buffer unchanged
- **Visibility**: Targets set to `LevelFilter::Off` are hidden when `hide_target` is toggled via the `SPACE` key

## 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_target` calls
- **Key bindings**: **-** decreases and **+** increases the captured level (handled by `MinusKey` and `PlusKey` in [`src/widget/inner.rs`](https://github.com/gin66/tui-logger/blob/main/src/widget/inner.rs))
- **State variables**: Uses `opt_selected_recording_less` and `opt_selected_recording_more`
- **Effect**: Only messages meeting the captured level threshold are stored in the circular buffer
- **Persistence**: Setting to `LevelFilter::Off` stops 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`](https://github.com/gin66/tui-logger/blob/main/src/widget/target.rs)** calculates available filter levels using `advance_levelfilter`:

```rust
// 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`](https://github.com/gin66/tui-logger/blob/main/src/widget/inner.rs)** contains the `TuiWidgetInnerState::transition` method that processes key events:

SHOW filter adjustments update the widget configuration:

```rust
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:

```rust
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) within `LevelConfig`
- **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`:

```rust
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:

```rust
// 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`](https://github.com/gin66/tui-logger/blob/main/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 via `opt_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`](https://github.com/gin66/tui-logger/blob/main/src/widget/target.rs), [`src/widget/inner.rs`](https://github.com/gin66/tui-logger/blob/main/src/widget/inner.rs), and [`src/config/level_config.rs`](https://github.com/gin66/tui-logger/blob/main/src/config/level_config.rs)
- Both filters can be adjusted programmatically via `TuiWidgetState::transition` or `set_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`](https://github.com/gin66/tui-logger/blob/main/src/lib.rs) (lines 71-84) with explicit references to **CAPTURED** and **SHOWN** filters, and implemented in [`src/widget/inner.rs`](https://github.com/gin66/tui-logger/blob/main/src/widget/inner.rs) within the `TuiWidgetInnerState::transition` method that handles `LeftKey`, `RightKey`, `MinusKey`, and `PlusKey` events.