Interactive TUI
Fullscreen live tail with ratatui: 3 zones, filters, popups and per-IP actions
Interactive TUI
sentry tail has two modes (defined in
cli.rs,
dispatched in
cmd.rs):
sentry tail(orsentry tail --tui) → fullscreen interactive TUI withratatui+crossterm. Default mode when stdout is a TTY.sentry tail --stream→ non-interactive mode, one line per event. Automatically enabled when stdout is not a TTY (detected viastd::io::IsTerminal).
Both modes read events from Postgres — they require a config with
storage.postgres.url.
Fullscreen layout — 3 zones
The TUI polls the latest 500 events every 200 ms. The layout has 3 zones (illustrative mockup):
┌───────────────────────── Sentry — live ─────────────────────────┐
│ ▁▂▃▅▇▆▄▂▃▅ req/s 412 Info 9.8k Low 142 Med 31 │
│ [PAUSED] +12 novos filtro:"/admin" levels:High,Critical db: ok│
├──────────────────────────── Eventos ────────────────────────────┤
│ 14:02:11 critical 78 203.0.113.7 [nginx] POST /api/login │
│ 403 SQLi (+60) ' OR 1=1-- │
│ 14:02:09 high 35 198.51.100.4 [nginx] GET /.env 404 │
│ Sensitive (+25) │
├────────────────────── Agregados — janela ───────────────────────┤
│ Top IPs │ Top paths │ ASN/Geo │
│ 203.0.113.7 18 CRIT │ /admin 22 │ AS64512 41% │
│ 198.51.100.4 11 HIGH│ /.env 9 │ Tor 3% │
└─────────────────────────────────────────────────────────────────┘
[f]iltrar · [Enter] detalhe · [b] bloquear · [u] unblock · [c]
challenge · [i] info IP · [r] rotas · [Space] pausa · [q] sair- Header — req/s sparkline, per-level counters
(
Info/Low/Med/High/Crit) and a status line:[PAUSED]with backlog, active text filter, level filter and connection health (db: ok/db: ERRO). - Events — stream colored by level (time, level, score, IP, source, method, path, status and signal summary), with a selection cursor.
- Footer — aggregates over the visible window: Top IPs (with worst level), Top paths and ASN/Geo (with Tor %). Responsive: 3 columns at width ≥ 100, 2 columns ≥ 60, 1 column below that.
Shortcuts
| Key | Action |
|---|---|
j/↓, k/↑ | Move through the list (PageDown/PageUp jump 10). |
g/Home, G/End | Jump to top / bottom. |
f or / | Opens the text filter input (Enter applies, empty clears, Esc cancels). Case-insensitive substring over level, IP, source, verdict, path, ASN, country and event signals. |
Space | Pause/resume the stream; while paused the header shows [PAUSED] +N novos. |
Enter | Detail popup of the selected event. |
b | Block the selected event's IP (confirm with y/n; writes to ip_state + NOTIFY sentry_blocks_changed). |
u | Unblock the IP (removes the block and strikes). |
c | Cloudflare managed challenge for the IP (TTL 24h). |
i | Popup with IP info: blocked state, strikes, open incident and last 15 events. |
r | Popup with the known routes (up to 100). |
q/Esc | Quit (or close the open popup). |
Actions b/c respect the [real_ip] never-ban guard: trusted IPs get an
"action ignored" flash instead of being banned.
Event detail
In the popup opened with Enter: time, client ip:port → local port, geo
(ASN/country), request (method/path → status), risk (level/score/verdict/
source), the signal list with weight and detail, the protocol JSON
(truncated at 60 lines) and the raw log line. Scroll with j/k or
PageUp/PageDown; any other key closes it.
Stream mode
sentry tail --stream prints one line per event (plain or colored text
when stdout is a TTY), with the last 20 events on startup and a 1 s poll
after that. With --json, it emits JSONL with a stable key set:
timestamp, source, ip, server_port, asn, country, level,
score, verdict, method, path, status, signals. Ideal for piping
(| jq, | grep) and structured collection. Implementation in
tui/stream.rs.
Themes
--theme selects the theme (parsed in
tui/theme.rs):
dark(default) — light text for dark terminals.light— dark text for light-background terminals.mono— no color: bold/dim only (accessibility, colorless terminals).
Implementation
The tui/
module:
| File | Responsibility |
|---|---|
mod.rs | App, Postgres polling, popups (detail/filter/confirm), per-IP actions. |
agg.rs | Level (--only) and text filters, sparkline, Top IPs/paths, ASN/Geo, signal labels. |
stream.rs | --stream mode (text and JSONL). |
theme.rs | dark/light/mono themes. |