struct App {Show 26 fields
src: Source,
tab: Tab,
win: usize,
limit: usize,
filter: String,
filter_undo: String,
mode: Mode,
rows: Vec<Yaml>,
sel: usize,
names: Vec<Yaml>,
nsel: usize,
series: Vec<Yaml>,
ssel: usize,
on_series: bool,
trace: Option<Trace>,
frame: Option<FrameView>,
map: Option<MapView>,
alerts: Vec<Yaml>,
diag: Option<Yaml>,
psel: usize,
tail: bool,
scroll: usize,
stats: String,
status: String,
err: bool,
job: Option<Job>,
}Fields§
§src: Source§tab: Tab§win: usize§limit: usize§filter: String§filter_undo: StringThe filter as it was before / was pressed, so Esc can put it back.
mode: Mode§rows: Vec<Yaml>§sel: usize§names: Vec<Yaml>§nsel: usize§series: Vec<Yaml>§ssel: usize§on_series: boolWhich metrics pane the arrow keys drive.
trace: Option<Trace>§frame: Option<FrameView>The frame and map panes, and the one cursor they share — only one of the two is ever on screen, and both are lists of things Enter acts on.
map: Option<MapView>§alerts: Vec<Yaml>The alert list shares the same cursor: it is the third pane that is a list of things Enter acts on, and only one of the three is ever drawn.
diag: Option<Yaml>The whole /api/v1/stats document, rendered rather than destructured —
a field added to the endpoint should appear here without a code change.
psel: usize§tail: boolRe-run the list query on a timer instead of blocking on a key.
scroll: usize§stats: String§status: String§err: bool§job: Option<Job>Implementations§
Source§impl App
impl App
fn new(src: Source) -> App
fn reload(&mut self)
fn run(&mut self, job: Job, h: usize)
fn rows_query(&self) -> String
Sourcefn frame_query(&self) -> String
fn frame_query(&self) -> String
The same filter the list is showing, expanded into a frame.
traces then peers, in that order and not the other: traces measures
the real extent of what was found, and peers then reads the services
inside it. Reversed, peers runs against the window the rows happened to
land in and finds only what is already on screen.
No limit: a frame is bounded by the engine’s own entity and trace caps
and says so in truncated, which is a different question from how many
rows this pane can draw.
fn window_query(&self) -> String
fn series_query(&self) -> String
Sourcefn ignored_word(&self) -> Option<String>
fn ignored_word(&self) -> Option<String>
A word in the filter that this tab has nowhere to put.
Only metrics can produce one — every other tab reads a bare word as free text. The one thing that must not happen is silence: the filter bar goes on showing the word, so the rows look filtered when they are not.
fn terms(&self, j: &mut Json)
Sourcefn follow_pick(&mut self)
fn follow_pick(&mut self)
Enter, in the frame or map pane.
Everything in either pane is a link back into an ordinary query, which is what the algebra’s closure buys (section 7.3): there is nothing selectable here that lands the reader somewhere they cannot then filter.
Sourcefn follow_alert(&mut self)
fn follow_alert(&mut self)
Enter, on an alert: show the records the rule counted.
The rule’s where terms come back from the API already spelled in the
filter-bar grammar (alert::filter_of), so this is an assignment rather
than a translation — the alert and the query it fired on cannot drift
into two different filters, because there is only one spelling of them.
The window is left alone: over is how the rule counts, and a reader who
has just been paged usually wants more history than that, not less.
fn filter_key(&mut self, k: Key) -> bool
fn go(&mut self, tab: Tab)
Sourcefn move_by(&mut self, d: isize)
fn move_by(&mut self, d: isize)
Move whichever cursor the current pane owns.
One function rather than one per view because every view’s list is a selected index plus a length, and the clamping is the part that is easy to get wrong twice.
Clamped in usize, not isize. The scrolling panes report their length
as usize::MAX — see cursor — and that is a negative
isize, so an isize clamp reads its own upper bound as below its lower
bound and panics. j in the detail pane is the keystroke that did it.
fn move_to(&mut self, n: usize)
fn cursor(&self) -> (usize, usize)
fn set_cursor(&mut self, n: usize)
Sourcefn open_trace(&mut self)
fn open_trace(&mut self)
Follow whatever trace the selection points at.
This is the correlation story as one keystroke: a log line carries the
trace_id of the request that emitted it, a span carries its own, and a
metric exemplar carries the id of the request that produced the
measurement. Three different tabs, one key, because to the person
looking it is the same question.
fn selected(&self) -> Option<&Yaml>
fn frame(&mut self, w: usize, h: usize) -> Vec<String>
fn tabbar(&self, w: usize) -> String
fn filterbar(&self, w: usize) -> String
fn statusbar(&self, w: usize) -> String
fn hints(&self, w: usize) -> String
Sourcefn records(&self, w: usize, h: usize) -> Vec<String>
fn records(&self, w: usize, h: usize) -> Vec<String>
Logs and traces: a list on top, the selection’s detail below.
fn detail_full(&self, w: usize) -> Vec<String>
Sourcefn metrics(&self, w: usize, h: usize) -> Vec<String>
fn metrics(&self, w: usize, h: usize) -> Vec<String>
Metric names on the left, the selected name’s series on the right.
Sourcefn series_lines(&self, w: usize) -> Vec<String>
fn series_lines(&self, w: usize) -> Vec<String>
Three lines per series: its attributes, its sparkline, its exemplars.
Pre-rendered as plain strings and then windowed by the caller, because the vertical scroll is over series and each one is a fixed three rows.
Sourcefn frame_pane(&self, w: usize, h: usize) -> Vec<String>
fn frame_pane(&self, w: usize, h: usize) -> Vec<String>
The frame: the window it measured, the services in it, the traces in it.
Sourcefn map_pane(&self, w: usize, h: usize) -> Vec<String>
fn map_pane(&self, w: usize, h: usize) -> Vec<String>
The service map, as a call tree rooted at entry.
Sourcefn alerts_pane(&self, w: usize, h: usize) -> Vec<String>
fn alerts_pane(&self, w: usize, h: usize) -> Vec<String>
Every rule this node evaluates, firing or not.
Quiet rules are listed as prominently as loud ones. An alerting screen that shows only what is on fire cannot answer the question an operator actually has at 3am — “is the rule I wrote for this even running?” — and an empty screen then means both “all clear” and “nothing is watching”.
Sourcefn diag_pane(&self, w: usize) -> Vec<String>
fn diag_pane(&self, w: usize) -> Vec<String>
What this node counts about itself: /api/v1/stats, laid out.
Every number here is one the ingest path already keeps or the filesystem
already knows, so opening this pane costs a readdir and nothing else —
a diagnostics screen that perturbs what it measures is worse than none.
mmap residency is deliberately absent: mincore over a week of blocks
is thousands of syscalls per refresh, and the page cache is the OS’s to
report. ponytail: add it per-block behind an explicit key if a hit rate
ever turns out to be the question someone is actually asking.
fn waterfall(&self, w: usize, h: usize) -> Vec<String>
Auto Trait Implementations§
impl Freeze for App
impl RefUnwindSafe for App
impl Send for App
impl Sync for App
impl Unpin for App
impl UnsafeUnpin for App
impl UnwindSafe for App
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].