Merge branch 'feat/tui-rework'
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 32s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 31s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 10s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 27s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 28s
Supply chain / cargo-deny bans licenses sources (push) Successful in 8s
Supply chain / cargo-deny advisories (push) Successful in 9s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m7s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 32s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 31s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 10s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 27s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 28s
Supply chain / cargo-deny bans licenses sources (push) Successful in 8s
Supply chain / cargo-deny advisories (push) Successful in 9s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m7s
This commit is contained in:
3 files changed
+698
-887
No files matched your search
@@ -17,11 +17,15 @@ use crate::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
|
use crossterm::{
|
||||||
|
event::{self, Event, KeyCode, KeyEventKind, KeyModifiers},
|
||||||
|
terminal,
|
||||||
|
};
|
||||||
use irtt_client::managed::{
|
use irtt_client::managed::{
|
||||||
BlockingManagedClient, ManagedEndReason, ManagedEvent, ManagedEventSubscription,
|
BlockingManagedClient, ManagedEndReason, ManagedEvent, ManagedEventSubscription,
|
||||||
ManagedEventTryRecvError, TargetInstance,
|
ManagedEventTryRecvError, TargetInstance,
|
||||||
};
|
};
|
||||||
|
use ratatui::layout::Rect;
|
||||||
|
|
||||||
const RENDER_INTERVAL: Duration = Duration::from_millis(250);
|
const RENDER_INTERVAL: Duration = Duration::from_millis(250);
|
||||||
const TUI_WAIT_SLICE: Duration = Duration::from_millis(20);
|
const TUI_WAIT_SLICE: Duration = Duration::from_millis(20);
|
||||||
@@ -218,8 +222,13 @@ fn handle_input(state: &mut TuiState, shutdown_requested: &AtomicBool) -> io::Re
|
|||||||
if !event::poll(Duration::ZERO)? {
|
if !event::poll(Duration::ZERO)? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let Event::Key(key) = event::read()? else {
|
let key = match event::read()? {
|
||||||
continue;
|
Event::Key(key) => key,
|
||||||
|
Event::Resize(_, _) => {
|
||||||
|
force_render = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
};
|
};
|
||||||
if key.kind == KeyEventKind::Release {
|
if key.kind == KeyEventKind::Release {
|
||||||
continue;
|
continue;
|
||||||
@@ -234,59 +243,10 @@ fn handle_input(state: &mut TuiState, shutdown_requested: &AtomicBool) -> io::Re
|
|||||||
force_render = true;
|
force_render = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
KeyCode::Char('r') => {
|
_ => {
|
||||||
state.clear_visible_history();
|
let (width, height) = terminal::size()?;
|
||||||
force_render = true;
|
force_render |= state.handle_key(key.code, Rect::new(0, 0, width, height));
|
||||||
}
|
}
|
||||||
KeyCode::Char('p') => {
|
|
||||||
state.toggle_pause();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Char('g') => {
|
|
||||||
state.toggle_view();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Char('m') => {
|
|
||||||
state.cycle_graph_metric();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Left => {
|
|
||||||
state.pan_graph_left();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Right => {
|
|
||||||
state.pan_graph_right();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::PageUp => {
|
|
||||||
state.pan_graph_page_left();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::PageDown => {
|
|
||||||
state.pan_graph_page_right();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Home => {
|
|
||||||
state.jump_graph_oldest();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::End => {
|
|
||||||
state.jump_graph_live();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Char('+') | KeyCode::Char('=') => {
|
|
||||||
state.zoom_graph_in();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Char('-') => {
|
|
||||||
state.zoom_graph_out();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
KeyCode::Char('0') => {
|
|
||||||
state.reset_graph_window();
|
|
||||||
force_render = true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(force_render)
|
Ok(force_render)
|
||||||
|
|||||||
+628
-821
File diff suppressed because it is too large.
Load diff
+55
-11
@@ -31,21 +31,65 @@ a finite run:
|
|||||||
irtt-tui <server> --duration 30s
|
irtt-tui <server> --duration 30s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## DASHBOARD
|
||||||
|
|
||||||
|
One dashboard is used for every target count and terminal size. It shows:
|
||||||
|
|
||||||
|
- Run status, elapsed time, and finite duration or continuous mode.
|
||||||
|
- The selected target's label and remote address, plus latest signed
|
||||||
|
client-to-server and server-to-client delays (`-` means unavailable).
|
||||||
|
- Target rows with latest effective RTT, cumulative loss percentage, jitter
|
||||||
|
(standard deviation of round-trip IPDV), and age of the last primary reply.
|
||||||
|
- A graph overlaying all targets, with matching target colors and a visible
|
||||||
|
live/history indicator and window size.
|
||||||
|
|
||||||
|
An active session with no primary replies shows `waiting`. Reply age makes a
|
||||||
|
stale RTT distinguishable from a fresh measurement. Loss follows the shared
|
||||||
|
statistics collector: outstanding sends can temporarily contribute to the
|
||||||
|
cumulative loss estimate. Jitter is `-` until an IPDV pair is available.
|
||||||
|
|
||||||
|
`Tab` / `Shift-Tab` selects a target, bringing its row into view when necessary.
|
||||||
|
Up to six target rows are shown; smaller terminals show fewer. Selecting a target
|
||||||
|
changes the identification, one-way summary and details; the graph continues to
|
||||||
|
compare every target.
|
||||||
|
|
||||||
|
`d` opens a details sheet in the graph's space. It contains the selected target's
|
||||||
|
session and negotiation, packet counters, progress, latest timing sample, full
|
||||||
|
timing statistics, warnings, and recent events from all targets. Scroll it with
|
||||||
|
the arrows or page keys. Long lines and timing columns can be read with horizontal
|
||||||
|
scrolling, including full labels and remote addresses that do not fit in the
|
||||||
|
header. `d` or `Esc` returns to the graph, preserving its metric and viewport.
|
||||||
|
The former large/compact Dashboard screens have been replaced by this sheet;
|
||||||
|
`g` remains an alias for `d`.
|
||||||
|
|
||||||
|
The minimum terminal size is 56 columns by 18 rows. Below that size the UI asks
|
||||||
|
for a resize and continues acquiring measurements. Resize and important status
|
||||||
|
redraws still work while the display is paused.
|
||||||
|
|
||||||
## CONTROLS
|
## CONTROLS
|
||||||
|
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `q`, `Ctrl-C` | Quit |
|
| `q`, `Ctrl-C` | Quit |
|
||||||
| `p` | Toggle display pause (probing continues; only redraws stop) |
|
| `p` | Toggle display pause (probing and acquisition continue) |
|
||||||
| `g` | Toggle Graph / Dashboard view |
|
| `Tab` / `Shift-Tab` | Select next / previous target |
|
||||||
| `m` | Cycle graph metric |
|
| `d`, `g` | Toggle target details |
|
||||||
| `r` | Clear visible graph history |
|
| `Esc` | Close target details |
|
||||||
| `←` / `→` | Pan graph |
|
| `r` | Clear graph history for all targets; keep latest samples and statistics |
|
||||||
| `PageUp` / `PageDown` | Page-pan graph |
|
| `m` | Cycle graph metric (graph visible) |
|
||||||
| `Home` / `End` | Jump to oldest / jump to live |
|
| `←` / `→` | Pan graph; scroll columns in details |
|
||||||
| `+` / `=` | Zoom graph in |
|
| `↑` / `↓` | Scroll details |
|
||||||
| `-` | Zoom graph out |
|
| `PageUp` / `PageDown` | Page-pan graph; page-scroll details |
|
||||||
| `0` | Reset graph window and zoom |
|
| `Home` / `End` | Oldest / live graph; top / bottom of details |
|
||||||
|
| `+` / `=` | Zoom graph in (graph visible) |
|
||||||
|
| `-` | Zoom graph out (graph visible) |
|
||||||
|
| `0` | Reset graph window and zoom, keeping live/history position (graph visible) |
|
||||||
|
|
||||||
|
The six graph metrics are effective RTT, raw RTT, adjusted RTT,
|
||||||
|
client-to-server delay, server-to-client delay, and server processing time.
|
||||||
|
Signed effective/adjusted RTT and one-way values are preserved. Graph windows
|
||||||
|
range from 5 seconds to one hour and default to one minute. The footer shows
|
||||||
|
controls appropriate to the currently open graph or details sheet.
|
||||||
|
|
||||||
## RETAINED HISTORY
|
## RETAINED HISTORY
|
||||||
|
|
||||||
@@ -55,7 +99,7 @@ retention described in `irtt-client(1)`:
|
|||||||
- Up to 100,000 graph samples per target.
|
- Up to 100,000 graph samples per target.
|
||||||
- Up to 80 recent status/log messages.
|
- Up to 80 recent status/log messages.
|
||||||
|
|
||||||
`r` clears the currently visible graph history and returns the viewport to
|
`r` clears graph history for all targets and returns the viewport to
|
||||||
live; it does not change the 100,000-sample cap itself. These are
|
live; it does not change the 100,000-sample cap itself. These are
|
||||||
presentation bounds on top of the client's own statistics retention (see
|
presentation bounds on top of the client's own statistics retention (see
|
||||||
`irtt-client(1)` MEASUREMENTS AND MEMORY) — a long continuous TUI session's
|
`irtt-client(1)` MEASUREMENTS AND MEMORY) — a long continuous TUI session's
|
||||||
|
|||||||
Reference in new issue
Block a user